first_app.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #include "first_app.h"
  2. #include "render_system.h"
  3. #include "point_light_system.h"
  4. #include "skybox_system.h"
  5. #include "coral_camera.h"
  6. #include "coral_buffer.h"
  7. #include "vk_initializers.h"
  8. // STD
  9. #include <chrono>
  10. #include <iostream>
  11. // IMGUI
  12. #include "imgui.h"
  13. #include "imgui_impl_vulkan.h"
  14. #include "imgui_impl_glfw.h"
  15. using namespace coral_3d;
  16. first_app::first_app()
  17. : cubemap_{device_, true}
  18. {
  19. init_imgui();
  20. descriptor_pool_ = coral_descriptor_pool::Builder(device_)
  21. .set_max_sets(MAX_MATERIAL_SETS)
  22. .add_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, coral_swapchain::MAX_FRAMES_IN_FLIGHT)
  23. .add_pool_size(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_MATERIAL_SETS)
  24. .build();
  25. input.add_callback(GLFW_KEY_B,
  26. coral_input::Callback(GLFW_PRESS, [&](){
  27. show_cursor_ = !show_cursor_;
  28. glfwSetInputMode(window_.get_glfw_window(), GLFW_CURSOR,
  29. show_cursor_ ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED);
  30. }));
  31. }
  32. void first_app::run()
  33. {
  34. // Create buffer that is mapped to the global descriptor
  35. coral_buffer global_ubo
  36. {
  37. device_,
  38. sizeof(GlobalUBO),
  39. coral_swapchain::MAX_FRAMES_IN_FLIGHT,
  40. VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
  41. VMA_MEMORY_USAGE_CPU_ONLY,
  42. 0,
  43. device_.properties.limits.minUniformBufferOffsetAlignment
  44. };
  45. global_ubo.map();
  46. // Set 0: Global descriptor set (Scene data)
  47. global_set_layout_ = coral_descriptor_set_layout::Builder(device_)
  48. .add_binding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
  49. .add_binding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT)
  50. .build();
  51. // Set 1: Material descriptor set
  52. auto material_set_layout = coral_descriptor_set_layout::Builder(device_)
  53. .add_binding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT)
  54. .add_binding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT)
  55. .add_binding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT)
  56. .add_binding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT)
  57. .build();
  58. // Combined descriptor set layouts
  59. std::vector<VkDescriptorSetLayout> desc_set_layouts
  60. {
  61. global_set_layout_->get_descriptor_set_layout(),
  62. material_set_layout->get_descriptor_set_layout()
  63. };
  64. // RENDER SYSTEM
  65. render_system render_system{device_, desc_set_layouts};
  66. load_gameobjects(*material_set_layout, render_system.pipeline_layout(), global_ubo);
  67. // POINT LIGHT SYSTEM
  68. desc_set_layouts.pop_back();
  69. point_light_system point_light_system{device_, renderer_.get_swapchain_render_pass(), desc_set_layouts};
  70. // SKYBOX SYSTEM
  71. skybox_system skybox_system{device_, renderer_.get_swapchain_render_pass(), desc_set_layouts};
  72. // CAMERA
  73. coral_camera camera{ {0.f, 0.f, 3.f} };
  74. camera.set_view_direction(camera.get_position(), {0.f, 0.f, -1.f});
  75. auto last_time{ std::chrono::high_resolution_clock::now() };
  76. while (!window_.should_close())
  77. {
  78. // UPDATE INPUT
  79. glfwPollEvents();
  80. auto current_time{ std::chrono::high_resolution_clock::now() };
  81. auto frame_time{ std::chrono::duration<float, std::chrono::seconds::period>(current_time - last_time).count() };
  82. last_time = current_time;
  83. // MOVE CAMERA
  84. if(!show_cursor_)
  85. {
  86. camera.update_input(window_.get_glfw_window(), frame_time);
  87. }
  88. float aspect{ renderer_.get_aspect_ratio() };
  89. camera.set_perspective_projection(glm::radians(60.f), aspect, 0.1f, 1000.f);
  90. // IMGUI FRAME
  91. ImGui_ImplVulkan_NewFrame();
  92. ImGui_ImplGlfw_NewFrame();
  93. ImGui::NewFrame();
  94. if (auto command_buffer = renderer_.begin_frame())
  95. {
  96. const int frame_index{ renderer_.get_frame_index() };
  97. auto& obj = gameobjects_.at(0);
  98. FrameInfo frame_info
  99. {
  100. frame_index,
  101. frame_time,
  102. command_buffer,
  103. camera,
  104. global_descriptor_sets_[frame_index],
  105. gameobjects_
  106. };
  107. // UPDATE
  108. GlobalUBO ubo{};
  109. ubo.view = camera.get_view();
  110. ubo.view_inverse = glm::inverse(camera.get_view());
  111. ubo.view_projection = camera.get_projection() * camera.get_view();
  112. point_light_system.update(frame_info, ubo);
  113. global_ubo.write_to_index(&ubo, frame_index);
  114. global_ubo.flush_index(frame_index);
  115. // RENDER
  116. renderer_.begin_swapchain_render_pass(command_buffer);
  117. // IMGUI
  118. ImGui::Render();
  119. skybox_system.render(frame_info);
  120. render_system.render_gameobjects(frame_info);
  121. point_light_system.render(frame_info);
  122. ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), command_buffer);
  123. renderer_.end_swapchain_render_pass(command_buffer);
  124. renderer_.end_frame();
  125. }
  126. }
  127. vkDeviceWaitIdle(device_.device());
  128. }
  129. void first_app::load_gameobjects(coral_descriptor_set_layout& material_set_layout, VkPipelineLayout pipeline_layout,
  130. coral_buffer& global_ubo)
  131. {
  132. // GAMEOBJECTS
  133. auto sponza_scene{std::make_shared<coral_gameobject>(coral_gameobject::create_gameobject()) };
  134. // MESHES
  135. std::shared_ptr<coral_mesh> sponza_mesh
  136. {
  137. coral_mesh::create_mesh_from_file(device_,"assets/meshes/SciFiHelmet/SciFiHelmet.gltf", sponza_scene.get())
  138. };
  139. // CREATE MESH MATERIALS AND PIPELINES
  140. sponza_mesh->load_materials(material_set_layout, *descriptor_pool_);
  141. sponza_mesh->create_pipelines(
  142. "assets/shaders/simple_shader.vert.spv",
  143. "assets/shaders/simple_shader.frag.spv",
  144. renderer_.get_swapchain_render_pass(),
  145. pipeline_layout);
  146. sponza_scene->mesh_ = sponza_mesh;
  147. sponza_scene->transform_.translation = glm::vec3(0.f, 0.f, 0.f);
  148. gameobjects_.emplace(sponza_scene->get_id(), sponza_scene);
  149. // LIGHTS
  150. auto point_light = std::make_shared<coral_gameobject>(coral_gameobject::create_point_light(1.f, 0.1f, {1.f, 0.2f, 0.2f}));
  151. point_light->transform_.translation = glm::vec3(-4.f, 0.f, 0.f);
  152. gameobjects_.emplace(point_light->get_id(), point_light);
  153. point_light = std::make_shared<coral_gameobject>(coral_gameobject::create_point_light(1.f, 0.1f, {0.2f, 1.f, 0.2f}));
  154. point_light->transform_.translation = glm::vec3(-2.f, 0.f, 0.f);
  155. gameobjects_.emplace(point_light->get_id(), point_light);
  156. point_light = std::make_shared<coral_gameobject>(coral_gameobject::create_point_light(1.f));
  157. point_light->transform_.translation = glm::vec3(0.f, 0.f, 0.f);
  158. gameobjects_.emplace(point_light->get_id(), point_light);
  159. point_light = std::make_shared<coral_gameobject>(coral_gameobject::create_point_light(1.f, 0.1f, {0.2f, 0.2f, 1.f}));
  160. point_light->transform_.translation = glm::vec3(2.f, 0.f, 0.f);
  161. gameobjects_.emplace(point_light->get_id(), point_light);
  162. point_light = std::make_shared<coral_gameobject>(coral_gameobject::create_point_light(1.f, 0.1f, {1.f, 0.2f, 1.f}));
  163. point_light->transform_.translation = glm::vec3(4.f, 0.f, 0.f);
  164. gameobjects_.emplace(point_light->get_id(), point_light);
  165. // SKYBOX
  166. std::vector<std::string> file_names
  167. {
  168. "assets/textures/cubemap/posx.jpg",
  169. "assets/textures/cubemap/negx.jpg",
  170. "assets/textures/cubemap/negy.jpg",
  171. "assets/textures/cubemap/posy.jpg",
  172. "assets/textures/cubemap/posz.jpg",
  173. "assets/textures/cubemap/negz.jpg"
  174. };
  175. cubemap_.init(file_names,true, true);
  176. // Write global UBO
  177. for (size_t i = 0; i < global_descriptor_sets_.size(); i++)
  178. {
  179. auto buffer_info = global_ubo.descriptor_info_index(i);
  180. auto skybox_info = cubemap_.get_descriptor_image_info();
  181. coral_descriptor_writer(*global_set_layout_, *descriptor_pool_)
  182. .write_buffer(0, &buffer_info)
  183. .write_image(1, &skybox_info)
  184. .build(global_descriptor_sets_[i]);
  185. }
  186. }
  187. void first_app::init_imgui()
  188. {
  189. // Create descriptor pool for IMGUI
  190. imgui_pool_ = coral_descriptor_pool::Builder(device_)
  191. .set_max_sets(MAX_MATERIAL_SETS)
  192. .add_pool_size(VK_DESCRIPTOR_TYPE_SAMPLER, 1000)
  193. .add_pool_size(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000)
  194. .add_pool_size(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000)
  195. .add_pool_size(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000)
  196. .add_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000)
  197. .add_pool_size(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000)
  198. .add_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000)
  199. .add_pool_size(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000)
  200. .add_pool_size(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000)
  201. .add_pool_size(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000)
  202. .add_pool_size(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000)
  203. .build();
  204. // Initialize ImGui
  205. ImGui::CreateContext();
  206. // Initialize ImGui for GLFW
  207. ImGui_ImplGlfw_InitForVulkan(window_.get_glfw_window(), true);
  208. // Initialize ImGui for Vulkan
  209. ImGui_ImplVulkan_InitInfo init_info = {};
  210. init_info.Instance = device_.instance();
  211. init_info.PhysicalDevice = device_.physical_device();
  212. init_info.Device = device_.device();
  213. init_info.Queue = device_.graphics_queue();
  214. init_info.DescriptorPool = imgui_pool_->pool();
  215. init_info.MinImageCount = 3;
  216. init_info.ImageCount = 3;
  217. init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
  218. ImGui_ImplVulkan_Init(&init_info, renderer_.get_swapchain_render_pass());
  219. // Execute GPU command to upload font textures
  220. device_.immediate_submit([&](VkCommandBuffer cmd){
  221. ImGui_ImplVulkan_CreateFontsTexture(cmd);
  222. });
  223. // Delete font textures from the CPU
  224. ImGui_ImplVulkan_DestroyFontUploadObjects();
  225. device_.deletion_queue().deletors.emplace_back([=](){
  226. ImGui_ImplVulkan_Shutdown();
  227. });
  228. }