~sircmpwn/xrgears

ref: f162555056b018a3805f96df49158518ec63f94c xrgears/vitamin-k/scene/vikSkyBox.hpp -rw-r--r-- 4.6 KiB
f1625550 — Lubosz Sarnecki vik: Use struct and array initializers. 2 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
131
132
133
134
135
/*
 * vitamin-k
 *
 * Copyright 2016 Sascha Willems - www.saschawillems.de
 * Copyright 2017-2018 Collabora Ltd.
 *
 * Authors: Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
 * SPDX-License-Identifier: MIT
 */

#pragma once

#include <vector>
#include <string>

#include "../render/vikTexture.hpp"
#include "../render/vikModel.hpp"

#include "../system/vikAssets.hpp"
#include "../render/vikShader.hpp"

namespace vik {
class SkyBox {
 private:
  TextureCubeMap cube_map;
  VkDescriptorSet descriptor_set;
  VkDevice device;
  VkDescriptorImageInfo texture_descriptor;
  Model model;
  VkPipeline pipeline;

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

  ~SkyBox() {
    cube_map.destroy();
    model.destroy();
    vkDestroyPipeline(device, pipeline, nullptr);
  }

  void init_texture_descriptor() {
    // Image descriptor for the cube map texture
    texture_descriptor = {
      .sampler = cube_map.sampler,
      .imageView = cube_map.view,
      .imageLayout = cube_map.imageLayout
    };
  }

  VkWriteDescriptorSet
  get_cube_map_write_descriptor_set(unsigned binding, VkDescriptorSet ds) {
    return  (VkWriteDescriptorSet) {
      .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
      .dstSet = ds,
      .dstBinding = binding,
      .descriptorCount = 1,
      .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
      .pImageInfo = &texture_descriptor
    };
  }

  void load_assets(VertexLayout vertexLayout, Device *vik_device, VkQueue queue,
                   const std::string& file_name, VkFormat format) {
    model.loadFromFile(vik::Assets::get_asset_path() + "models/cube.obj",
                       vertexLayout, 10.0f, vik_device, queue);
    cube_map.loadFromFile(file_name, format, vik_device, queue);
    init_texture_descriptor();
  }

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

    std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
      (VkWriteDescriptorSet){
        .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
        .dstSet = descriptor_set,
        .dstBinding = 2,
        .descriptorCount = 1,
        .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
        .pBufferInfo = cameraDescriptor
      },
      get_cube_map_write_descriptor_set(3, descriptor_set)
    };
    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, &descriptor_set, 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 init_pipeline(VkGraphicsPipelineCreateInfo* pipeline_info,
                     const VkPipelineCache& pipeline_cache) {
    VkPipelineRasterizationStateCreateInfo rasterization_state = {
      .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
      .depthClampEnable = VK_FALSE,
      .polygonMode = VK_POLYGON_MODE_FILL,
      .cullMode = VK_CULL_MODE_BACK_BIT,
      .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
      .lineWidth = 1.0f
    };

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

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

    pipeline_info->stageCount = shader_stages.size();
    pipeline_info->pStages = shader_stages.data();
    pipeline_info->pRasterizationState = &rasterization_state;

    vik_log_check(vkCreateGraphicsPipelines(device, pipeline_cache, 1,
                                            pipeline_info, nullptr, &pipeline));

    vkDestroyShaderModule(device, shader_stages[0].module, nullptr);
    vkDestroyShaderModule(device, shader_stages[1].module, nullptr);
    vkDestroyShaderModule(device, shader_stages[2].module, nullptr);
  }
};
}  // namespace vik