diff --git a/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.cpp b/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.cpp index 4e56b463..3641c384 100644 --- a/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.cpp +++ b/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.cpp @@ -90,7 +90,9 @@ SceneRenderPipeline::SceneRenderPipeline() GBufferMaterial = CreateRef(ImageFormat::RGBA8, defaultSize); GBufferDepth = CreateRef(ImageFormat::D32F, defaultSize, ImageUsage::Depth); - ShadingOutput = CreateRef(ImageFormat::RGBA8, defaultSize); + ShadingOutput = CreateRef(ImageFormat::RGBA16F, defaultSize); + + TonemappedOutput = CreateRef(ImageFormat::RGBA8, defaultSize); // Initialize pipeline VkShaderManager& shaderMgr = VkShaderManager::Get(); @@ -151,7 +153,7 @@ SceneRenderPipeline::SceneRenderPipeline() auto& shadingPass = GBufferPipeline.AddPass("Shading"); shadingPass.SetShaders(shaderMgr.GetShader("shading_vert"), shaderMgr.GetShader("shading_frag")); shadingPass.SetPushConstant(shadingConstant); - shadingPass.AddAttachment("Output", ShadingOutput->GetFormat()); + shadingPass.AddAttachment("ShadingOutput", ShadingOutput->GetFormat()); shadingPass.SetDepthTest(false); shadingPass.AddInput("Albedo"); shadingPass.AddInput("Normal"); @@ -175,6 +177,7 @@ SceneRenderPipeline::SceneRenderPipeline() shadingConstant.DepthTextureID = res.GetBindlessTextureID(GBufferDepth->GetID()); shadingConstant.NormalTextureID = res.GetBindlessTextureID(GBufferNormal->GetID()); shadingConstant.MaterialTextureID = res.GetBindlessTextureID(GBufferMaterial->GetID()); + shadingConstant.AmbientTerm = ctx.scene->GetEnvironment()->AmbientTerm; // Camera shadingConstant.CameraID = ctx.cameraID; @@ -189,7 +192,43 @@ SceneRenderPipeline::SceneRenderPipeline() shadingPass.SetRender([&](PassRenderContext& ctx) { auto& cmd = ctx.commandBuffer; cmd.PushConstants(ctx.renderPass->PipelineLayout, sizeof(ShadingConstant), &shadingConstant); - + + // Draw full screen quad + auto& quadMesh = VkSceneRenderer::QuadMesh; + cmd.BindDescriptorSet(ctx.renderPass->PipelineLayout, quadMesh->GetDescriptorSet(), 1); + cmd.BindIndexBuffer(quadMesh->GetIndexBuffer()->GetBuffer()); + cmd.DrawIndexed(6); + }); + + auto& tonemapPass = GBufferPipeline.AddPass("Tonemap"); + tonemapPass.SetShaders(shaderMgr.GetShader("tonemap_vert"), shaderMgr.GetShader("tonemap_frag")); + tonemapPass.SetPushConstant(tonemapConstant); + tonemapPass.AddAttachment("TonemapOutput", TonemappedOutput->GetFormat()); + tonemapPass.SetDepthTest(false); + tonemapPass.AddInput("ShadingOutput"); + tonemapPass.SetPreRender([&](PassRenderContext& ctx) { + Cmd& cmd = ctx.commandBuffer; + auto& layout = ctx.renderPass->PipelineLayout; + auto& res = GPUResources::Get(); + + // Bindless + cmd.BindDescriptorSet(layout, res.ModelDescriptor, 0); + cmd.BindDescriptorSet(layout, res.SamplerDescriptor, 2); + cmd.BindDescriptorSet(layout, res.MaterialDescriptor, 3); + cmd.BindDescriptorSet(layout, res.TexturesDescriptor, 4); + cmd.BindDescriptorSet(layout, res.LightsDescriptor, 5); + cmd.BindDescriptorSet(layout, res.CamerasDescriptor, 6); + + // Inputs + tonemapConstant.Exposure = ctx.scene->GetEnvironment()->Exposure; + tonemapConstant.SourceTextureID = res.GetBindlessTextureID(ShadingOutput->GetID()); + tonemapConstant.Gamma = ctx.scene->GetEnvironment()->Gamma; + }); + tonemapPass.SetRender([&](PassRenderContext& ctx) + { + auto& cmd = ctx.commandBuffer; + cmd.PushConstants(ctx.renderPass->PipelineLayout, sizeof(TonemapConstant), &tonemapConstant); + // Draw full screen quad auto& quadMesh = VkSceneRenderer::QuadMesh; cmd.BindDescriptorSet(ctx.renderPass->PipelineLayout, quadMesh->GetDescriptorSet(), 1); @@ -213,12 +252,13 @@ void SceneRenderPipeline::Render(PassRenderContext& ctx) GBufferNormal = ResizeImage(GBufferNormal, ctx.resolution); GBufferMaterial = ResizeImage(GBufferMaterial, ctx.resolution); ShadingOutput = ResizeImage(ShadingOutput, ctx.resolution); + TonemappedOutput = ResizeImage(TonemappedOutput, ctx.resolution); PipelineAttachments pipelineInputs { { GBufferAlbedo, GBufferDepth, GBufferNormal, GBufferMaterial }, // GBuffer - { ShadingOutput } // Shading - // ... other passes + { ShadingOutput }, // Shading + { TonemappedOutput } }; GBufferPipeline.Execute(ctx, pipelineInputs); diff --git a/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.h b/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.h index ea2eb66a..be1e7124 100644 --- a/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.h +++ b/Nuake/src/Rendering/Vulkan/SceneRenderPipeline.h @@ -38,6 +38,14 @@ namespace Nuake int LightCount; int CameraID; float CascadeSplits[4]; + float AmbientTerm; + }; + + struct TonemapConstant + { + float Exposure; + float Gamma; + int SourceTextureID; }; // This class handles all the rendering of the scene @@ -55,9 +63,11 @@ namespace Nuake // Attachments Shading Ref ShadingOutput; + Ref TonemappedOutput; + GBufferConstant gbufferConstant; ShadingConstant shadingConstant; - + TonemapConstant tonemapConstant; static RenderPipeline GBufferPipeline; public: @@ -66,7 +76,7 @@ namespace Nuake void SetCamera(UUID camera); void Render(PassRenderContext& ctx); - Ref GetOutput() { return ShadingOutput; } + Ref GetOutput() { return TonemappedOutput; } private: Ref ResizeImage(Ref image, const Vector2& size); diff --git a/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp b/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp index 9adf7bef..39e0426c 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp @@ -32,7 +32,7 @@ #include -bool NKUseValidationLayer = false; +bool NKUseValidationLayer = true; using namespace Nuake; diff --git a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp index ebda0d82..c95bc156 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanSceneRenderer.cpp @@ -63,6 +63,8 @@ void VkSceneRenderer::LoadShaders() shaderMgr.AddShader("shading_vert", shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/shading.vert")); shaderMgr.AddShader("shadow_frag", shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/shadow.frag")); shaderMgr.AddShader("shadow_vert", shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/shadow.vert")); + shaderMgr.AddShader("tonemap_frag", shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/tonemap.frag")); + shaderMgr.AddShader("tonemap_vert", shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/tonemap.vert")); } void VkSceneRenderer::SetGBufferSize(const Vector2& size) diff --git a/Nuake/src/Scene/Components/LightComponent.cpp b/Nuake/src/Scene/Components/LightComponent.cpp index 398f6bb2..9f71e1c2 100644 --- a/Nuake/src/Scene/Components/LightComponent.cpp +++ b/Nuake/src/Scene/Components/LightComponent.cpp @@ -32,10 +32,8 @@ namespace Nuake { for (int i = 0; i < CSM_AMOUNT; i++) { - m_Framebuffers[i] = CreateRef(false, glm::vec2(4096, 4096)); - auto texture = CreateRef(glm::vec2(4096, 4096), GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT); - texture->SetParameter(GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - m_Framebuffers[i]->SetTexture(texture, GL_DEPTH_ATTACHMENT); + m_ShadowMaps[i] = CreateRef(ImageFormat::D32F, Vector2{ 4096, 4096 }, ImageUsage::Depth); + GPUResources::Get().AddTexture(m_ShadowMaps[i]); } } } @@ -43,7 +41,7 @@ namespace Nuake { for (int i = 0; i < CSM_AMOUNT; i++) { - m_Framebuffers[i] = nullptr; + // TODO: Delete old shadowmaps } } } diff --git a/Nuake/src/Scene/Components/LightComponent.h b/Nuake/src/Scene/Components/LightComponent.h index 8ba0defb..3706d669 100644 --- a/Nuake/src/Scene/Components/LightComponent.h +++ b/Nuake/src/Scene/Components/LightComponent.h @@ -2,13 +2,15 @@ #include "Component.h" -#include -#include #include "TransformComponent.h" #include "../Rendering/Camera.h" -#include "src/Rendering/Buffers/Framebuffer.h" #include "VisibilityComponent.h" #include "../Resource/Serializable.h" +#include "src/Rendering/Buffers/Framebuffer.h" +#include "src/Rendering/Vulkan/VulkanImage/VulkanImage.h" + +#include +#include #include namespace Nuake @@ -43,8 +45,7 @@ namespace Nuake bool SyncDirectionWithSky = false; bool CastShadows = false; - - Ref m_Framebuffers[CSM_AMOUNT]; + Ref m_ShadowMaps[CSM_AMOUNT]; Matrix4 mViewProjections[CSM_AMOUNT]; std::vector m_LightViews; static float mCascadeSplitDepth[CSM_AMOUNT]; @@ -55,7 +56,7 @@ namespace Nuake LightComponent(); ~LightComponent() = default; - UUID LightMapID; + std::vector LightMapIDs = std::vector(); void SetCastShadows(bool toggle); Matrix4 GetProjection(); @@ -63,15 +64,8 @@ namespace Nuake void CalculateViewProjection(glm::mat4& view, const glm::mat4& projection) { - Matrix4 normalProj = projection; - - // Convert to normal Z - //normalProj[2][2] = -normalProj[2][2]; // Restore the sign - //normalProj[2][3] = -normalProj[2][3]; // Restore the far depth term sign - - //normalProj *= -1.0f; - glm::mat4 viewProjection = normalProj * view; - glm::mat4 inverseViewProjection = glm::inverse(viewProjection); + Matrix4 viewProjection = projection * view; + Matrix4 inverseViewProjection = glm::inverse(viewProjection); // TODO: Automate this const float nearClip = 0.01f; @@ -79,7 +73,7 @@ namespace Nuake const float clipRange = farClip - nearClip; const float mCascadeNearPlaneOffset = -100.0f; - const float mCascadeFarPlaneOffset = 0.0; + const float mCascadeFarPlaneOffset = 100.0; // Calculate the optimal cascade distances const float minZ = nearClip; @@ -95,16 +89,14 @@ namespace Nuake mCascadeSplits[i] = (d - nearClip) / clipRange; } - mCascadeSplits[0] = 0.01f; - //mCascadeSplits[1] = 0.45f; - //mCascadeSplits[2] = 1.0f; + //mCascadeSplits[0] = 0.01f; float lastSplitDist = 0.0f; // Calculate Orthographic Projection matrix for each cascade for (int cascade = 0; cascade < CSM_AMOUNT; cascade++) { float splitDist = mCascadeSplits[cascade]; - glm::vec4 frustumCorners[8] = + Vector4 frustumCorners[8] = { //Near face { 1.0f, -1.0f, 1.0f, 1.0f }, @@ -122,70 +114,51 @@ namespace Nuake // Project frustum corners into world space from clip space for (int i = 0; i < 8; i++) { - glm::vec4 invCorner = inverseViewProjection * frustumCorners[i]; + Vector4 invCorner = inverseViewProjection * frustumCorners[i]; frustumCorners[i] = invCorner / invCorner.w; } + for (int i = 0; i < CSM_AMOUNT; i++) { - glm::vec4 dist = frustumCorners[i + 4] - frustumCorners[i]; + Vector4 dist = frustumCorners[i + 4] - frustumCorners[i]; frustumCorners[i + 4] = frustumCorners[i] + (dist * splitDist); frustumCorners[i] = frustumCorners[i] + (dist * lastSplitDist); } // Get frustum center - glm::vec3 frustumCenter = glm::vec3(0.0f); + Vector3 frustumCenter = Vector3(0.0f); for (int i = 0; i < 8; i++) - frustumCenter += glm::vec3(frustumCorners[i]); + { + frustumCenter += Vector3(frustumCorners[i]); + } frustumCenter /= 8.0f; // Get the minimum and maximum extents float radius = 0.0f; for (int i = 0; i < 8; i++) { - float distance = glm::length(glm::vec3(frustumCorners[i]) - frustumCenter); + float distance = glm::length(Vector3(frustumCorners[i]) - frustumCenter); radius = glm::max(radius, distance); } radius = std::ceil(radius * 16.0f) / 16.0f; - glm::vec3 maxExtents = glm::vec3(radius); - glm::vec3 minExtents = -maxExtents; + Vector3 maxExtents = Vector3(radius); + Vector3 minExtents = -maxExtents; // Calculate the view and projection matrix - glm::vec3 lightDir = -this->Direction; - lightDir.y *= -1.0f; - lightDir.x *= -1.0f; - lightDir.z *= -1.0f; - glm::mat4 lightViewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, glm::vec3(0.0f, 1.0, 0.0f)); - glm::mat4 lightProjectionMatrix = glm::ortho(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f + mCascadeNearPlaneOffset, maxExtents.z - minExtents.z + mCascadeFarPlaneOffset); + Vector3 lightDir = this->Direction; + Matrix4 lightViewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, Vector3(0.0f, 1.0, 0.0f)); + Matrix4 lightProjectionMatrix = glm::ortho(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f + mCascadeNearPlaneOffset, maxExtents.z - minExtents.z + mCascadeFarPlaneOffset); - //lightDir.y *= -1.0f; - // - //glm::mat4 lightViewMatrix = glm::lookAt( - // frustumCenter + lightDir * -minExtents.z, - // frustumCenter, - // glm::vec3(0.0f, 1.0f, 0.0f) - //); - //glm::mat4 lightProjectionMatrix = glm::ortho( - // minExtents.x, maxExtents.x, - // minExtents.y, maxExtents.y, // Y-flip for Vulkan - // 0.0f + mCascadeNearPlaneOffset, - // maxExtents.z - minExtents.z + mCascadeFarPlaneOffset - //); - //lightProjectionMatrix = glm::ortho(-25.0f, 25.0f, -25.0f, 25.0f, 100.0f, -100.0f); // Offset to texel space to avoid shimmering ->(https://stackoverflow.com/questions/33499053/cascaded-shadow-map-shimmering) - glm::mat4 shadowMatrix = lightProjectionMatrix * lightViewMatrix; - //const float ShadowMapResolution = 4096; - //glm::vec4 shadowOrigin = (shadowMatrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)) * ShadowMapResolution / 2.0f; - //glm::vec4 roundedOrigin = glm::round(shadowOrigin); - //glm::vec4 roundOffset = roundedOrigin - shadowOrigin; - //roundOffset = roundOffset * 2.0f / ShadowMapResolution; - //roundOffset.z = 0.0f; - //roundOffset.w = 0.0f; - //lightProjectionMatrix[3] += roundOffset; - float near_plane = 0.01f, far_plane = 100.0f; - //glm::mat4 lightProjection = glm::ortho(-25.0f, 25.0f, -25.0f, 25.0f, 25.0f, -25.0f); - - //lightProjectionMatrix[2][2] = -lightProjectionMatrix[2][2]; // Flip the sign - //lightProjectionMatrix[2][3] = -lightProjectionMatrix[2][3]; // Flip the sign of the far depth term + Matrix4 shadowMatrix = lightProjectionMatrix * lightViewMatrix; + const float ShadowMapResolution = 4096; + Vector4 shadowOrigin = (shadowMatrix * Vector4(0.0f, 0.0f, 0.0f, 1.0f)) * ShadowMapResolution / 2.0f; + Vector4 roundedOrigin = glm::round(shadowOrigin); + Vector4 roundOffset = roundedOrigin - shadowOrigin; + roundOffset = roundOffset * 2.0f / ShadowMapResolution; + roundOffset.z = 0.0f; + roundOffset.w = 0.0f; + lightProjectionMatrix[3] += roundOffset; m_LightViews[cascade].View = lightViewMatrix; m_LightViews[cascade].Proj = lightProjectionMatrix; @@ -194,14 +167,6 @@ namespace Nuake mCascadeSplitDepth[cascade] = (nearClip + splitDist * clipRange) * 1.0f; mViewProjections[cascade] = shadowMatrix; lastSplitDist = mCascadeSplits[cascade]; - - - - // -----------------------Debug only----------------------- - // RendererDebug::BeginScene(viewProjection); - // RendererDebug::SubmitCameraFrustum(frustumCorners, glm::mat4(1.0f), GetColor(cascade)); // Draws the divided camera frustums - // RendererDebug::SubmitLine(glm::vec3(0.0f, 0.0f, 0.0f), frustumCenter, GetColor(cascade)); // Draws the center of the frustum (A line pointing from origin to the center) - // RendererDebug::EndScene(); } } diff --git a/Resources/Shaders/Vulkan/shading.frag b/Resources/Shaders/Vulkan/shading.frag index c8dafedb..2a843819 100644 --- a/Resources/Shaders/Vulkan/shading.frag +++ b/Resources/Shaders/Vulkan/shading.frag @@ -98,6 +98,7 @@ struct ShadingPushConstant int LightCount; int CameraID; float cascadeDepth[4]; + float AmbientTerm; }; [[vk::push_constant]] @@ -340,7 +341,7 @@ PSOutput main(PSInput input) float3 kD = 1.0 - kS; kD *= 1.0 - metallic; - float3 ambient = (albedo) * ao * 0.5f; + float3 ambient = (albedo) * ao * pushConstants.AmbientTerm; float3 color = (ambient) + Lo; output.oColor0 = float4(color, 1); diff --git a/Resources/Shaders/Vulkan/shading.vert b/Resources/Shaders/Vulkan/shading.vert index dcd6ea01..b3e50819 100644 --- a/Resources/Shaders/Vulkan/shading.vert +++ b/Resources/Shaders/Vulkan/shading.vert @@ -89,6 +89,7 @@ struct ShadingPushConstant int LightCount; int CameraID; float cascadeDepth[4]; + float AmbientTerm; }; [[vk::push_constant]] diff --git a/Resources/Shaders/Vulkan/tonemap.frag b/Resources/Shaders/Vulkan/tonemap.frag new file mode 100644 index 00000000..8a0c8510 --- /dev/null +++ b/Resources/Shaders/Vulkan/tonemap.frag @@ -0,0 +1,132 @@ +// Transforms +struct ModelData +{ + float4x4 model; +}; +[[vk::binding(0, 0)]] +StructuredBuffer model : register(t1); + +// Vertex +struct Vertex +{ + float3 position; + float uv_x; + float3 normal; + float uv_y; + float3 tangent; + float3 bitangent; +}; + +[[vk::binding(0, 1)]] +StructuredBuffer vertexBuffer : register(t2); + +// Samplers +[[vk::binding(0, 2)]] +SamplerState mySampler : register(s0); + +// Materials +struct Material +{ + bool hasAlbedo; + float3 albedo; + bool hasNormal; + bool hasMetalness; + bool hasRoughness; + bool hasAO; + float metalnessValue; + float roughnessValue; + float aoValue; + int albedoTextureId; + int normalTextureId; + int metalnessTextureId; + int roughnessTextureId; + int aoTextureId; +}; +[[vk::binding(0, 3)]] +StructuredBuffer material; + +// Textures +[[vk::binding(0, 4)]] +Texture2D textures[]; + +// Lights +struct Light +{ + float3 position; + int type; + float4 color; + float3 direction; + float outerConeAngle; + float innerConeAngle; + bool castShadow; + int shadowMapTextureId[4]; + int transformId[4]; +}; + +[[vk::binding(0, 5)]] +StructuredBuffer lights; + +// Cameras +struct CameraView { + float4x4 View; + float4x4 Projection; + float4x4 ViewProjection; + float4x4 InverseView; + float4x4 InverseProjection; + float3 Position; + float Near; + float Far; +}; +[[vk::binding(0, 6)]] +StructuredBuffer cameras; + +struct PSInput { + float4 Position : SV_Position; + float2 UV : TEXCOORD0; +}; + +struct PSOutput { + float4 oColor0 : SV_TARGET; +}; + +struct TonemapPushConstant +{ + float Exposure; + float Gamma; + int SourceTextureID; +}; + +[[vk::push_constant]] +TonemapPushConstant pushConstants; + +float3 PBRNeutralToneMapping(float3 color) +{ + const float startCompression = 0.8 - 0.04; + const float desaturation = 0.15; + + float x = min(color.r, min(color.g, color.b)); + float offset = x < 0.08 ? x - 6.25 * x * x : 0.04; + color -= offset; + + float peak = max(color.r, max(color.g, color.b)); + if (peak < startCompression) return color; + + const float d = 1. - startCompression; + float newPeak = 1. - d * d / (peak + d - startCompression); + color *= newPeak / peak; + + float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.); + return lerp(color, newPeak * float3(1, 1, 1), g); +} + +PSOutput main(PSInput input) +{ + PSOutput output; + float3 color = textures[pushConstants.SourceTextureID].Sample(mySampler, input.UV).rgb; + float3 mapped = float3(1.0, 1.0, 1.0) - exp(-color * pushConstants.Exposure); + + color = pow(mapped, float3(pushConstants.Gamma, pushConstants.Gamma, pushConstants.Gamma)); + + output.oColor0 = float4(color, 1); + return output; +} \ No newline at end of file diff --git a/Resources/Shaders/Vulkan/tonemap.vert b/Resources/Shaders/Vulkan/tonemap.vert new file mode 100644 index 00000000..f2f71de7 --- /dev/null +++ b/Resources/Shaders/Vulkan/tonemap.vert @@ -0,0 +1,110 @@ +// Transforms +struct ModelData +{ + float4x4 model; +}; +[[vk::binding(0, 0)]] +StructuredBuffer model : register(t1); + +// Vertex +struct Vertex +{ + float3 position; + float uv_x; + float3 normal; + float uv_y; + float3 tangent; + float3 bitangent; +}; + +[[vk::binding(0, 1)]] +StructuredBuffer vertexBuffer : register(t2); + +// Samplers +[[vk::binding(0, 2)]] +SamplerState mySampler : register(s0); + +// Materials +struct Material +{ + bool hasAlbedo; + float3 albedo; + bool hasNormal; + bool hasMetalness; + bool hasRoughness; + bool hasAO; + float metalnessValue; + float roughnessValue; + float aoValue; + int albedoTextureId; + int normalTextureId; + int metalnessTextureId; + int roughnessTextureId; + int aoTextureId; +}; +[[vk::binding(0, 3)]] +StructuredBuffer material; + +// Textures +[[vk::binding(0, 4)]] +Texture2D textures[]; + +// Lights +struct Light +{ + float3 position; + int type; + float4 color; + float3 direction; + float outerConeAngle; + float innerConeAngle; + bool castShadow; + int shadowMapTextureId[4]; + int transformId[4]; +}; + +[[vk::binding(0, 5)]] +StructuredBuffer lights; + +// Cameras +struct CameraView { + float4x4 View; + float4x4 Projection; + float4x4 ViewProjection; + float4x4 InverseView; + float4x4 InverseProjection; + float3 Position; + float Near; + float Far; +}; +[[vk::binding(0, 6)]] +StructuredBuffer cameras; + +struct TonemapPushConstant +{ + float Exposure; + float Gamma; + int SourceTextureID; +}; + +[[vk::push_constant]] +TonemapPushConstant pushConstants; + +// Outputs +struct VSOutput { + float4 Position : SV_Position; + float2 UV : TEXCOORD0; +}; + + +// Main vertex shader +VSOutput main(uint vertexIndex : SV_VertexID) +{ + VSOutput output; + + Vertex v = vertexBuffer[vertexIndex]; + output.UV = float2(v.uv_x, v.uv_y); + output.Position = float4(v.position, 1.0f); + + return output; +} \ No newline at end of file