~sircmpwn/xrgears

ref: c4afd33e13398688fc03f60ef3d0a498bf40bfdd xrgears/vitamin-k/VikSkyBox.hpp -rw-r--r-- 4.6 KiB
c4afd33e — Lubosz Sarnecki add new abstract classes for interfaces between vks and vkc. 4 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * XRGears
 *
 * Copyright (C) 2016 Sascha Willems - www.saschawillems.de
 * Copyright (C) 2017 Lubosz Sarnecki <lubosz.sarnecki@collabora.co.uk>
 *
 * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 *
 * Based on Vulkan Examples written by Sascha Willems
 */

#pragma once

#include <vector>

#include "../vks/vksTexture.hpp"
#include "../vks/vksModel.hpp"

#include "VikAssets.hpp"
#include "VikShader.hpp"
#include "VikBuffer.hpp"

class VikSkyBox {
 private:
  vks::TextureCubeMap cubeMap;
  VkDescriptorSet descriptorSet;
  VkDevice device;
  VkDescriptorImageInfo textureDescriptor;
  vks::Model model;
  VkPipeline pipeline;

 public:
  explicit VikSkyBox(VkDevice device) : device(device) {}

  ~VikSkyBox() {
    cubeMap.destroy();
    model.destroy();
    vkDestroyPipeline(device, pipeline, nullptr);
  }

  void initTextureDescriptor() {
    // Image descriptor for the cube map texture
    textureDescriptor =
        vks::initializers::descriptorImageInfo(
          cubeMap.sampler,
          cubeMap.view,
          cubeMap.imageLayout);
  }

  VkWriteDescriptorSet getCubeMapWriteDescriptorSet(unsigned binding, VkDescriptorSet ds) {
    return vks::initializers::writeDescriptorSet(
          ds,
          VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
          binding,
          &textureDescriptor);
  }

  void loadAssets(vks::VertexLayout vertexLayout, vks::Device *vulkanDevice, VkQueue queue) {
    // Skybox
    model.loadFromFile(VikAssets::getAssetPath() + "models/cube.obj", vertexLayout, 10.0f, vulkanDevice, queue);
    cubeMap.loadFromFile(
          VikAssets::getTexturePath() + "cubemap_yokohama_bc3_unorm.ktx", VK_FORMAT_BC2_UNORM_BLOCK,
          // VikAssets::getTexturePath() + "equirect/cube2/cube.ktx", VK_FORMAT_R16G16B16A16_SFLOAT,
          // VikAssets::getTexturePath() + "hdr/pisa_cube.ktx", VK_FORMAT_R16G16B16A16_SFLOAT,
          // VikAssets::getAssetPath() + "textures/cubemap_space.ktx", VK_FORMAT_R8G8B8A8_UNORM,
          vulkanDevice,
          queue);
    initTextureDescriptor();
  }

  void createDescriptorSet(const VkDescriptorSetAllocateInfo& allocInfo,
                           VkDescriptorBufferInfo* cameraDescriptor) {
    vik_log_check(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));

    std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
      vks::initializers::writeDescriptorSet(
      descriptorSet,
      VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
      2,
      cameraDescriptor)
    };

    writeDescriptorSets.push_back(getCubeMapWriteDescriptorSet(3, descriptorSet));

    vkUpdateDescriptorSets(device,
                           static_cast<uint32_t>(writeDescriptorSets.size()),
                           writeDescriptorSets.data(),
                           0,
                           nullptr);
  }

  void draw(VkCommandBuffer cmdbuffer, VkPipelineLayout pipelineLayout) {
    VkDeviceSize offsets[1] = { 0 };

    vkCmdBindDescriptorSets(cmdbuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
    vkCmdBindVertexBuffers(cmdbuffer, 0, 1, &model.vertices.buffer, offsets);
    vkCmdBindIndexBuffer(cmdbuffer, model.indices.buffer, 0, VK_INDEX_TYPE_UINT32);

    vkCmdBindPipeline(cmdbuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);

    vkCmdDrawIndexed(cmdbuffer, model.indexCount, 1, 0, 0, 0);
  }

  void createPipeline(VkGraphicsPipelineCreateInfo* pipelineCreateInfo,
                      const VkPipelineCache& pipelineCache) {
    VkPipelineRasterizationStateCreateInfo rasterizationStateSky =
        vks::initializers::pipelineRasterizationStateCreateInfo(
          VK_POLYGON_MODE_FILL,
          VK_CULL_MODE_BACK_BIT,
          VK_FRONT_FACE_COUNTER_CLOCKWISE,
          0);

    // Skybox pipeline (background cube)
    std::array<VkPipelineShaderStageCreateInfo, 3> shaderStagesSky;

    shaderStagesSky[0] = VikShader::load(device, "xrgears/sky.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
    shaderStagesSky[1] = VikShader::load(device, "xrgears/sky.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
    shaderStagesSky[2] = VikShader::load(device, "xrgears/sky.geom.spv", VK_SHADER_STAGE_GEOMETRY_BIT);

    pipelineCreateInfo->stageCount = shaderStagesSky.size();
    pipelineCreateInfo->pStages = shaderStagesSky.data();
    pipelineCreateInfo->pRasterizationState = &rasterizationStateSky;

    vik_log_check(vkCreateGraphicsPipelines(device, pipelineCache, 1, pipelineCreateInfo, nullptr, &pipeline));

    vkDestroyShaderModule(device, shaderStagesSky[0].module, nullptr);
    vkDestroyShaderModule(device, shaderStagesSky[1].module, nullptr);
    vkDestroyShaderModule(device, shaderStagesSky[2].module, nullptr);
  }
};