aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2021-09-06 22:55:51 +0200
committerladevieq <ladevie.quentin@gmail.com>2021-09-06 22:55:51 +0200
commit3f6d9a3a75e2615866f8ed2cd0015fabea6490b7 (patch)
tree077e568cca0a8823f0b361f570a2d76b43011aac /src
parentbf512216323f3df55627421bb0187ed364d58340 (diff)
Load gltf materials + diffuse and specular brdf
Diffstat (limited to 'src')
-rw-r--r--src/gltf.cpp133
-rw-r--r--src/main.cpp12
-rw-r--r--src/scene.cpp14
-rw-r--r--src/vk-context.cpp1
-rw-r--r--src/vk-renderer.cpp53
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))
+
+}