diff --git a/Nuake/src/Rendering/Vulkan/DescriptorLayoutBuilder.cpp b/Nuake/src/Rendering/Vulkan/DescriptorLayoutBuilder.cpp index 26f938ed..90d43598 100644 --- a/Nuake/src/Rendering/Vulkan/DescriptorLayoutBuilder.cpp +++ b/Nuake/src/Rendering/Vulkan/DescriptorLayoutBuilder.cpp @@ -4,11 +4,11 @@ using namespace Nuake; -void DescriptorLayoutBuilder::AddBinding(uint32_t binding, VkDescriptorType type) +void DescriptorLayoutBuilder::AddBinding(uint32_t binding, VkDescriptorType type, uint32_t count) { VkDescriptorSetLayoutBinding newbind{}; newbind.binding = binding; - newbind.descriptorCount = 1; + newbind.descriptorCount = count; newbind.descriptorType = type; Bindings.push_back(newbind); diff --git a/Nuake/src/Rendering/Vulkan/DescriptorLayoutBuilder.h b/Nuake/src/Rendering/Vulkan/DescriptorLayoutBuilder.h index 8b707e7f..805bc204 100644 --- a/Nuake/src/Rendering/Vulkan/DescriptorLayoutBuilder.h +++ b/Nuake/src/Rendering/Vulkan/DescriptorLayoutBuilder.h @@ -10,7 +10,7 @@ namespace Nuake { std::vector Bindings; - void AddBinding(uint32_t binding, VkDescriptorType type); + void AddBinding(uint32_t binding, VkDescriptorType type, uint32_t count = 1); void Clear(); VkDescriptorSetLayout Build(VkDevice device, VkShaderStageFlags shaderStages, void* pNext = nullptr, VkDescriptorSetLayoutCreateFlags flags = 0); }; diff --git a/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.cpp b/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.cpp index a7704e93..cbdd5045 100644 --- a/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.cpp +++ b/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.cpp @@ -21,7 +21,8 @@ TextureAttachment::TextureAttachment(const std::string& name, ImageFormat format } RenderPass::RenderPass(const std::string& name) : - Name(name) + Name(name), + PushConstantSize(0) { } @@ -45,7 +46,7 @@ void RenderPass::ClearAttachments(PassRenderContext& ctx) // TODO: Queue deletion of old textures } - if (DepthAttachment.Image->GetSize() != ctx.resolution) + if (DepthAttachment.Image && DepthAttachment.Image->GetSize() != ctx.resolution) { Ref newDepthAttachment = std::make_shared(DepthAttachment.Format, ctx.resolution, ImageUsage::Depth); DepthAttachment.Image = newDepthAttachment; @@ -74,7 +75,25 @@ void RenderPass::TransitionAttachments(PassRenderContext& ctx) } // Transition depth attachment - VulkanUtil::TransitionImage(ctx.commandBuffer, DepthAttachment.Image->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL); + if (DepthAttachment.Image) + { + VulkanUtil::TransitionImage(ctx.commandBuffer, DepthAttachment.Image->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL); + } +} + +void RenderPass::UntransitionAttachments(PassRenderContext& ctx) +{ + for (auto& attachment : Attachments) + { + // Transform from color attachment to transfer src for next pass + VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); + } + + if (DepthAttachment.Image) + { + //VulkanUtil::TransitionImage(ctx.commandBuffer, DepthAttachment.Image->GetImage(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); + } } void RenderPass::Render(PassRenderContext& ctx) @@ -96,9 +115,13 @@ void RenderPass::Render(PassRenderContext& ctx) renderAttachmentInfos.push_back(attachmentInfo); } - VkRenderingAttachmentInfo depthAttachmentInfo = VulkanInit::DepthAttachmentInfo(DepthAttachment.Image->GetImageView(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL); + VkRenderingAttachmentInfo depthAttachmentInfo = {}; + if (DepthAttachment.Image) + { + depthAttachmentInfo = VulkanInit::DepthAttachmentInfo(DepthAttachment.Image->GetImageView(), VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL); + } - VkRenderingInfo renderInfo = VulkanInit::RenderingInfo(ctx.resolution, renderAttachmentInfos, &depthAttachmentInfo); + VkRenderingInfo renderInfo = VulkanInit::RenderingInfo(ctx.resolution, renderAttachmentInfos, !DepthAttachment.Image ? nullptr : &depthAttachmentInfo); renderInfo.colorAttachmentCount = std::size(renderAttachmentInfos); renderInfo.pColorAttachments = renderAttachmentInfos.data(); @@ -132,12 +155,7 @@ void RenderPass::Render(PassRenderContext& ctx) vkCmdEndRendering(ctx.commandBuffer); // End rendering - for (auto& attachment : Attachments) - { - // Transform from color attachment to transfer src for next pass - VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - VulkanUtil::TransitionImage(ctx.commandBuffer, attachment.Image->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); - } + if (PostRender) { @@ -172,9 +190,9 @@ TextureAttachment& RenderPass::GetAttachment(const std::string& name) return Attachments[0]; } -std::vector RenderPass::GetAttachments() +std::vector RenderPass::GetAttachments() { - std::vector attachentRefs; + std::vector attachentRefs; attachentRefs.reserve(Attachments.size()); for (auto& attachment : Attachments) { @@ -188,12 +206,12 @@ void RenderPass::AddInput(const std::string& name) InputNames.push_back(name); } -std::vector Nuake::RenderPass::GetInputs() +std::vector RenderPass::GetInputs() { return InputNames; } -void RenderPass::SetInput(const std::string& name, TextureAttachment& attachment) +void RenderPass::SetInput(const std::string& name, TextureAttachment attachment) { Inputs[name] = attachment; } @@ -207,10 +225,16 @@ void RenderPass::SetShaders(Ref vertShader, Ref frag void RenderPass::Build() { // Push constant range + uint32_t pushRange = 0; VkPushConstantRange bufferRange{}; - bufferRange.offset = 0; - bufferRange.size = PushConstantSize; - bufferRange.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; + if (PushConstantSize > 0) + { + bufferRange.offset = 0; + bufferRange.size = PushConstantSize; + bufferRange.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; + + pushRange = 1; + } // TODO: Get the bindless descriptor layout std::vector layouts = GPUResources::Get().GetBindlessLayout(); @@ -218,7 +242,7 @@ void RenderPass::Build() // Create pipeline layout VkPipelineLayoutCreateInfo pipeline_layout_info = VulkanInit::PipelineLayoutCreateInfo(); pipeline_layout_info.pPushConstantRanges = &bufferRange; - pipeline_layout_info.pushConstantRangeCount = 1; + pipeline_layout_info.pushConstantRangeCount = pushRange; pipeline_layout_info.pSetLayouts = layouts.data(); pipeline_layout_info.setLayoutCount = layouts.size(); @@ -283,26 +307,43 @@ RenderPass& RenderPipeline::GetRenderPass(const std::string& name) bool RenderPipeline::Build() { - std::map attachments; + std::map attachments; for (auto& pass : RenderPasses) { pass.Build(); for (auto& input : pass.GetInputs()) { + bool alreadyFoundAttachment = false; if (attachments.find(input) == attachments.end()) { - Logger::Log("Failed to build RenderPipeline. input " + input + " not found in previous passes.", "vulkan", CRITICAL); - return false; + if (pass.GetDepthAttachment().Image && pass.GetDepthAttachment().Name == input) + { + pass.SetInput(input, pass.GetDepthAttachment()); + alreadyFoundAttachment = true; + } + else + { + Logger::Log("Failed to build RenderPipeline. input " + input + " not found in previous passes.", "vulkan", CRITICAL); + return false; + } } - pass.SetInput(input, attachments[input]); + if (!alreadyFoundAttachment) + { + pass.SetInput(input, attachments[input]); + } } for (auto& attachment : pass.GetAttachments()) { attachments[attachment.Name] = attachment; } + + if (pass.GetDepthAttachment().Image) + { + attachments[pass.GetDepthAttachment().Name] = pass.GetDepthAttachment(); + } } for (auto& pass : RenderPasses) @@ -325,6 +366,7 @@ void RenderPipeline::Execute(PassRenderContext& ctx) pass.ClearAttachments(ctx); pass.TransitionAttachments(ctx); pass.Render(ctx); + pass.UntransitionAttachments(ctx); } } diff --git a/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.h b/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.h index 66a41b2e..cd0dc3c5 100644 --- a/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.h +++ b/Nuake/src/Rendering/Vulkan/Pipeline/RenderPipeline.h @@ -73,18 +73,20 @@ namespace Nuake void ClearAttachments(PassRenderContext& ctx); void TransitionAttachments(PassRenderContext& ctx); + void UntransitionAttachments(PassRenderContext& ctx); void Render(PassRenderContext& ctx); public: std::string GetName() const { return Name; } TextureAttachment& AddAttachment(const std::string& name, ImageFormat format, ImageUsage usage = ImageUsage::Default); TextureAttachment& GetAttachment(const std::string& name); - std::vector GetAttachments(); + std::vector GetAttachments(); void AddInput(const std::string& name); std::vector GetInputs(); + TextureAttachment& GetDepthAttachment() { return DepthAttachment; } - void SetInput(const std::string& name, TextureAttachment& attachment); + void SetInput(const std::string& name, TextureAttachment attachment); void SetShaders(Ref vertShader, Ref fragShader); template @@ -109,9 +111,7 @@ namespace Nuake { private: bool Built; - std::vector RenderPasses; - public: RenderPipeline(); diff --git a/Nuake/src/Rendering/Vulkan/VkResources.h b/Nuake/src/Rendering/Vulkan/VkResources.h index 57c1a25a..019c9847 100644 --- a/Nuake/src/Rendering/Vulkan/VkResources.h +++ b/Nuake/src/Rendering/Vulkan/VkResources.h @@ -30,11 +30,13 @@ namespace Nuake VkDescriptorSetLayout ImageDescriptorLayout; VkDescriptorSetLayout SamplerDescriptorLayout; VkDescriptorSetLayout MaterialDescriptorLayout; + VkDescriptorSetLayout TexturesDescriptorLayout; VkDescriptorSet CameraDescriptor; VkDescriptorSet ModelDescriptor; VkDescriptorSet SamplerDescriptor; VkDescriptorSet MaterialDescriptor; + VkDescriptorSet TextureDescriptor; public: static GPUResources& Get() @@ -60,6 +62,7 @@ namespace Nuake bool AddTexture(Ref image); Ref GetTexture(const UUID& id); + std::vector> GetAllTextures(); std::vector GetBindlessLayout(); diff --git a/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.cpp b/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.cpp index 35082161..09f961f2 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.cpp @@ -110,6 +110,7 @@ VulkanImage::VulkanImage(ImageFormat inFormat, Vector2 inSize, ImageUsage usage) else if (usage == ImageUsage::Depth) { drawImageUsages |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + drawImageUsages |= VK_IMAGE_USAGE_SAMPLED_BIT; } VkImageCreateInfo imgCreateInfo = VulkanInit::ImageCreateInfo(static_cast(inFormat), drawImageUsages, vkExtent); diff --git a/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp b/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp index dbcc504f..e037c6a9 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp @@ -514,7 +514,6 @@ void VkRenderer::InitTrianglePipeline() void VkRenderer::DrawScene(RenderContext ctx) { SceneRenderer->BeginScene(ctx); - SceneRenderer->DrawScene(); SceneRenderer->EndScene(); } diff --git a/Nuake/src/Rendering/Vulkan/VulkanRenderer.h b/Nuake/src/Rendering/Vulkan/VulkanRenderer.h index 31b63ad2..4eff016a 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanRenderer.h +++ b/Nuake/src/Rendering/Vulkan/VulkanRenderer.h @@ -125,6 +125,7 @@ namespace Nuake constexpr uint32_t FRAME_OVERLAP = 2; constexpr uint32_t MAX_MODEL_MATRIX = 3000; constexpr uint32_t MAX_MATERIAL = 1000; + constexpr uint32_t MAX_TEXTURES = 500; class VkRenderer { diff --git a/Nuake/src/Rendering/Vulkan/VulkanResources.cpp b/Nuake/src/Rendering/Vulkan/VulkanResources.cpp index a993fd12..b2096d1e 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanResources.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanResources.cpp @@ -108,6 +108,17 @@ Ref GPUResources::GetTexture(const UUID& id) return TextureManager::Get()->GetTexture2("missing_texture"); } +std::vector> GPUResources::GetAllTextures() +{ + std::vector> allImages; + allImages.reserve(Images.size()); + for (const auto& [id, image] : Images) + { + allImages.push_back(image); + } + return allImages; +} + void GPUResources::CreateBindlessLayout() { auto& vk = VkRenderer::Get(); @@ -153,6 +164,13 @@ void GPUResources::CreateBindlessLayout() builder.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); MaterialDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_FRAGMENT_BIT); } + + // Textures + { + DescriptorLayoutBuilder builder; + builder.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MAX_TEXTURES); + TexturesDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS); + } } std::vector GPUResources::GetBindlessLayout() @@ -163,7 +181,8 @@ std::vector GPUResources::GetBindlessLayout() TriangleBufferDescriptorLayout, ImageDescriptorLayout, SamplerDescriptorLayout, - MaterialDescriptorLayout + MaterialDescriptorLayout, + TexturesDescriptorLayout }; return layouts; } \ No newline at end of file diff --git a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp index 19ebd964..4520838e 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp @@ -52,6 +52,8 @@ void VkSceneRenderer::BeginScene(RenderContext inContext) BuildMatrixBuffer(); UpdateTransformBuffer(); + + auto& cmd = Context.CommandBuffer; auto& scene = Context.CurrentScene; auto& vk = VkRenderer::Get(); @@ -107,6 +109,8 @@ void VkSceneRenderer::LoadShaders() ShaderCompiler& shaderCompiler = ShaderCompiler::Get(); Shaders["basic_frag"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/triangle.frag"); Shaders["basic_vert"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/triangle.vert"); + Shaders["shading_frag"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/shading.frag"); + Shaders["shading_vert"] = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/shading.vert"); } void VkSceneRenderer::CreateSamplers() @@ -170,12 +174,20 @@ void VkSceneRenderer::CreateDescriptors() MaterialBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_FRAGMENT_BIT); } + //Bindless Textures + { + DescriptorLayoutBuilder builder; + builder.AddBinding(0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MAX_TEXTURES); + TextureBufferDescriptorLayout = builder.Build(device, VK_SHADER_STAGE_ALL_GRAPHICS); + } + auto allocator = vk.GetDescriptorAllocator(); TriangleBufferDescriptors = allocator.Allocate(device, TriangleBufferDescriptorLayout); CameraBufferDescriptors = allocator.Allocate(device, CameraBufferDescriptorLayout); ModelBufferDescriptor = allocator.Allocate(device, ModelBufferDescriptorLayout); SamplerDescriptor = allocator.Allocate(device, SamplerDescriptorLayout); MaterialBufferDescriptor = allocator.Allocate(device, MaterialBufferDescriptorLayout); + TextureBufferDescriptor = allocator.Allocate(device, TextureBufferDescriptorLayout); //SamplerDescriptor = allocator.Allocate(device, SamplerDescriptorLayout); // Update descriptor set for camera @@ -209,6 +221,9 @@ void VkSceneRenderer::CreateDescriptors() samplerWrite.pImageInfo = &textureInfo; // Sampler info (same as texture) vkUpdateDescriptorSets(device, 1, &samplerWrite, 0, nullptr); + + // Textures + } void VkSceneRenderer::CreatePipelines() @@ -247,6 +262,17 @@ void VkSceneRenderer::CreatePipelines() 0, // dynamicOffsetCount nullptr // dynamicOffsets ); + + vkCmdBindDescriptorSets( + ctx.commandBuffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + ctx.renderPass->PipelineLayout, + 6, // firstSet + 1, // descriptorSetCount + &TextureBufferDescriptor, // pointer to the descriptor set(s) + 0, // dynamicOffsetCount + nullptr // dynamicOffsets + ); }); gBufferPass.SetRender([&](PassRenderContext& ctx){ @@ -321,10 +347,17 @@ void VkSceneRenderer::CreatePipelines() }); auto& shadingPass = GBufferPipeline.AddPass("Shading"); - + shadingPass.SetShaders(Shaders["shading_vert"], Shaders["shading_frag"]); + shadingPass.SetPushConstant(modelPushConstant); shadingPass.AddAttachment("Output", ImageFormat::RGBA16F); + shadingPass.AddAttachment("DepthShading", ImageFormat::D32F, ImageUsage::Depth); + shadingPass.AddInput("Albedo"); + shadingPass.AddInput("Normal"); + shadingPass.AddInput("Material"); + shadingPass.AddInput("Depth"); - + shadingPass.SetPreRender([](PassRenderContext& ctx) {}); + shadingPass.SetRender([](PassRenderContext& ctx) {}); GBufferPipeline.Build(); } @@ -488,6 +521,25 @@ void VkSceneRenderer::UpdateTransformBuffer() bufferWrite.descriptorCount = 1; bufferWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; bufferWrite.pBufferInfo = &bufferInfo; + bufferWrite.pImageInfo = VK_NULL_HANDLE; vkUpdateDescriptorSets(VkRenderer::Get().GetDevice(), 1, &bufferWrite, 0, nullptr); } + + auto allTextures = GPUResources::Get().GetAllTextures(); + std::vector imageInfos(allTextures.size()); + for (size_t i = 0; i < allTextures.size(); i++) { + imageInfos[i].imageView = allTextures[i]->GetImageView(); + imageInfos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + + VkWriteDescriptorSet write{}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.dstSet = TextureBufferDescriptor; + write.dstBinding = 0; // Binding 0 + write.dstArrayElement = 0; + write.descriptorCount = static_cast(imageInfos.size()); + write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + write.pImageInfo = imageInfos.data(); + + vkUpdateDescriptorSets(VkRenderer::Get().GetDevice(), 1, &write, 0, nullptr); } \ No newline at end of file diff --git a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.h b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.h index bd9f17f0..3b81dc4b 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.h +++ b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.h @@ -74,6 +74,10 @@ namespace Nuake VkDescriptorSet MaterialBufferDescriptor; VkDescriptorSetLayout MaterialBufferDescriptorLayout; + Ref TextureBuffer; + VkDescriptorSet TextureBufferDescriptor; + VkDescriptorSetLayout TextureBufferDescriptorLayout; + ModelData ModelTransforms; MaterialData MaterialDataContainer; diff --git a/Resources/Shaders/Vulkan/shading.frag b/Resources/Shaders/Vulkan/shading.frag new file mode 100644 index 00000000..60cece66 --- /dev/null +++ b/Resources/Shaders/Vulkan/shading.frag @@ -0,0 +1,103 @@ +[[vk::binding(0, 3)]] +Texture2D albedo : register(t1); // Texture binding at slot t0 + +[[vk::binding(0, 4)]] +SamplerState mySampler : register(s0); // Sampler binding at slot s0 + +struct Material +{ + float hasAlbedo; + float3 albedo; + int hasNormal; + int hasMetalness; + int hasRoughness; + int hasAO; + float metalnessValue; + float roughnessValue; + float aoValue; +}; +[[vk::binding(0, 5)]] +StructuredBuffer material; + +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 +{ + int modelIndex; // Push constant data + int materialIndex; +}; + +[[vk::push_constant]] +ModelPushConstant pushConstants; + +PSOutput main(PSInput input) +{ + PSOutput output; + + Material inMaterial = material[pushConstants.materialIndex]; + // NORMAL + // TODO use TBN matrix + float3 normal = float3(0.0, 0.0f, 1.0f); + if(inMaterial.hasNormal == 1) + { + // Sample from texture. + } + + normal = mul(input.TBN, normal); + normal = 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 albedoTextureSample = albedo.Sample(mySampler, input.UV); + + // Alpha cutout? + if(albedoTextureSample.a < 0.001f) + { + discard; + } + + albedoColor.xyz = albedoTextureSample.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/shading.vert b/Resources/Shaders/Vulkan/shading.vert new file mode 100644 index 00000000..a01bd138 --- /dev/null +++ b/Resources/Shaders/Vulkan/shading.vert @@ -0,0 +1,70 @@ +struct Camera +{ + float4x4 view; + float4x4 proj; +}; +[[vk::binding(0, 0)]] +StructuredBuffer camera : register(t0); + +struct ModelData +{ + float4x4 model; +}; +[[vk::binding(0, 1)]] +StructuredBuffer model : register(t1); + +struct Vertex +{ + float3 position; + float uv_x; + float3 normal; + float uv_y; + float3 tangent; + float3 bitangent; +}; + +[[vk::binding(0, 2)]] +StructuredBuffer vertexBuffer : register(t2); + +struct ModelPushConstant +{ + int modelIndex; // Push constant data + int materialIndex; +}; + +[[vk::push_constant]] +ModelPushConstant pushConstants; + +// Outputs +struct VSOutput { + float4 Position : SV_Position; + float3 Color : TEXCOORD0; + float2 UV : TEXCOORD1; + float3 Normal : TEXCOORD2; + float3x3 TBN : TEXCOORD3; +}; + +// Main vertex shader +VSOutput main(uint vertexIndex : SV_VertexID) +{ + VSOutput output; + + Camera camData = camera[0]; + + ModelData modelData = model[pushConstants.modelIndex]; + + // Load vertex data from the buffer + Vertex v = vertexBuffer[vertexIndex]; + + // 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 diff --git a/Resources/Shaders/Vulkan/triangle.frag b/Resources/Shaders/Vulkan/triangle.frag index 60cece66..519ab49f 100644 --- a/Resources/Shaders/Vulkan/triangle.frag +++ b/Resources/Shaders/Vulkan/triangle.frag @@ -19,6 +19,9 @@ struct Material [[vk::binding(0, 5)]] StructuredBuffer material; +[[vk::binding(0, 6)]] +Texture2D textures[]; + struct PSInput { float4 Position : SV_Position; float3 Color : TEXCOORD0; @@ -65,6 +68,7 @@ PSOutput main(PSInput input) float4 albedoColor = float4(inMaterial.albedo.xyz, 1.0f); if(inMaterial.hasAlbedo == 1) { + float4 testTexture = textures[pushConstants.modelIndex].Sample(mySampler, input.UV); float4 albedoTextureSample = albedo.Sample(mySampler, input.UV); // Alpha cutout? @@ -73,7 +77,7 @@ PSOutput main(PSInput input) discard; } - albedoColor.xyz = albedoTextureSample.xyz; + albedoColor.xyz = testTexture.xyz * albedoTextureSample.xyz; } output.oColor0 = albedoColor; diff --git a/Resources/Shaders/Vulkan/triangle.vert.hlsl b/Resources/Shaders/Vulkan/triangle.vert.hlsl deleted file mode 100644 index 35745b97..00000000 --- a/Resources/Shaders/Vulkan/triangle.vert.hlsl +++ /dev/null @@ -1,39 +0,0 @@ -struct Vertex -{ - float3 position; - float uv_x; - float3 normal; - float uv_y; - float4 color; -}; - -// Define the structured buffer for vertices -StructuredBuffer vertexBuffer : register(t0); // Binding of vertex buffer (example: t0) - -// Define push constants block -cbuffer PushConstants : register(b0) { // Push constants binding (example: b0) - float4x4 render_matrix; // Matrix for rendering - uint64_t vertexBufferAddress; // Buffer reference address (Vulkan-specific handling required) -}; - -// Outputs -struct VSOutput { - float4 Position : SV_Position; - float3 Color : TEXCOORD0; - float2 UV : TEXCOORD1; -}; - -// Main vertex shader -VSOutput main(uint vertexIndex : SV_VertexID) { - VSOutput output; - - // Load vertex data from the buffer - Vertex v = vertexBuffer[vertexIndex]; - - // Transform and output vertex data - output.Position = mul(render_matrix, float4(v.position, 1.0f)); - output.Color = v.color.xyz; - output.UV = float2(v.uv_x, v.uv_y); - - return output; -} \ No newline at end of file