diff --git a/assets/models/level_scene.glb b/assets/models/level_scene.glb index 5f5da0f..bd622ac 100644 Binary files a/assets/models/level_scene.glb and b/assets/models/level_scene.glb differ diff --git a/assets/models/level_scene.glb.b4k b/assets/models/level_scene.glb.b4k new file mode 100644 index 0000000..2a78176 Binary files /dev/null and b/assets/models/level_scene.glb.b4k differ diff --git a/assets/models/level_scene.glb.weird b/assets/models/level_scene.glb.weird new file mode 100644 index 0000000..fb5f12a Binary files /dev/null and b/assets/models/level_scene.glb.weird differ diff --git a/assets/shaders/composite.slang b/assets/shaders/composite.slang index 6a450ad..692947b 100644 --- a/assets/shaders/composite.slang +++ b/assets/shaders/composite.slang @@ -26,5 +26,4 @@ float4 frag_main(post_transform_vertex input) : SV_Target { let ambient_contribution = 0.1f; let lighting = max(sun_contribution, ambient_contribution); return float4(lighting * albedo, 1.0f); - //return float4(lighting + float3(1.0f), 1.0f); } diff --git a/assets/shaders/render_mesh.slang b/assets/shaders/render_mesh.slang index b3c0d5c..ad0d157 100644 --- a/assets/shaders/render_mesh.slang +++ b/assets/shaders/render_mesh.slang @@ -1,7 +1,13 @@ #include "camera.slang" +struct model_matrices { + float4x4 model; + float4x4 normal; +}; + [[vk_binding(0, 0)]] ConstantBuffer camera; [[vk_binding(1, 0)]] Sampler2D albedo; +[[vk_binding(2, 0)]] ConstantBuffer matrices; struct input_vertex { @@ -18,13 +24,16 @@ struct post_transform_vertex { [shader("vertex")] post_transform_vertex vert_main(input_vertex vertex) { - post_transform_vertex output; - - output.position = mul(camera.projection, mul(camera.view, float4(vertex.pos, 1.0f))); - output.normal = vertex.normal; - output.uv = vertex.texcoord; + post_transform_vertex output; - return output; + float4 position = mul(matrices.model, float4(vertex.pos, 1.0f)); + //float4 position = float4(vertex.pos, 1.0f); + + output.position = mul(camera.projection, mul(camera.view, position)); + output.normal = normalize(mul(float3x3(matrices.normal), vertex.normal)); + output.uv = vertex.texcoord; + + return output; } struct fragment_output { diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 22d546b..f3d187a 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -60,7 +60,7 @@ FetchContent_Declare( FetchContent_Declare( fastgltf_fetch GIT_REPOSITORY https://github.com/spnda/fastgltf.git - GIT_TAG ce52187 + GIT_TAG 35368f913b79acc112c05d67291681e7badea68b ) FetchContent_MakeAvailable(vuk_fetch glfw_fetch glm_fetch entt_fetch slang_fetch fastgltf_fetch) diff --git a/source/game/engine.cpp b/source/game/engine.cpp index 1f8d5f9..1fd6a1a 100644 --- a/source/game/engine.cpp +++ b/source/game/engine.cpp @@ -26,14 +26,13 @@ bounds_of(const trb::game::scene &scene) { auto min = glm::vec3(std::numeric_limits::infinity()); auto max = glm::vec3(-std::numeric_limits::infinity()); - const auto is_mesh_node = [](const auto &v) { - return std::holds_alternative(v); - }; - for (const auto &mesh : scene.meshes) { + const auto transform = [mesh](glm::vec3 p) { + return glm::vec3(mesh.transform * glm::vec4(p, 1.0f)); + }; for (const auto [position, normal, uv] : mesh.vertices) { - min = glm::min(min, position); - max = glm::max(max, position); + min = glm::min(min, transform(position)); + max = glm::max(max, transform(position)); } } @@ -103,7 +102,7 @@ void engine::run() { try { const auto [map_min, map_max] = ::bounds_of(level_border); const auto [view, projection] = ::calculate_camera_matrices( - map_min, map_max, 1920.0f / 1080.0f, 1.1f); + map_min, map_max, 1920.0f / 1080.0f, 3.0f); renderer.render(level_border_render_ids, view, projection); } catch (const vuk::VkException &ex) { if (ex.what() != std::string("Out of date.")) { diff --git a/source/game/model.cpp b/source/game/model.cpp index 938b78b..413bd95 100644 --- a/source/game/model.cpp +++ b/source/game/model.cpp @@ -1,11 +1,13 @@ #include "model.hpp" #define STB_IMAGE_IMPLEMENTATION +#include #include #include #include #include +#include #include #include @@ -274,11 +276,20 @@ scene load_glb(std::filesystem::path path) { auto &asset = maybe_asset.get(); auto meshes = std::vector(); - for (auto &in_mesh : asset.meshes) { - for (auto &parsed_mesh : ::load_mesh(asset, in_mesh)) { - meshes.push_back(std::move(parsed_mesh)); - } - } + fastgltf::iterateSceneNodes( + asset, 0, fastgltf::math::fmat4x4(), + [&](fastgltf::Node &node, fastgltf::math::fmat4x4 matrix) { + if (node.meshIndex.has_value()) { + for (auto &parsed_mesh : + ::load_mesh(asset, asset.meshes[node.meshIndex.value()])) { + auto transform = glm::mat4(); + std::memcpy(glm::value_ptr(transform), matrix.data(), + sizeof(float) * 16); + parsed_mesh.transform = transform; + meshes.push_back(std::move(parsed_mesh)); + } + } + }); return { .meshes = meshes, diff --git a/source/game/model.hpp b/source/game/model.hpp index 0f86d07..f82e805 100644 --- a/source/game/model.hpp +++ b/source/game/model.hpp @@ -18,6 +18,7 @@ struct mesh_node { std::vector vertices; std::vector indices; std::uint32_t material_index; + glm::mat4 transform; }; struct texture_source { diff --git a/source/render/renderer.cpp b/source/render/renderer.cpp index 6fdb0b1..53eae53 100644 --- a/source/render/renderer.cpp +++ b/source/render/renderer.cpp @@ -66,6 +66,7 @@ VUK_BA(vuk::eIndirectRead) indirect_buffer, VUK_BA(vuk::eVertexRead) vertex_buffer, VUK_BA(vuk::eIndexRead) index_buffer, + VUK_BA(vuk::eVertexRead) transform_buffer, VUK_IA(vuk::eColorWrite) normals, VUK_IA(vuk::eColorWrite) albedos, VUK_IA(vuk::eDepthStencilRW) depth_target) { auto attributes = std::vector(); @@ -108,6 +109,7 @@ .bind_index_buffer(index_buffer, vuk::IndexType::eUint32) .bind_buffer(0, 0, camera_buffer) .bind_image(0, 1, *mesh->albedo_view) + .bind_buffer(0, 2, transform_buffer) .bind_sampler(0, 1, { .magFilter = vuk::Filter::eLinear, @@ -226,6 +228,7 @@ void renderer::render(std::span meshes, glm::mat4 view, vuk::make_constant("mesh indirect command", *mesh.indirect_command), vuk::make_constant("mesh vertices", *mesh.vertices), vuk::make_constant("mesh indices", *mesh.indices), + vuk::make_constant("mesh transform", *mesh.transform), std::move(normal_buffer), std::move(albedo_buffer), std::move(depth_image)); } @@ -263,6 +266,14 @@ std::uint32_t renderer::register_mesh(const game::mesh_node &mesh, vuk::DomainFlagBits::eTransferOperation, std::span(indirect_draw)); + auto matrices = std::array(); + matrices[0] = mesh.transform; + matrices[1] = + glm::mat4(glm::transpose(glm::inverse(glm::mat3(mesh.transform)))); + auto [transform_buffer, transform_future] = vuk::create_buffer( + context.superframe_allocator, vuk::MemoryUsage::eGPUonly, + vuk::DomainFlagBits::eTransferOperation, std::span(matrices)); + auto albedo_ia = vuk::ImageAttachment(); albedo_ia.format = vuk::Format::eR8G8B8A8Srgb; albedo_ia.extent = vuk::Extent3D{ @@ -289,6 +300,7 @@ std::uint32_t renderer::register_mesh(const game::mesh_node &mesh, futures.push_back(std::move(vertex_future)); futures.push_back(std::move(index_future)); futures.push_back(std::move(indirect_future)); + futures.push_back(std::move(transform_future)); futures.push_back(std::move(albedo_future.as_released( vuk::Access::eFragmentSampled, vuk::DomainFlagBits::eGraphicsQueue))); @@ -303,6 +315,7 @@ std::uint32_t renderer::register_mesh(const game::mesh_node &mesh, .indirect_command = std::move(indirect_buffer), .albedo = std::move(albedo_image), .albedo_view = std::move(albedo_view), + .transform = std::move(transform_buffer), }}); return id; diff --git a/source/render/renderer.hpp b/source/render/renderer.hpp index 148d76c..64d3ee7 100644 --- a/source/render/renderer.hpp +++ b/source/render/renderer.hpp @@ -20,6 +20,7 @@ public: vuk::Unique indirect_command; vuk::Unique albedo; vuk::Unique albedo_view; + vuk::Unique transform; }; private: