diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/gltf.cpp | 133 | ||||
| -rw-r--r-- | src/main.cpp | 12 | ||||
| -rw-r--r-- | src/scene.cpp | 14 | ||||
| -rw-r--r-- | src/vk-context.cpp | 1 | ||||
| -rw-r--r-- | src/vk-renderer.cpp | 53 |
5 files changed, 183 insertions, 30 deletions
diff --git a/src/gltf.cpp b/src/gltf.cpp index 66147dc..bfd7522 100644 --- a/src/gltf.cpp +++ b/src/gltf.cpp @@ -3,11 +3,14 @@ #include <fstream>
#include <cstring>
+#define STB_IMAGE_IMPLEMENTATION
+#include "thirdparty/stb_image.h"
+
#include "utils.hpp"
const vec3 scale (0.00800000037997961);
-node gltf::load(std::filesystem::path &path, std::string &filename) {
+node gltf::load(std::filesystem::path &path, std::string &filename, vkrenderer &renderer) {
std::fstream f(path / filename);
json gltf_json;
@@ -24,8 +27,8 @@ node gltf::load(std::filesystem::path &path, std::string &filename) { buffer_index++;
}
- // auto materials = load_materials(gltf_json);
- std::vector<material> materials;
+ auto textures = load_textures(gltf_json, path, renderer);
+ auto materials = load_materials(gltf_json, textures);
auto meshes = load_meshes(gltf_json, buffers_content, materials);
@@ -77,7 +80,68 @@ std::vector<mesh> gltf::load_meshes(json &gltf_json, std::vector<std::vector<uin return std::move(meshes);
}
-std::vector<material> gltf::load_materials(json &gltf_json) {
+std::vector<texture> gltf::load_textures(json &gltf_json, std::filesystem::path &path, vkrenderer &renderer) {
+ auto &gltf_images = gltf_json["images"];
+ auto images_count = gltf_images.size();
+ std::vector<image> images { images_count };
+
+ for (size_t image_index = 0; image_index < images_count; image_index++) {
+ auto &gltf_image = gltf_images[image_index];
+ int x,y,n;
+ auto filepath = (path / gltf_image["uri"].get<std::string>()).string();
+ unsigned char *data = stbi_load(filepath.c_str(), &x, &y, &n, 4);
+ VkExtent3D size {
+ .width = static_cast<uint32_t>(x),
+ .height = static_cast<uint32_t>(y),
+ .depth = 1
+ };
+ auto img = renderer.api.create_image(size, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
+ renderer.update_image(img, data, x * y * 4);
+
+ stbi_image_free(data);
+
+ images[image_index] = std::move(img);
+ }
+
+ renderer.api.update_descriptor_images(images, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
+
+ auto &gltf_samplers = gltf_json["samplers"];
+ auto samplers_count = gltf_samplers.size();
+ std::vector<sampler> samplers { samplers_count };
+
+ for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
+ samplers[sampler_index] = renderer.api.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
+ }
+
+ renderer.api.update_descriptor_samplers(samplers);
+
+ auto &gltf_textures = gltf_json["textures"];
+ auto textures_count = gltf_textures.size();
+ std::vector<texture> textures { textures_count };
+
+ for (size_t texture_index = 0; texture_index < textures_count; texture_index++) {
+ auto gltf_texture = gltf_textures[texture_index];
+
+ auto image_index = gltf_texture["source"].get<uint32_t>();
+ auto &image = images[image_index];
+
+ uint32_t sampler_id = 0;
+ if (gltf_texture.contains("sampler")) {
+ auto sampler_index = gltf_texture["sampler"].get<uint32_t>();
+ auto &sampler = samplers[sampler_index];
+ sampler_id = sampler.bindless_index;
+ }
+
+ textures[texture_index] = texture {
+ .image_id = image.bindless_sampled_index,
+ .sampler_id = sampler_id
+ };
+ }
+
+ return std::move(textures);
+}
+
+std::vector<material> gltf::load_materials(json &gltf_json, std::vector<texture> &textures) {
auto &gltf_materials = gltf_json["materials"];
auto materials_count = gltf_materials.size();
std::vector<material> materials { materials_count };
@@ -86,13 +150,38 @@ std::vector<material> gltf::load_materials(json &gltf_json) { auto& gltf_material = gltf_materials[material_index];
auto& material = materials[material_index];
- auto base_color = gltf_material["baseColorFactor"];
- material.base_color.v[0] = base_color[0];
- material.base_color.v[1] = base_color[1];
- material.base_color.v[2] = base_color[2];
- material.base_color.v[3] = base_color[3];
- material.metalness = gltf_material["matellicFactor"].get<float>();
- material.roughness = gltf_material["roughnessFactor"].get<float>();
+ if (gltf_material.contains("pbrMetallicRoughness")) {
+ auto &pbr_params = gltf_material["pbrMetallicRoughness"];
+
+ if (pbr_params.contains("baseColorFactor")) {
+ auto &base_color = pbr_params["baseColorFactor"];
+ material.base_color.v[0] = base_color[0].get<float>();
+ material.base_color.v[1] = base_color[1].get<float>();
+ material.base_color.v[2] = base_color[2].get<float>();
+ material.base_color.v[3] = base_color[3].get<float>();
+ } else
+ material.base_color = vec3(1.f);
+
+ if (pbr_params.contains("baseColorTexture")) {
+ auto base_color_index = pbr_params["baseColorTexture"]["index"].get<uint32_t>();
+ material.base_color_texture = textures[base_color_index];
+ }
+
+ if (pbr_params.contains("metallicFactor"))
+ material.metalness = pbr_params["metallicFactor"].get<float>();
+ else
+ material.metalness = 1.0;
+
+ if (pbr_params.contains("roughnessFactor"))
+ material.roughness = pbr_params["roughnessFactor"].get<float>();
+ else
+ material.roughness = 1.0;
+
+ if (pbr_params.contains("metallicRoughnessTexture")) {
+ auto metallic_roughness_index = pbr_params["metallicRoughnessTexture"]["index"].get<uint32_t>();
+ material.metallic_roughness_texture = textures[metallic_roughness_index];
+ }
+ }
}
return std::move(materials);
@@ -159,7 +248,27 @@ mesh_part gltf::load_primitive(json &gltf_json, json &primitive, std::vector<std }
}
- // part.mat = materials[primitive["material"].get<uint32_t>()];
+ {
+ auto uvs_accessor_index = primitive["attributes"]["TEXCOORD_0"].get<uint32_t>();
+ auto uvs_view_index = accessors[uvs_accessor_index]["bufferView"].get<uint32_t>();
+ auto &uvs_view = gltf_json["bufferViews"][uvs_view_index];
+
+ auto uvs_buffer_index = uvs_view["buffer"].get<uint32_t>();
+ auto uvs_offset = uvs_view["byteOffset"].get<size_t>();
+ auto uvs_length = uvs_view["byteLength"].get<size_t>();
+
+ auto &uvs_buffer = buffers_content[uvs_buffer_index];
+ float* uvs_start = (float*)(uvs_buffer.data() + uvs_offset);
+
+ size_t uvs_count = uvs_length / (sizeof(float) * 2);
+ part.uvs.resize(uvs_count);
+
+ for (size_t i = 0; i < uvs_count; i++) {
+ part.uvs[i] = vec3(uvs_start[i * 2], uvs_start[i * 2 + 1], 0.0);
+ }
+ }
+
+ part.mat = materials[primitive["material"].get<uint32_t>()];
return std::move(part);
}
diff --git a/src/main.cpp b/src/main.cpp index c47aaeb..287b0eb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,17 +60,23 @@ int main() { 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.meta), sizeof(main_scene.triangles[0]) * main_scene.triangles.size(), sizeof(main_scene.packed_nodes[0]) * main_scene.packed_nodes.size() }; + + vkrenderer renderer { wnd }; + auto main_scene = scene(cam, width, height, renderer); // vkrenderer renderer { wnd, sizeof(main_scene.meta), sizeof(main_scene.spheres[0]) * main_scene.spheres.size(), sizeof(main_scene.packed_nodes[0]) * main_scene.packed_nodes.size() }; + renderer.create_scene_buffer(sizeof(main_scene.meta)); + renderer.create_geometry_buffer(sizeof(main_scene.triangles[0]) * main_scene.triangles.size()); + renderer.create_bvh_buffer(sizeof(main_scene.packed_nodes[0]) * main_scene.packed_nodes.size()); + // Upload scene content std::memcpy(renderer.scene_buffer_ptr(), &main_scene.meta, sizeof(main_scene.meta)); renderer.update_geometry_buffer(main_scene.triangles.data()); // renderer.update_geometry_buffer(main_scene.spheres.data()); renderer.update_bvh_buffer(main_scene.packed_nodes.data()); + auto can_render = true; + ImGuiIO& io = ImGui::GetIO(); io.DisplaySize.x = (float)width; io.DisplaySize.y = (float)height; diff --git a/src/scene.cpp b/src/scene.cpp index a94c603..d162b3a 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -55,16 +55,16 @@ // spheres_count = spheres.size();
// }
-scene::scene(camera cam, uint32_t width, uint32_t height)
+scene::scene(camera cam, uint32_t width, uint32_t height, vkrenderer &renderer)
:meta(cam, width, height){
auto bistro_interior_path = std::filesystem::path("../models/BistroInterior");
auto bistro_interior_filename = std::string("BistroInterior.gltf");
- auto root_node = gltf::load(bistro_interior_path, bistro_interior_filename);
+ auto root_node = gltf::load(bistro_interior_path, bistro_interior_filename, renderer);
// auto sponza_path = std::filesystem::path("../models/sponza");
// auto sponza_filename = std::string("Sponza.gltf");
- // auto root_node = gltf::load(sponza_path, sponza_filename);
+ // auto root_node = gltf::load(sponza_path, sponza_filename, renderer);
std::queue<node> nodes_to_load {};
nodes_to_load.push(root_node);
@@ -80,11 +80,11 @@ scene::scene(camera cam, uint32_t width, uint32_t height) 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] };
+ auto v1 = vertex { .position = mesh_part.positions[i1], .normal = mesh_part.normals[i1], .uv = mesh_part.uvs[i1] };
+ auto v2 = vertex { .position = mesh_part.positions[i2], .normal = mesh_part.normals[i2], .uv = mesh_part.uvs[i2] };
+ auto v3 = vertex { .position = mesh_part.positions[i3], .normal = mesh_part.normals[i3], .uv = mesh_part.uvs[i3] };
- triangles.emplace_back(v1, v2, v3);
+ triangles.emplace_back(v1, v2, v3, mesh_part.mat);
}
}
}
diff --git a/src/vk-context.cpp b/src/vk-context.cpp index 2f909ff..d68dca9 100644 --- a/src/vk-context.cpp +++ b/src/vk-context.cpp @@ -118,6 +118,7 @@ void vkcontext::create_device() { physical_device_12_features.bufferDeviceAddress = VK_TRUE; physical_device_12_features.runtimeDescriptorArray = VK_TRUE; physical_device_12_features.shaderStorageImageArrayNonUniformIndexing = VK_TRUE; + physical_device_12_features.shaderSampledImageArrayNonUniformIndexing = VK_TRUE; physical_device_12_features.descriptorBindingPartiallyBound = VK_TRUE; physical_device_12_features.descriptorBindingPartiallyBound = VK_TRUE; physical_device_12_features.descriptorBindingUpdateUnusedWhilePending = VK_TRUE; diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp index 68debc8..4ac1cd0 100644 --- a/src/vk-renderer.cpp +++ b/src/vk-renderer.cpp @@ -28,7 +28,7 @@ struct UiTransforms { float translate_x, translate_y; }; -vkrenderer::vkrenderer(window& wnd, size_t scene_buffer_size, size_t geometry_buffer_size, size_t bvh_buffer_size) { +vkrenderer::vkrenderer(window& wnd) { platform_surface = api.create_surface(wnd); swapchain = api.create_swapchain( platform_surface, @@ -55,10 +55,6 @@ vkrenderer::vkrenderer(window& wnd, size_t scene_buffer_size, size_t geometry_bu execution_semaphores = api.create_semaphores(virtual_frames_count); acquire_semaphores = api.create_semaphores(virtual_frames_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 | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY); - bvh_buffer = api.create_buffer(bvh_buffer_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY); - std::vector<VkFormat> attachments_format { swapchain.surface_format.format }; render_pass = api.create_render_pass(attachments_format, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); @@ -87,7 +83,7 @@ vkrenderer::vkrenderer(window& wnd, size_t scene_buffer_size, size_t geometry_bu .height = (uint32_t)atlas_height, .depth = 1, }; - auto staging_buffer = api.create_buffer(atlas_width * atlas_height * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); + staging_buffer = api.create_buffer(4096 * 4096 * 4 * sizeof(uint32_t), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); std::memcpy(staging_buffer.alloc_info.pMappedData, pixels, atlas_width * atlas_height * sizeof(uint32_t)); ui_texture = api.create_image(atlas_size, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); @@ -115,8 +111,6 @@ vkrenderer::vkrenderer(window& wnd, size_t scene_buffer_size, size_t geometry_bu VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX)) - api.destroy_buffer(staging_buffer); - std::vector<image> images = { accumulation_images[0], accumulation_images[1], @@ -152,6 +146,7 @@ vkrenderer::~vkrenderer() { api.destroy_buffer(scene_buffer); api.destroy_buffer(geometry_buffer); api.destroy_buffer(bvh_buffer); + api.destroy_buffer(staging_buffer); api.destroy_fences(submission_fences); api.destroy_semaphores(execution_semaphores); api.destroy_semaphores(acquire_semaphores); @@ -411,6 +406,18 @@ void vkrenderer::handle_swapchain_result(VkResult function_result) { } +void vkrenderer::create_scene_buffer(size_t size) { + scene_buffer = api.create_buffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU); +} + +void vkrenderer::create_geometry_buffer(size_t size) { + geometry_buffer = api.create_buffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY); +} + +void vkrenderer::create_bvh_buffer(size_t size) { + bvh_buffer = api.create_buffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY); +} + // TODO: Integrate into the API so that we no longer have to wait for the fence void vkrenderer::update_geometry_buffer(void* data) { VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX)) @@ -453,3 +460,33 @@ void vkrenderer::update_bvh_buffer(void* data) { api.destroy_buffer(staging_buffer); } + +void vkrenderer::update_image(image img, void* data, size_t size) { + if (staging_buffer.size < size) { + api.destroy_buffer(staging_buffer); + + staging_buffer = api.create_buffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); + } + + std::memcpy(staging_buffer.alloc_info.pMappedData, data, size); + + VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX)) + VKRESULT(vkResetFences(api.context.device, 1, &submission_fences[virtual_frame_index])) + + auto cmd_buf = command_buffers[virtual_frame_index]; + api.start_record(cmd_buf); + + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_MEMORY_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, img); + + api.copy_buffer(cmd_buf, staging_buffer, img); + + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, 0, img); + + api.end_record(cmd_buf); + + + api.submit(cmd_buf, VK_NULL_HANDLE, VK_NULL_HANDLE, submission_fences[virtual_frame_index]); + + VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[virtual_frame_index], VK_TRUE, UINT64_MAX)) + +} |
