diff --git a/data/shaders/glsl/gltfloading/mesh.frag b/data/shaders/glsl/gltfloading/mesh.frag index fb415cef..866dd316 100644 --- a/data/shaders/glsl/gltfloading/mesh.frag +++ b/data/shaders/glsl/gltfloading/mesh.frag @@ -17,7 +17,7 @@ void main() vec3 N = normalize(inNormal); vec3 L = normalize(inLightVec); vec3 V = normalize(inViewVec); - vec3 R = reflect(-L, N); + vec3 R = reflect(L, N); vec3 diffuse = max(dot(N, L), 0.15) * inColor; vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); outFragColor = vec4(diffuse * color.rgb + specular, 1.0); diff --git a/data/shaders/glsl/gltfloading/mesh.frag.spv b/data/shaders/glsl/gltfloading/mesh.frag.spv index 5cd56265..00c5c46a 100644 Binary files a/data/shaders/glsl/gltfloading/mesh.frag.spv and b/data/shaders/glsl/gltfloading/mesh.frag.spv differ diff --git a/data/shaders/glsl/gltfloading/mesh.vert b/data/shaders/glsl/gltfloading/mesh.vert index 2760684e..e2da4ece 100644 --- a/data/shaders/glsl/gltfloading/mesh.vert +++ b/data/shaders/glsl/gltfloading/mesh.vert @@ -10,6 +10,7 @@ layout (set = 0, binding = 0) uniform UBOScene mat4 projection; mat4 view; vec4 lightPos; + vec4 viewPos; } uboScene; layout(push_constant) uniform PushConsts { @@ -32,6 +33,6 @@ void main() vec4 pos = uboScene.view * vec4(inPos, 1.0); outNormal = mat3(uboScene.view) * inNormal; vec3 lPos = mat3(uboScene.view) * uboScene.lightPos.xyz; - outLightVec = lPos - pos.xyz; - outViewVec = -pos.xyz; + outLightVec = uboScene.lightPos.xyz - pos.xyz; + outViewVec = uboScene.viewPos.xyz - pos.xyz; } \ No newline at end of file diff --git a/data/shaders/glsl/gltfloading/mesh.vert.spv b/data/shaders/glsl/gltfloading/mesh.vert.spv index cf6fc4ac..4fe54ca9 100644 Binary files a/data/shaders/glsl/gltfloading/mesh.vert.spv and b/data/shaders/glsl/gltfloading/mesh.vert.spv differ diff --git a/data/shaders/hlsl/gltfloading/mesh.frag b/data/shaders/hlsl/gltfloading/mesh.frag index 914421a0..a574c7a1 100644 --- a/data/shaders/hlsl/gltfloading/mesh.frag +++ b/data/shaders/hlsl/gltfloading/mesh.frag @@ -24,7 +24,7 @@ float4 main(VSOutput input) : SV_TARGET float3 N = normalize(input.Normal); float3 L = normalize(input.LightVec); float3 V = normalize(input.ViewVec); - float3 R = reflect(-L, N); + float3 R = reflect(L, N); float3 diffuse = max(dot(N, L), 0.0) * input.Color; float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); return float4(diffuse * color.rgb + specular, 1.0); diff --git a/data/shaders/hlsl/gltfloading/mesh.frag.spv b/data/shaders/hlsl/gltfloading/mesh.frag.spv index a801c5f2..4eafff86 100644 Binary files a/data/shaders/hlsl/gltfloading/mesh.frag.spv and b/data/shaders/hlsl/gltfloading/mesh.frag.spv differ diff --git a/data/shaders/hlsl/gltfloading/mesh.vert b/data/shaders/hlsl/gltfloading/mesh.vert index a47967ac..3f46fbc5 100644 --- a/data/shaders/hlsl/gltfloading/mesh.vert +++ b/data/shaders/hlsl/gltfloading/mesh.vert @@ -13,6 +13,7 @@ struct UBO float4x4 projection; float4x4 view; float4 lightPos; + float4 viewPos; }; cbuffer ubo : register(b0) { UBO ubo; } @@ -42,8 +43,7 @@ VSOutput main(VSInput input) float4 pos = mul(ubo.view, float4(input.Pos, 1.0)); output.Normal = mul((float3x3)ubo.view, input.Normal); - float3 lPos = mul((float3x3)ubo.view, ubo.lightPos.xyz); - output.LightVec = lPos - pos.xyz; - output.ViewVec = -pos.xyz; + output.LightVec = ubo.lightPos.xyz - pos.xyz; + output.ViewVec = ubo.viewPos.xyz - pos.xyz; return output; } \ No newline at end of file diff --git a/data/shaders/hlsl/gltfloading/mesh.vert.spv b/data/shaders/hlsl/gltfloading/mesh.vert.spv index 3061fec4..612219e6 100644 Binary files a/data/shaders/hlsl/gltfloading/mesh.vert.spv and b/data/shaders/hlsl/gltfloading/mesh.vert.spv differ diff --git a/examples/gltfloading/gltfloading.cpp b/examples/gltfloading/gltfloading.cpp index 1aa42647..7a38fcef 100644 --- a/examples/gltfloading/gltfloading.cpp +++ b/examples/gltfloading/gltfloading.cpp @@ -1,7 +1,7 @@ /* * Vulkan Example - glTF scene loading and rendering * -* Copyright (C) 2020-2021 by Sascha Willems - www.saschawillems.de +* Copyright (C) 2020-2022 by Sascha Willems - www.saschawillems.de * * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) */ @@ -78,9 +78,14 @@ public: // A node represents an object in the glTF scene graph struct Node { Node* parent; - std::vector children; + std::vector children; Mesh mesh; glm::mat4 matrix; + ~Node() { + for (auto& child : children) { + delete child; + } + } }; // A glTF material stores information in e.g. the texture that is attached to it and colors @@ -109,10 +114,13 @@ public: std::vector images; std::vector textures; std::vector materials; - std::vector nodes; + std::vector nodes; ~VulkanglTFModel() { + for (auto node : nodes) { + delete node; + } // Release all Vulkan resources allocated for the model vkDestroyBuffer(vulkanDevice->logicalDevice, vertices.buffer, nullptr); vkFreeMemory(vulkanDevice->logicalDevice, vertices.memory, nullptr); @@ -195,29 +203,30 @@ public: void loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFModel::Node* parent, std::vector& indexBuffer, std::vector& vertexBuffer) { - VulkanglTFModel::Node node{}; - node.matrix = glm::mat4(1.0f); + VulkanglTFModel::Node* node = new VulkanglTFModel::Node{}; + node->matrix = glm::mat4(1.0f); + node->parent = parent; // Get the local node matrix // It's either made up from translation, rotation, scale or a 4x4 matrix if (inputNode.translation.size() == 3) { - node.matrix = glm::translate(node.matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); + node->matrix = glm::translate(node->matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); } if (inputNode.rotation.size() == 4) { glm::quat q = glm::make_quat(inputNode.rotation.data()); - node.matrix *= glm::mat4(q); + node->matrix *= glm::mat4(q); } if (inputNode.scale.size() == 3) { - node.matrix = glm::scale(node.matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); + node->matrix = glm::scale(node->matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); } if (inputNode.matrix.size() == 16) { - node.matrix = glm::make_mat4x4(inputNode.matrix.data()); + node->matrix = glm::make_mat4x4(inputNode.matrix.data()); }; // Load node's children if (inputNode.children.size() > 0) { for (size_t i = 0; i < inputNode.children.size(); i++) { - loadNode(input.nodes[inputNode.children[i]], input , &node, indexBuffer, vertexBuffer); + loadNode(input.nodes[inputNode.children[i]], input , node, indexBuffer, vertexBuffer); } } @@ -309,7 +318,7 @@ public: primitive.firstIndex = firstIndex; primitive.indexCount = indexCount; primitive.materialIndex = glTFPrimitive.material; - node.mesh.primitives.push_back(primitive); + node->mesh.primitives.push_back(primitive); } } @@ -326,20 +335,20 @@ public: */ // Draw a single node including child nodes (if present) - void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node node) + void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFModel::Node* node) { - if (node.mesh.primitives.size() > 0) { + if (node->mesh.primitives.size() > 0) { // Pass the node's matrix via push constants // Traverse the node hierarchy to the top-most parent to get the final matrix of the current node - glm::mat4 nodeMatrix = node.matrix; - VulkanglTFModel::Node* currentParent = node.parent; + glm::mat4 nodeMatrix = node->matrix; + VulkanglTFModel::Node* currentParent = node->parent; while (currentParent) { nodeMatrix = currentParent->matrix * nodeMatrix; currentParent = currentParent->parent; } // Pass the final matrix to the vertex shader using push constants vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); - for (VulkanglTFModel::Primitive& primitive : node.mesh.primitives) { + for (VulkanglTFModel::Primitive& primitive : node->mesh.primitives) { if (primitive.indexCount > 0) { // Get the texture index for this primitive VulkanglTFModel::Texture texture = textures[materials[primitive.materialIndex].baseColorTextureIndex]; @@ -349,7 +358,7 @@ public: } } } - for (auto& child : node.children) { + for (auto& child : node->children) { drawNode(commandBuffer, pipelineLayout, child); } } @@ -382,6 +391,7 @@ public: glm::mat4 projection; glm::mat4 model; glm::vec4 lightPos = glm::vec4(5.0f, 5.0f, -5.0f, 1.0f); + glm::vec4 viewPos; } values; } shaderData; @@ -404,7 +414,7 @@ public: camera.type = Camera::CameraType::lookat; camera.flipY = true; camera.setPosition(glm::vec3(0.0f, -0.1f, -1.0f)); - camera.setRotation(glm::vec3(0.0f, -135.0f, 0.0f)); + camera.setRotation(glm::vec3(0.0f, 45.0f, 0.0f)); camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); } @@ -707,6 +717,7 @@ public: { shaderData.values.projection = camera.matrices.perspective; shaderData.values.model = camera.matrices.view; + shaderData.values.viewPos = camera.viewPos; memcpy(shaderData.buffer.mapped, &shaderData.values, sizeof(shaderData.values)); } diff --git a/examples/gltfscenerendering/gltfscenerendering.cpp b/examples/gltfscenerendering/gltfscenerendering.cpp index 9090317a..7ba5ee0f 100644 --- a/examples/gltfscenerendering/gltfscenerendering.cpp +++ b/examples/gltfscenerendering/gltfscenerendering.cpp @@ -1,7 +1,7 @@ /* * Vulkan Example - Scene rendering * -* Copyright (C) 2020-2021 by Sascha Willems - www.saschawillems.de +* Copyright (C) 2020-202- by Sascha Willems - www.saschawillems.de * * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) * @@ -20,6 +20,9 @@ VulkanglTFScene::~VulkanglTFScene() { + for (auto node : nodes) { + delete node; + } // Release all Vulkan resources allocated for the model vkDestroyBuffer(vulkanDevice->logicalDevice, vertices.buffer, nullptr); vkFreeMemory(vulkanDevice->logicalDevice, vertices.memory, nullptr); @@ -87,30 +90,31 @@ void VulkanglTFScene::loadMaterials(tinygltf::Model& input) void VulkanglTFScene::loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFScene::Node* parent, std::vector& indexBuffer, std::vector& vertexBuffer) { - VulkanglTFScene::Node node{}; - node.name = inputNode.name; + VulkanglTFScene::Node* node = new VulkanglTFScene::Node{}; + node->name = inputNode.name; + node->parent = parent; // Get the local node matrix // It's either made up from translation, rotation, scale or a 4x4 matrix - node.matrix = glm::mat4(1.0f); + node->matrix = glm::mat4(1.0f); if (inputNode.translation.size() == 3) { - node.matrix = glm::translate(node.matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); + node->matrix = glm::translate(node->matrix, glm::vec3(glm::make_vec3(inputNode.translation.data()))); } if (inputNode.rotation.size() == 4) { glm::quat q = glm::make_quat(inputNode.rotation.data()); - node.matrix *= glm::mat4(q); + node->matrix *= glm::mat4(q); } if (inputNode.scale.size() == 3) { - node.matrix = glm::scale(node.matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); + node->matrix = glm::scale(node->matrix, glm::vec3(glm::make_vec3(inputNode.scale.data()))); } if (inputNode.matrix.size() == 16) { - node.matrix = glm::make_mat4x4(inputNode.matrix.data()); + node->matrix = glm::make_mat4x4(inputNode.matrix.data()); }; // Load node's children if (inputNode.children.size() > 0) { for (size_t i = 0; i < inputNode.children.size(); i++) { - loadNode(input.nodes[inputNode.children[i]], input, &node, indexBuffer, vertexBuffer); + loadNode(input.nodes[inputNode.children[i]], input, node, indexBuffer, vertexBuffer); } } @@ -210,7 +214,7 @@ void VulkanglTFScene::loadNode(const tinygltf::Node& inputNode, const tinygltf:: primitive.firstIndex = firstIndex; primitive.indexCount = indexCount; primitive.materialIndex = glTFPrimitive.material; - node.mesh.primitives.push_back(primitive); + node->mesh.primitives.push_back(primitive); } } @@ -232,23 +236,23 @@ VkDescriptorImageInfo VulkanglTFScene::getTextureDescriptor(const size_t index) */ // Draw a single node including child nodes (if present) -void VulkanglTFScene::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFScene::Node node) +void VulkanglTFScene::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFScene::Node* node) { - if (!node.visible) { + if (!node->visible) { return; } - if (node.mesh.primitives.size() > 0) { + if (node->mesh.primitives.size() > 0) { // Pass the node's matrix via push constants // Traverse the node hierarchy to the top-most parent to get the final matrix of the current node - glm::mat4 nodeMatrix = node.matrix; - VulkanglTFScene::Node* currentParent = node.parent; + glm::mat4 nodeMatrix = node->matrix; + VulkanglTFScene::Node* currentParent = node->parent; while (currentParent) { nodeMatrix = currentParent->matrix * nodeMatrix; currentParent = currentParent->parent; } // Pass the final matrix to the vertex shader using push constants vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &nodeMatrix); - for (VulkanglTFScene::Primitive& primitive : node.mesh.primitives) { + for (VulkanglTFScene::Primitive& primitive : node->mesh.primitives) { if (primitive.indexCount > 0) { VulkanglTFScene::Material& material = materials[primitive.materialIndex]; // POI: Bind the pipeline for the node's material @@ -258,7 +262,7 @@ void VulkanglTFScene::drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout p } } } - for (auto& child : node.children) { + for (auto& child : node->children) { drawNode(commandBuffer, pipelineLayout, child); } } @@ -641,21 +645,21 @@ void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) if (overlay->header("Visibility")) { if (overlay->button("All")) { - std::for_each(glTFScene.nodes.begin(), glTFScene.nodes.end(), [](VulkanglTFScene::Node &node) { node.visible = true; }); + std::for_each(glTFScene.nodes.begin(), glTFScene.nodes.end(), [](VulkanglTFScene::Node* node) { node->visible = true; }); buildCommandBuffers(); } ImGui::SameLine(); if (overlay->button("None")) { - std::for_each(glTFScene.nodes.begin(), glTFScene.nodes.end(), [](VulkanglTFScene::Node &node) { node.visible = false; }); + std::for_each(glTFScene.nodes.begin(), glTFScene.nodes.end(), [](VulkanglTFScene::Node* node) { node->visible = false; }); buildCommandBuffers(); } ImGui::NewLine(); // POI: Create a list of glTF nodes for visibility toggle ImGui::BeginChild("#nodelist", ImVec2(200.0f * overlay->scale, 340.0f * overlay->scale), false); - for (auto &node : glTFScene.nodes) + for (auto& node : glTFScene.nodes) { - if (overlay->checkBox(node.name.c_str(), &node.visible)) + if (overlay->checkBox(node->name.c_str(), &node->visible)) { buildCommandBuffers(); } diff --git a/examples/gltfscenerendering/gltfscenerendering.h b/examples/gltfscenerendering/gltfscenerendering.h index 1e1d673c..b29c90b1 100644 --- a/examples/gltfscenerendering/gltfscenerendering.h +++ b/examples/gltfscenerendering/gltfscenerendering.h @@ -1,7 +1,7 @@ /* * Vulkan Example - Scene rendering * -* Copyright (C) 2020 by Sascha Willems - www.saschawillems.de +* Copyright (C) 2020-2022 by Sascha Willems - www.saschawillems.de * * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) * @@ -76,11 +76,16 @@ public: // A node represents an object in the glTF scene graph struct Node { Node* parent; - std::vector children; + std::vector children; Mesh mesh; glm::mat4 matrix; std::string name; bool visible = true; + ~Node() { + for (auto& child : children) { + delete child; + } + } }; // A glTF material stores information in e.g. the texture that is attached to it and colors @@ -113,7 +118,7 @@ public: std::vector images; std::vector textures; std::vector materials; - std::vector nodes; + std::vector nodes; std::string path; @@ -123,7 +128,7 @@ public: void loadTextures(tinygltf::Model& input); void loadMaterials(tinygltf::Model& input); void loadNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, VulkanglTFScene::Node* parent, std::vector& indexBuffer, std::vector& vertexBuffer); - void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFScene::Node node); + void drawNode(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout, VulkanglTFScene::Node* node); void draw(VkCommandBuffer commandBuffer, VkPipelineLayout pipelineLayout); };