From 3dd870b001bef62aaa501257352d968d1346c7f2 Mon Sep 17 00:00:00 2001 From: ladevieq Date: Sun, 25 Jul 2021 11:58:01 +0200 Subject: Use a different buffer for scene info, geometry, bvh and load gltf --- src/CMakeLists.txt | 4 ++ src/gltf.cpp | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 56 ++++++++++++++++------------ src/scene.cpp | 53 ++++++++++++++++++-------- src/vk-renderer.cpp | 28 ++++++++++++-- 5 files changed, 202 insertions(+), 43 deletions(-) create mode 100644 src/gltf.cpp (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b2b34b6..b871d67 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,5 @@ +find_package(nlohmann_json CONFIG REQUIRED) + add_definitions(-DNOMINMAX -D_USE_MATH_DEFINES) include_directories(${CMAKE_SOURCE_DIR}/include) @@ -22,6 +24,7 @@ add_executable( vk-api.cpp window.cpp scene.cpp + gltf.cpp ) if(UNIX AND NOT APPLE) @@ -29,3 +32,4 @@ if(UNIX AND NOT APPLE) endif() target_link_libraries(path-tracer PRIVATE ${LIBRARIES}) +target_link_libraries(path-tracer PRIVATE nlohmann_json nlohmann_json::nlohmann_json) diff --git a/src/gltf.cpp b/src/gltf.cpp new file mode 100644 index 0000000..0e74aaf --- /dev/null +++ b/src/gltf.cpp @@ -0,0 +1,104 @@ +#include "gltf.hpp" + +#include +#include + +#include "utils.hpp" + +mesh gltf::load(std::filesystem::path &path, std::string &filename) { + std::fstream f(path / filename); + json gltf_json; + + f >> gltf_json; + + auto scene_index = gltf_json["scene"].get(); + auto scenes = gltf_json["scenes"]; + auto scene = scenes[scene_index]; + + auto buffers = gltf_json["buffers"]; + auto buffer_index = 0; + auto buffers_content = std::vector>(buffers.size()); + for (auto &buffer: buffers) { + auto buffer_path = (path / buffer["uri"].get()).string(); + buffers_content[buffer_index] = read_file(buffer_path); + buffer_index++; + } + + auto nodes = gltf_json["nodes"]; + auto gltf_mesh = mesh(); + + for (auto &node: nodes) { + gltf_mesh.nodes.push_back(std::vector()); + load_node(gltf_json, node, buffers_content, gltf_mesh); + } + + // return std::move(gltf_mesh); + return gltf_mesh; +} + +void gltf::load_node(json &gltf_json, json &node, std::vector> &buffers_content, mesh& gltf_mesh) { + auto mesh_index = node["mesh"].get(); + auto mesh = gltf_json["meshes"][mesh_index]; + auto primitives = mesh["primitives"]; + + for (auto &primitive: primitives) { + gltf_mesh.nodes.back().push_back(mesh_part()); + load_primitive(gltf_json, primitive, buffers_content, gltf_mesh); + } +} + +void gltf::load_primitive(json &gltf_json, json &primitive, std::vector> &buffers_content, mesh& gltf_mesh) { + auto accessors = gltf_json["accessors"]; + auto &mesh_part = gltf_mesh.nodes.back().back(); + + { + auto indices_accessor_index = primitive["indices"].get(); + auto indices_view_index = accessors[indices_accessor_index]["bufferView"].get(); + auto indices_view = gltf_json["bufferViews"][indices_view_index]; + + auto indices_buffer_index = indices_view["buffer"].get(); + auto indices_offset = indices_view["byteOffset"].get(); + auto indices_length = indices_view["byteLength"].get(); + + auto indices_buffer = buffers_content[indices_buffer_index]; + void* indices_start = indices_buffer.data() + indices_offset; + + mesh_part.indices.resize(indices_length / sizeof(uint16_t)); + + std::memcpy(mesh_part.indices.data(), indices_start, indices_length); + } + + { + auto positions_accessor_index = primitive["attributes"]["POSITION"].get(); + auto positions_view_index = accessors[positions_accessor_index]["bufferView"].get(); + auto positions_view = gltf_json["bufferViews"][positions_view_index]; + + auto positions_buffer_index = positions_view["buffer"].get(); + auto positions_offset = positions_view["byteOffset"].get(); + auto positions_length = positions_view["byteLength"].get(); + + auto positions_buffer = buffers_content[positions_buffer_index]; + void* positions_start = positions_buffer.data() + positions_offset; + + mesh_part.positions.resize(positions_length / (sizeof(float) * 3)); + + std::memcpy(mesh_part.positions.data(), positions_start, positions_length); + } + + { + auto normals_accessor_index = primitive["attributes"]["NORMAL"].get(); + auto normals_view_index = accessors[normals_accessor_index]["bufferView"].get(); + auto normals_view = gltf_json["bufferViews"][normals_view_index]; + + auto normals_buffer_index = normals_view["buffer"].get(); + auto normals_offset = normals_view["byteOffset"].get(); + auto normals_length = normals_view["byteLength"].get(); + + auto normals_buffer = buffers_content[normals_buffer_index]; + void* normals_start = normals_buffer.data() + normals_offset; + + mesh_part.normals.resize(normals_length / (sizeof(float) * 3)); + + std::memcpy(mesh_part.normals.data(), normals_start, normals_length); + } +} diff --git a/src/main.cpp b/src/main.cpp index 3678f2a..875527f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,12 +54,22 @@ int main() { uint64_t frame_count = 0; auto start = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now(); - auto main_scene = scene(width, height); + + point3 position = { 13.0, 2.0, 3.0 }; + point3 target = { 0.0, 0.0, 0.0 }; + auto v_fov = 20; + auto aperture = 0.1; + auto focus_distance = 10; + auto cam = camera(position, target, v_fov, (float)width / (float)height, aperture, focus_distance); + auto main_scene = scene(cam, width, height); auto can_render = true; - vkrenderer renderer { wnd, sizeof(main_scene) }; + // vkrenderer renderer { wnd, sizeof(main_scene.meta), sizeof(main_scene.triangles[0]) * main_scene.triangles.size(), sizeof(main_scene.nodes[0]) * main_scene.nodes.size() }; + vkrenderer renderer { wnd, sizeof(main_scene.meta), sizeof(main_scene.spheres[0]) * main_scene.spheres.size(), sizeof(main_scene.nodes[0]) * main_scene.nodes.size() }; - // Upload scene - std::memcpy(renderer.scene_buffer_ptr(), &main_scene, sizeof(main_scene)); + // Upload scene content + std::memcpy(renderer.scene_buffer_ptr(), &main_scene.meta, sizeof(main_scene.meta)); + std::memcpy(renderer.geometry_buffer_ptr(), main_scene.spheres.data(), sizeof(main_scene.spheres[0]) * main_scene.spheres.size()); + std::memcpy(renderer.bvh_buffer_ptr(), main_scene.nodes.data(), sizeof(main_scene.nodes[0]) * main_scene.nodes.size()); ImGuiIO& io = ImGui::GetIO(); io.DisplaySize.x = (float)width; @@ -85,8 +95,8 @@ int main() { width = event.width; height = event.height; - ((scene*) renderer.scene_buffer_ptr())->width = width; - ((scene*) renderer.scene_buffer_ptr())->height = height; + ((scene*) renderer.scene_buffer_ptr())->meta.width = width; + ((scene*) renderer.scene_buffer_ptr())->meta.height = height; io.DisplaySize.x = (float)width; io.DisplaySize.y = (float)height; @@ -96,8 +106,8 @@ int main() { } else { can_render = true; renderer.recreate_swapchain(); - ((scene*) renderer.scene_buffer_ptr())->cam.set_aspect_ratio((float)event.width / (float)event.height); - ((scene*) renderer.scene_buffer_ptr())->sample_index = 0; + ((scene*) renderer.scene_buffer_ptr())->meta.cam.set_aspect_ratio((float)event.width / (float)event.height); + ((scene*) renderer.scene_buffer_ptr())->meta.sample_index = 0; } reset_accumulation = true; @@ -114,44 +124,44 @@ int main() { switch (event.key) { case KEYS::W: { - move_vec = ((scene*) renderer.scene_buffer_ptr())->cam.forward.unit() * move_speed; + move_vec = ((scene*) renderer.scene_buffer_ptr())->meta.cam.forward.unit() * move_speed; break; } case KEYS::S: { - move_vec = -((scene*) renderer.scene_buffer_ptr())->cam.forward.unit() * move_speed; + move_vec = -((scene*) renderer.scene_buffer_ptr())->meta.cam.forward.unit() * move_speed; break; } case KEYS::D: { - move_vec = ((scene*) renderer.scene_buffer_ptr())->cam.right.unit() * move_speed; + move_vec = ((scene*) renderer.scene_buffer_ptr())->meta.cam.right.unit() * move_speed; break; } case KEYS::A: { - move_vec = -((scene*) renderer.scene_buffer_ptr())->cam.right.unit() * move_speed; + move_vec = -((scene*) renderer.scene_buffer_ptr())->meta.cam.right.unit() * move_speed; break; } case KEYS::E: { - ((scene*) renderer.scene_buffer_ptr())->cam.rotate_y(0.001f * delta_time); + ((scene*) renderer.scene_buffer_ptr())->meta.cam.rotate_y(0.001f * delta_time); reset_accumulation = true; break; } case KEYS::Q: { - ((scene*) renderer.scene_buffer_ptr())->cam.rotate_y(-0.001f * delta_time); + ((scene*) renderer.scene_buffer_ptr())->meta.cam.rotate_y(-0.001f * delta_time); reset_accumulation = true; break; } case KEYS::SPACE: { - move_vec = ((scene*) renderer.scene_buffer_ptr())->cam.up.unit() * move_speed; + move_vec = ((scene*) renderer.scene_buffer_ptr())->meta.cam.up.unit() * move_speed; break; } case KEYS::CTRL: { - move_vec = -((scene*) renderer.scene_buffer_ptr())->cam.up.unit() * move_speed; + move_vec = -((scene*) renderer.scene_buffer_ptr())->meta.cam.up.unit() * move_speed; break; } default: break; } - ((scene*) renderer.scene_buffer_ptr())->cam.move(move_vec); + ((scene*) renderer.scene_buffer_ptr())->meta.cam.move(move_vec); if (!move_vec.near_zero()) { reset_accumulation = true; @@ -200,15 +210,15 @@ int main() { ImGui::Text("frame per second %u\n", static_cast(1000.f / delta_time)); ImGui::Text("frame time %f ms\n", delta_time); - ImGui::Text("frame count %u\n", ((scene*) renderer.scene_buffer_ptr())->sample_index); + ImGui::Text("frame count %u\n", ((scene*) renderer.scene_buffer_ptr())->meta.sample_index); - if (ImGui::Checkbox("depth of field", (bool*)&((scene*) renderer.scene_buffer_ptr())->enable_dof)) { + if (ImGui::Checkbox("depth of field", (bool*)&((scene*) renderer.scene_buffer_ptr())->meta.enable_dof)) { reset_accumulation = true; } - ImGui::SliderInt("bounces", (int32_t*)&((scene*) renderer.scene_buffer_ptr())->max_bounce, 2, 250); + ImGui::SliderInt("bounces", (int32_t*)&((scene*) renderer.scene_buffer_ptr())->meta.max_bounce, 2, 250); - if (ImGui::Checkbox("debug bvh", (bool*)&((scene*) renderer.scene_buffer_ptr())->debug_bvh)) { + if (ImGui::Checkbox("debug bvh", (bool*)&((scene*) renderer.scene_buffer_ptr())->meta.debug_bvh)) { reset_accumulation = true; } @@ -226,13 +236,13 @@ int main() { renderer.begin_frame(); if (reset_accumulation) { - ((scene*) renderer.scene_buffer_ptr())->sample_index = 0; + ((scene*) renderer.scene_buffer_ptr())->meta.sample_index = 0; renderer.reset_accumulation(); } renderer.compute(width, height); - ((scene*) renderer.scene_buffer_ptr())->sample_index++; + ((scene*) renderer.scene_buffer_ptr())->meta.sample_index++; renderer.ui(); diff --git a/src/scene.cpp b/src/scene.cpp index 68929d8..9fd57eb 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -1,14 +1,15 @@ #include "scene.hpp" +#include + #include "utils.hpp" +#include "gltf.hpp" // Return the number of instantiated spheres -uint32_t scene::random_scene(sphere *world) { +void scene::random_scene() { material ground_material = { { 0.5, 0.5, 0.5 } }; ground_material.type = MATERIAL_TYPE::LAMBERTIAN; - world[0] = sphere{ { 0, -1000, 0 }, ground_material, 1000 }; - - uint32_t world_sphere_index = 1; + spheres.emplace_back(vec3 { 0, -1000, 0 }, ground_material, 1000); int32_t spheres_count = 11; for (int a = -spheres_count; a < spheres_count; a++) { @@ -34,8 +35,7 @@ uint32_t scene::random_scene(sphere *world) { sphere_material.type = MATERIAL_TYPE::DIELECTRIC; } - world[world_sphere_index] = { center, sphere_material, 0.2 }; - world_sphere_index++; + spheres.emplace_back(center, sphere_material, 0.2); } } } @@ -43,34 +43,55 @@ uint32_t scene::random_scene(sphere *world) { material material1 = {}; material1.ior = 1.5; material1.type = MATERIAL_TYPE::DIELECTRIC; - world[world_sphere_index] = { { 0, 1, 0 }, material1, 1.0 }; + spheres.emplace_back(vec3 { 0, 1, 0 }, material1, 1.0); material material2 = {}; material2.albedo = color{ 0.4, 0.2, 0.1 }; material2.type = MATERIAL_TYPE::LAMBERTIAN; - world[world_sphere_index + 1] = { { -4, 1, 0 }, material2, 1.0 }; + spheres.emplace_back(vec3 { -4, 1, 0 }, material2, 1.0); material material3 = {}; material3.albedo = color{ 0.7, 0.6, 0.5 }; material3.fuzz = 0.0; material3.type = MATERIAL_TYPE::METAL; - world[world_sphere_index + 2] = { { 4, 1, 0 }, material3, 1.0 }; + spheres.emplace_back(vec3 { 4, 1, 0 }, material3, 1.0); material material4 = {}; material4.albedo = color{ 0.0, 0.0, 0.0 }; material4.emissive = color{ 1.0, 1.0, 1.0 } * 1000.0; material4.fuzz = 0.0; material4.type = MATERIAL_TYPE::EMISSIVE; - world[world_sphere_index + 3] = { { 2, 1.5, 2 }, material4, 0.5 }; + spheres.emplace_back(vec3 { 2, 1.5, 2 }, material4, 0.5); - return world_sphere_index + 4; + spheres_count = spheres.size(); } -scene::scene(uint32_t width, uint32_t height) - :width(width), height(height), spheres_count(random_scene(spheres)), - cam({ 13.0, 2.0, 3.0 }, { 0.0, 0.0, 0.0 }, 20.0, (float)width / (float)height, 0.1, 10) { - bvh builder; - builder.build(spheres, spheres_count); +scene::scene(camera cam, uint32_t width, uint32_t height) + :meta(cam, width, height){ + + // auto sponza_path = std::filesystem::path("../models/sponza"); + // auto sponza_filename = std::string("Sponza.gltf"); + // auto mesh = gltf::load(sponza_path, sponza_filename); + + // auto node = mesh.nodes[0]; + // for (auto& mesh_part: node) { + // for (size_t i = 0; i < mesh_part.indices.size(); i += 3) { + // auto i1 = mesh_part.indices[i]; + // auto i2 = mesh_part.indices[i + 1]; + // auto i3 = mesh_part.indices[i + 2]; + + // auto v1 = vertex { .position = mesh_part.positions[i1], .normal = mesh_part.normals[i1] }; + // auto v2 = vertex { .position = mesh_part.positions[i2], .normal = mesh_part.normals[i2] }; + // auto v3 = vertex { .position = mesh_part.positions[i3], .normal = mesh_part.normals[i3] }; + + // triangles.emplace_back(v1, v2, v3); + // } + // } + + random_scene(); + + // bvh builder(triangles, nodes); + bvh builder(spheres, nodes); // builder.exporter(); for (uint32_t idx = 0; idx < builder.nodes.size(); idx++) { diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp index caa27f8..b31d934 100644 --- a/src/vk-renderer.cpp +++ b/src/vk-renderer.cpp @@ -24,7 +24,7 @@ struct UiTransforms { float translate_x, translate_y; }; -vkrenderer::vkrenderer(window& wnd, size_t scene_buffer_size) { +vkrenderer::vkrenderer(window& wnd, size_t scene_buffer_size, size_t geometry_buffer_size, size_t bvh_buffer_size) { platform_surface = api.create_surface(wnd); swapchain = api.create_swapchain( platform_surface, @@ -45,13 +45,27 @@ vkrenderer::vkrenderer(window& wnd, size_t scene_buffer_size) { }, { .binding = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, .pImmutableSamplers = VK_NULL_HANDLE, }, { .binding = 2, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, + .pImmutableSamplers = VK_NULL_HANDLE, + }, + { + .binding = 3, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, + .pImmutableSamplers = VK_NULL_HANDLE, + }, + { + .binding = 4, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, @@ -94,9 +108,13 @@ vkrenderer::vkrenderer(window& wnd, size_t scene_buffer_size) { acquire_semaphores = api.create_semaphores(swapchain.image_count); scene_buffer = api.create_buffer(scene_buffer_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + geometry_buffer = api.create_buffer(geometry_buffer_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); + bvh_buffer = api.create_buffer(bvh_buffer_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); for (size_t index = 0; index < swapchain.image_count; index++) { api.update_descriptor_set_buffer(compute_shader_sets[index], compute_sets_bindings[0], scene_buffer); + api.update_descriptor_set_buffer(compute_shader_sets[index], compute_sets_bindings[1], geometry_buffer); + api.update_descriptor_set_buffer(compute_shader_sets[index], compute_sets_bindings[2], bvh_buffer); } std::vector attachments_format { swapchain.surface_format.format }; @@ -215,6 +233,8 @@ vkrenderer::~vkrenderer() { VKRESULT(vkWaitForFences(api.context.device, submission_fences.size(), submission_fences.data(), VK_TRUE, UINT64_MAX)) api.destroy_buffer(scene_buffer); + api.destroy_buffer(geometry_buffer); + api.destroy_buffer(bvh_buffer); api.destroy_fences(submission_fences); api.destroy_semaphores(execution_semaphores); api.destroy_semaphores(acquire_semaphores); @@ -308,8 +328,8 @@ void vkrenderer::begin_frame() { auto output_image = accumulation_images[0]; auto accumulation_image = accumulation_images[1]; - api.update_descriptor_set_image(compute_shader_sets[swapchain_image_index], compute_sets_bindings[1], output_image.view, VK_NULL_HANDLE); - api.update_descriptor_set_image(compute_shader_sets[swapchain_image_index], compute_sets_bindings[2], accumulation_image.view, VK_NULL_HANDLE); + api.update_descriptor_set_image(compute_shader_sets[swapchain_image_index], compute_sets_bindings[3], output_image.view, VK_NULL_HANDLE); + api.update_descriptor_set_image(compute_shader_sets[swapchain_image_index], compute_sets_bindings[4], accumulation_image.view, VK_NULL_HANDLE); api.update_descriptor_set_image(tonemapping_shader_sets[swapchain_image_index], tonemapping_sets_bindings[0], swapchain.images[swapchain_image_index].view, VK_NULL_HANDLE); api.update_descriptor_set_image(tonemapping_shader_sets[swapchain_image_index], tonemapping_sets_bindings[1], output_image.view, VK_NULL_HANDLE); -- cgit v1.3