diff --git a/Nuake/src/Rendering/Vulkan/PipelineBuilder.cpp b/Nuake/src/Rendering/Vulkan/PipelineBuilder.cpp index f3538866..8afd23ab 100644 --- a/Nuake/src/Rendering/Vulkan/PipelineBuilder.cpp +++ b/Nuake/src/Rendering/Vulkan/PipelineBuilder.cpp @@ -52,8 +52,8 @@ VkPipeline PipelineBuilder::BuildPipeline(VkDevice device) if (ColorBlendAttachment.size() == 0) { - Logger::Log("Forgot blend attachment!", "vulkan", CRITICAL); - assert(false && "Error"); + Logger::Log("Forgot blend attachment?", "vulkan", CRITICAL); + //assert(false && "Error"); } // completely clear VertexInputStateCreateInfo, as we have no need for it diff --git a/Nuake/src/Rendering/Vulkan/VkResources.h b/Nuake/src/Rendering/Vulkan/VkResources.h index 46aad4d8..a9bca3c1 100644 --- a/Nuake/src/Rendering/Vulkan/VkResources.h +++ b/Nuake/src/Rendering/Vulkan/VkResources.h @@ -18,6 +18,18 @@ namespace Nuake { + struct CameraView + { + Matrix4 View; + Matrix4 Projection; + Matrix4 ViewProjection; + Matrix4 InverseView; + Matrix4 InverseProjection; + Vector3 Position; + float Near; + float Far; + }; + struct LightResource { @@ -31,6 +43,7 @@ namespace Nuake std::map> Meshes; std::map> Images; std::map> Light; + std::vector Cameras; // Bindless buffer layouts VkDescriptorSetLayout CameraDescriptorLayout; @@ -41,14 +54,17 @@ namespace Nuake VkDescriptorSetLayout MaterialDescriptorLayout; VkDescriptorSetLayout TexturesDescriptorLayout; VkDescriptorSetLayout LightsDescriptorLayout; + VkDescriptorSetLayout CamerasDescriptorLayout; VkDescriptorSet CameraDescriptor; VkDescriptorSet ModelDescriptor; VkDescriptorSet SamplerDescriptor; VkDescriptorSet MaterialDescriptor; VkDescriptorSet LightsDescriptor; + VkDescriptorSet CamerasDescriptor; std::map BindlessTextureMapping; + std::map CameraMapping; public: VkDescriptorSet TextureDescriptor; @@ -77,11 +93,16 @@ namespace Nuake Ref GetTexture(const UUID& id); std::vector> GetAllTextures(); + void AddCamera(const UUID& id, const CameraView& camera); + CameraView GetCamera(const UUID& id); + std::vector GetAllCameras(); + void ClearCameras(); + std::vector GetBindlessLayout(); uint32_t GetBindlessTextureID(const UUID& id); void RecreateBindlessTextures(); - + void RecreateBindlessCameras(); private: void CreateBindlessLayout(); }; diff --git a/Nuake/src/Rendering/Vulkan/VulkanRenderer.h b/Nuake/src/Rendering/Vulkan/VulkanRenderer.h index 3f420362..19a3abea 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanRenderer.h +++ b/Nuake/src/Rendering/Vulkan/VulkanRenderer.h @@ -130,6 +130,7 @@ namespace Nuake constexpr uint32_t MAX_MODEL_MATRIX = 3000; constexpr uint32_t MAX_MATERIAL = 1000; constexpr uint32_t MAX_TEXTURES = 500; + constexpr uint32_t MAX_CAMERAS = 100; constexpr uint32_t MAX_LIGHTS = 100; class VkRenderer { diff --git a/Nuake/src/Rendering/Vulkan/VulkanResources.cpp b/Nuake/src/Rendering/Vulkan/VulkanResources.cpp index 819f1bcc..6d62cd25 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanResources.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanResources.cpp @@ -119,6 +119,34 @@ std::vector> GPUResources::GetAllTextures() return allImages; } +void GPUResources::AddCamera(const UUID& id, const CameraView& camera) +{ + Cameras.push_back(camera); + CameraMapping[id] = Cameras.size() - 1; +} + +CameraView GPUResources::GetCamera(const UUID& id) +{ + if (CameraMapping.find(id) != CameraMapping.end()) + { + return Cameras[CameraMapping[id]]; + } + + Logger::Log("Camera with ID does not exist", "vulkan", CRITICAL); + return Cameras[0]; +} + +std::vector GPUResources::GetAllCameras() +{ + return Cameras; +} + +void GPUResources::ClearCameras() +{ + Cameras.clear(); + CameraMapping.clear(); +} + void GPUResources::CreateBindlessLayout() { auto& vk = VkRenderer::Get(); @@ -179,7 +207,18 @@ void GPUResources::CreateBindlessLayout() LightsDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS); } - TextureDescriptor = VkRenderer::Get().GetDescriptorAllocator().Allocate(VkRenderer::Get().GetDevice(), TexturesDescriptorLayout); + // bindless cameras + { + DescriptorLayoutBuilder builder; + builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, MAX_CAMERAS); + CamerasDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS); + } + + auto& vk = VkRenderer::Get(); + auto device = vk.GetDevice(); + auto allocator = vk.GetDescriptorAllocator(); + TextureDescriptor = allocator.Allocate(device, TexturesDescriptorLayout); + CamerasDescriptor = allocator.Allocate(device, CamerasDescriptorLayout); } void GPUResources::RecreateBindlessTextures() @@ -210,6 +249,15 @@ void GPUResources::RecreateBindlessTextures() vkUpdateDescriptorSets(VkRenderer::Get().GetDevice(), 1, &write, 0, nullptr); } +void GPUResources::RecreateBindlessCameras() +{ + if (!CamerasDescriptor) + { + CreateBindlessLayout(); + } + +} + std::vector GPUResources::GetBindlessLayout() { std::vector layouts = { diff --git a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp index 4fab4d9f..e1aad85c 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp @@ -18,6 +18,7 @@ #include "Pipeline/RenderPipeline.h" #include "src/Rendering/Vulkan/DescriptorLayoutBuilder.h" +#include using namespace Nuake; @@ -82,10 +83,29 @@ void VkSceneRenderer::BeginScene(RenderContext inContext) throw std::runtime_error("Draw image is not initialized"); } + // Build camera view list + auto view = scene->m_Registry.view(); + for (auto e : view) + { + auto [transform, camera] = view.get(e); + CameraView camData{}; + camData.View = camera.CameraInstance->GetTransform(); + camData.Projection = camera.CameraInstance->GetPerspective(); + camData.InverseView = glm::inverse(camData.Projection); + camData.InverseProjection = glm::inverse(camData.Projection); + camData.Position = transform.GetGlobalTransform()[3]; + camData.Near = camera.CameraInstance->Near; + camData.Far = camera.CameraInstance->Far; + GPUResources::Get().AddCamera(camera.ID, camData); + } + + // Execute light PassRenderContext passCtx = { }; passCtx.scene = inContext.CurrentScene; passCtx.commandBuffer = inContext.CommandBuffer; passCtx.resolution = Context.Size; + + ShadowPipeline.Execute(passCtx); GBufferPipeline.Execute(passCtx); } ModelPushConstant modelPushConstant{}; @@ -262,61 +282,118 @@ void VkSceneRenderer::CreateDescriptors() void VkSceneRenderer::CreatePipelines() { - //ShadowPipeline = RenderPipeline(); - //auto& shadowPass = ShadowPipeline.AddPass("Shadow"); - //shadowPass.AddAttachment("Depth", ImageFormat::D32F, ImageUsage::Depth); - //shadowPass.SetShaders(Shaders["shading_vert"], Shaders["shading_frag"]); - //shadowPass.SetPreRender([&](PassRenderContext& ctx) { - // std::vector descriptors2 = { CameraBufferDescriptors, ModelBufferDescriptor }; - // vkCmdBindDescriptorSets( - // ctx.commandBuffer, - // VK_PIPELINE_BIND_POINT_GRAPHICS, - // ctx.renderPass->PipelineLayout, - // 0, // firstSet - // 2, // descriptorSetCount - // descriptors2.data(), // pointer to the descriptor set(s) - // 0, // dynamicOffsetCount - // nullptr // dynamicOffsets - // ); - // - // // Bind material - // vkCmdBindDescriptorSets( - // ctx.commandBuffer, - // VK_PIPELINE_BIND_POINT_GRAPHICS, - // ctx.renderPass->PipelineLayout, - // 4, // firstSet - // 1, // descriptorSetCount - // &MaterialBufferDescriptor, // pointer to the descriptor set(s) - // 0, // dynamicOffsetCount - // nullptr // dynamicOffsets - // ); - // - // vkCmdBindDescriptorSets( - // ctx.commandBuffer, - // VK_PIPELINE_BIND_POINT_GRAPHICS, - // ctx.renderPass->PipelineLayout, - // 5, // firstSet - // 1, // descriptorSetCount - // &GPUResources::Get().TextureDescriptor, // pointer to the descriptor set(s) - // 0, // dynamicOffsetCount - // nullptr // dynamicOffsets - // ); - // - // vkCmdBindDescriptorSets( - // ctx.commandBuffer, - // VK_PIPELINE_BIND_POINT_GRAPHICS, - // ctx.renderPass->PipelineLayout, - // 6, // firstSet - // 1, // descriptorSetCount - // &LightBufferDescriptor, // pointer to the descriptor set(s) - // 0, // dynamicOffsetCount - // nullptr // dynamicOffsets - // ); - // - // vkCmdBindDescriptorSets(ctx.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx.renderPass->PipelineLayout, 3, 1, //&SamplerDescriptor, 0, nullptr); - //}); - //shadowPass.SetRender([&](PassRenderContext& ctx) {}); + ShadowPipeline = RenderPipeline(); + auto& shadowPass = ShadowPipeline.AddPass("Shadow"); + shadowPass.AddAttachment("Depth", ImageFormat::D32F, ImageUsage::Depth); + shadowPass.SetShaders(Shaders["shadow_vert"], Shaders["shadow_frag"]); + shadowPass.SetPushConstant(modelPushConstant); + shadowPass.SetPreRender([&](PassRenderContext& ctx) { + std::vector descriptors2 = { CameraBufferDescriptors, ModelBufferDescriptor }; + vkCmdBindDescriptorSets( + ctx.commandBuffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + ctx.renderPass->PipelineLayout, + 0, // firstSet + 2, // descriptorSetCount + descriptors2.data(), // pointer to the descriptor set(s) + 0, // dynamicOffsetCount + nullptr // dynamicOffsets + ); + // Bind material + vkCmdBindDescriptorSets( + ctx.commandBuffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + ctx.renderPass->PipelineLayout, + 4, // firstSet + 1, // descriptorSetCount + &MaterialBufferDescriptor, // pointer to the descriptor set(s) + 0, // dynamicOffsetCount + nullptr // dynamicOffsets + ); + + vkCmdBindDescriptorSets( + ctx.commandBuffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + ctx.renderPass->PipelineLayout, + 5, // firstSet + 1, // descriptorSetCount + &GPUResources::Get().TextureDescriptor, // pointer to the descriptor set(s) + 0, // dynamicOffsetCount + nullptr // dynamicOffsets + ); + + vkCmdBindDescriptorSets( + ctx.commandBuffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + ctx.renderPass->PipelineLayout, + 6, // firstSet + 1, // descriptorSetCount + &LightBufferDescriptor, // pointer to the descriptor set(s) + 0, // dynamicOffsetCount + nullptr // dynamicOffsets + ); + + vkCmdBindDescriptorSets(ctx.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx.renderPass->PipelineLayout, 3, 1, &SamplerDescriptor, 0, nullptr); + }); + shadowPass.SetRender([&](PassRenderContext& ctx) { + auto& cmd = ctx.commandBuffer; + auto& scene = ctx.scene; + auto& vk = VkRenderer::Get(); + + // Draw the scene + { + ZoneScopedN("Render Models"); + auto view = scene->m_Registry.view(); + for (auto e : view) + { + auto [transform, mesh, visibility] = view.get(e); + if (!mesh.ModelResource || !visibility.Visible) + { + continue; + } + + Entity entity = Entity((entt::entity)e, scene.get()); + for (auto& m : mesh.ModelResource->GetMeshes()) + { + Ref vkMesh = m->GetVkMesh(); + Matrix4 globalTransform = transform.GetGlobalTransform(); + + auto descSet = vkMesh->GetDescriptorSet(); + vkCmdBindDescriptorSets( + cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + ctx.renderPass->PipelineLayout, + 2, // firstSet + 1, // descriptorSetCount + &descSet, // pointer to the descriptor set(s) + 0, // dynamicOffsetCount + nullptr // dynamicOffsets + ); + + // Bind texture descriptor set + Ref material = m->GetMaterial(); + Ref albedo = GPUResources::Get().GetTexture(material->AlbedoImage); + + modelPushConstant.Index = ModelMatrixMapping[entity.GetID()]; + modelPushConstant.MaterialIndex = MeshMaterialMapping[vkMesh->GetID()]; + + vkCmdPushConstants( + cmd, + ctx.renderPass->PipelineLayout, + VK_SHADER_STAGE_ALL_GRAPHICS, // Stage matching the pipeline layout + 0, // Offset + sizeof(ModelPushConstant), // Size of the push constant + &modelPushConstant // Pointer to the value + ); + + vkCmdBindIndexBuffer(cmd, vkMesh->GetIndexBuffer()->GetBuffer(), 0, VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(cmd, vkMesh->GetIndexBuffer()->GetSize() / sizeof(uint32_t), 1, 0, 0, 0); + } + } + } + }); + ShadowPipeline.Build(); GBufferPipeline = RenderPipeline(); auto& gBufferPass = GBufferPipeline.AddPass("GBuffer"); @@ -332,11 +409,11 @@ void VkSceneRenderer::CreatePipelines() ctx.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx.renderPass->PipelineLayout, - 0, // firstSet - 2, // descriptorSetCount - descriptors2.data(), // pointer to the descriptor set(s) - 0, // dynamicOffsetCount - nullptr // dynamicOffsets + 0, // firstSet + 2, // descriptorSetCount + descriptors2.data(), // pointer to the descriptor set(s) + 0, // dynamicOffsetCount + nullptr // dynamicOffsets ); // Bind material @@ -433,7 +510,6 @@ void VkSceneRenderer::CreatePipelines() } }); - auto& shadingPass = GBufferPipeline.AddPass("Shading"); shadingPass.SetShaders(Shaders["shading_vert"], Shaders["shading_frag"]); diff --git a/Nuake/src/Scene/Components/CameraComponent.h b/Nuake/src/Scene/Components/CameraComponent.h index f4f1cf2d..07be17c7 100644 --- a/Nuake/src/Scene/Components/CameraComponent.h +++ b/Nuake/src/Scene/Components/CameraComponent.h @@ -6,6 +6,7 @@ #include "src/Core/Core.h" #include "src/Resource/Serializable.h" #include "src/Rendering/Camera.h" +#include "src/Resource/UUID.h" namespace Nuake { @@ -13,8 +14,8 @@ namespace Nuake class CameraComponent : public Component { NUAKECOMPONENT(CameraComponent, "Camera") - public: + UUID ID; Ref CameraInstance; TransformComponent* transformComponent; diff --git a/Resources/Shaders/Vulkan/shadow.frag b/Resources/Shaders/Vulkan/shadow.frag index 69163454..2f8af951 100644 --- a/Resources/Shaders/Vulkan/shadow.frag +++ b/Resources/Shaders/Vulkan/shadow.frag @@ -54,16 +54,10 @@ StructuredBuffer lights; struct PSInput { float4 Position : SV_Position; - float3 Color : TEXCOORD0; - float2 UV : TEXCOORD1; - float3 Normal : TEXCOORD2; - float3x3 TBN : TEXCOORD3; }; struct PSOutput { float4 oColor0 : SV_TARGET; - float4 oNormal : SV_TARGET1; - float4 oMaterial : SV_TARGET2; }; struct ModelPushConstant @@ -78,59 +72,5 @@ ModelPushConstant pushConstants; PSOutput main(PSInput input) { PSOutput output; - - Material inMaterial = material[pushConstants.materialIndex]; - // NORMAL - // TODO use TBN matrix - float3 normal = float3(0.5, 0.5, 1.0); - if(inMaterial.hasNormal == 1) - { - // Sample from texture. - } - - normal = mul(input.TBN, normal); - normal = input.Normal / 2.0f + 0.5f; - output.oNormal = float4(normal, 1.0f); - - // MATERIAL - - // ALBEDO COLOR - float4 albedoColor = float4(inMaterial.albedo.xyz, 1.0f); - if(inMaterial.hasAlbedo == 1) - { - float4 albedoSample = textures[inMaterial.albedoTextureId].Sample(mySampler, input.UV); - - // Alpha cutout? - if(albedoSample.a < 0.001f) - { - discard; - } - - albedoColor.xyz = albedoSample.xyz; - } - output.oColor0 = albedoColor; - - // MATERIAL PROPERTIES - float metalnessValue = inMaterial.metalnessValue; - if(inMaterial.hasMetalness == 1) - { - // TODO: Sample from metal texture - } - - float aoValue = inMaterial.aoValue; - if(inMaterial.hasAO == 1) - { - // TODO: Sample from AO texture - } - - float roughnessValue = inMaterial.roughnessValue; - if(inMaterial.hasRoughness == 1) - { - // TODO: Sample from roughness texture - } - - float3 materialOuput = float3(inMaterial.metalnessValue, inMaterial.aoValue, inMaterial.roughnessValue); - - output.oMaterial = float4(materialOuput, 1.0f); return output; } \ No newline at end of file diff --git a/Resources/Shaders/Vulkan/shadow.vert b/Resources/Shaders/Vulkan/shadow.vert index 2cafa98c..089ea79f 100644 --- a/Resources/Shaders/Vulkan/shadow.vert +++ b/Resources/Shaders/Vulkan/shadow.vert @@ -57,10 +57,6 @@ ModelPushConstant pushConstants; // Outputs struct VSOutput { float4 Position : SV_Position; - float3 Color : TEXCOORD0; - float2 UV : TEXCOORD1; - float3 Normal : TEXCOORD2; - float3x3 TBN : TEXCOORD3; }; // Main vertex shader @@ -69,7 +65,6 @@ VSOutput main(uint vertexIndex : SV_VertexID) VSOutput output; Camera camData = camera[0]; - ModelData modelData = model[pushConstants.modelIndex]; // Load vertex data from the buffer @@ -77,13 +72,6 @@ VSOutput main(uint vertexIndex : SV_VertexID) // Output the position of each vertex output.Position = mul(camData.proj, mul(camData.view, mul(modelData.model, float4(v.position, 1.0f)))); - output.Color = normalize(float3(v.position.xyz)); - output.UV = float2(v.uv_x, v.uv_y); - output.Normal = normalize(v.normal); - float3 T = normalize(mul((float3x3)modelData.model, normalize(v.tangent.xyz))); - float3 B = normalize(mul((float3x3)modelData.model, normalize(v.bitangent.xyz))); - float3 N = normalize(mul((float3x3)modelData.model, normalize(v.normal)).xyz); - output.TBN = transpose(float3x3(T, B, N)); return output; } \ No newline at end of file