diff --git a/Data/Shaders/Vulkan/depth_aware_blur.frag b/Data/Shaders/Vulkan/depth_aware_blur.frag new file mode 100644 index 00000000..8e8fd5ae --- /dev/null +++ b/Data/Shaders/Vulkan/depth_aware_blur.frag @@ -0,0 +1,160 @@ +// 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 DepthAwareBlurConstant +{ + int DepthTextureID; + int VolumetricTextureID; +}; + +[[vk::push_constant]] +DepthAwareBlurConstant pushConstants; + +float2 GetTextureSize(Texture2D tex) +{ + uint width, height; + tex.GetDimensions(width, height); + return float2(width, height); +} + +float PixelToUV(float2 uv, Texture2D tex) +{ + float2 texSize = GetTextureSize(tex); + return uv / texSize; +} + +PSOutput main(PSInput input) +{ + int depthTexture = pushConstants.DepthTextureID; + float upSampledDepth = textures[depthTexture].Sample(mySampler, input.UV).r; + float3 upSampledColor = textures[pushConstants.VolumetricTextureID].Sample(mySampler, input.UV).rgb; + float3 color = 0.0f.xxx; + float totalWeight = 0.0f; + + int2 screenCoordinates = int2(input.Position.xy); + int xOffset = (screenCoordinates.x % 2 == 0) ? -1 : 1; + int yOffset = (screenCoordinates.y % 2 == 0) ? -1 : 1; + + int2 offsets[] = {int2(0, 0), + int2(0, yOffset), + int2(xOffset, 0), + int2(xOffset, yOffset)}; + + for (int i = 0; i < 4; i ++) + { + float2 uvOffset = float2(offsets[i].x * 4.0, offsets[i].y * 4.0) ; + uvOffset = PixelToUV(uvOffset, textures[pushConstants.DepthTextureID]); + float3 downscaledColor = textures[pushConstants.VolumetricTextureID].Sample(mySampler, input.UV + uvOffset).rgb; + float downscaledDepth = textures[pushConstants.DepthTextureID].Sample(mySampler, input.UV + uvOffset).r; + + float currentWeight = 1.0f; + + if(abs(upSampledDepth - downscaledDepth) > 0.0001) + { + //color = float3(1, 0, 0); + currentWeight *= 0.0f; + } + //currentWeight *= max(0.0f, 1.0f - abs(upSampledDepth - downscaledDepth)); + + color += downscaledColor * currentWeight; + totalWeight += currentWeight; + } + + float3 volumetricLight; + const float epsilon = 0.0001f; + volumetricLight.xyz = color / (totalWeight + epsilon); + + PSOutput output; + output.oColor0 = float4(volumetricLight.x, volumetricLight.y, volumetricLight.z, 1.0f); + //output.oColor0 = float4(upSampledColor.x, upSampledColor.y, upSampledColor.z, 1.0f); + return output; +} \ No newline at end of file diff --git a/Data/Shaders/Vulkan/depth_aware_blur.vert b/Data/Shaders/Vulkan/depth_aware_blur.vert new file mode 100644 index 00000000..39eb8c10 --- /dev/null +++ b/Data/Shaders/Vulkan/depth_aware_blur.vert @@ -0,0 +1,109 @@ +// 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 DepthAwareBlurConstant +{ + int DepthTextureID; + int VolumetricTextureID; +}; + +[[vk::push_constant]] +DepthAwareBlurConstant 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 diff --git a/Data/Shaders/Vulkan/volumetric.frag b/Data/Shaders/Vulkan/volumetric.frag index 53e4136f..f59b2c25 100644 --- a/Data/Shaders/Vulkan/volumetric.frag +++ b/Data/Shaders/Vulkan/volumetric.frag @@ -103,6 +103,7 @@ struct VolumetricConstant float NoiseSpeed; float NoiseScale; float NoiseStrength; + float CSMSplits[4]; }; [[vk::push_constant]] @@ -214,8 +215,28 @@ float snoise(float3 v) return 42.0 * dot(m*m, float4(dot(g0,x0), dot(g1,x1), dot(g2,x2), dot(g3,x3))); } +int GetCSMSplit(float depth) +{ + for(int i = 0; i < 4; i++) + { + float csmSplitDepth = pushConstants.CSMSplits[i]; + + if(depth < csmSplitDepth + 0.000001) + { + return i; + } + } + + return 0; +} + PSOutput main(PSInput input) { + float ditherPattern[4][4] = { { 0.0f, 0.5f, 0.125f, 0.625f}, + { 0.75f, 0.22f, 0.875f, 0.375f}, + { 0.1875f, 0.6875f, 0.0625f, 0.5625}, + { 0.9375f, 0.4375f, 0.8125f, 0.3125} }; + CameraView camView = cameras[pushConstants.CamViewID]; float3 startPosition = camView.Position; @@ -246,31 +267,66 @@ PSOutput main(PSInput input) for(int l = 0; l < pushConstants.LightCount; l++) { Light light = lights[l]; - if(light.type != 0) + if(light.type == 0) { - continue; + float lightDepth = length(worldPos - camView.Position); + int splitIndex = GetCSMSplit(lightDepth); + + CameraView lightView = cameras[light.transformId[splitIndex]]; + float4 fragPosLightSpace = mul(lightView.Projection, mul(lightView.View, float4(currentPosition, 1.0))); + float3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; + projCoords.xy = projCoords.xy * 0.5 + 0.5; + + float currentDepth = projCoords.z; + float closestDepth = textures[light.shadowMapTextureId[splitIndex]].Sample(mySampler, projCoords.xy).r; + + float3 noiseOffset = float3(pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time); + float3 noiseSamplePos = (currentPosition + noiseOffset) * pushConstants.NoiseScale; + if(closestDepth < currentDepth) + { + accumFog += (ComputeScattering(dot(rayDirection, light.direction)).rrr * light.color.xyz) * pushConstants.Exponant * ((snoise(noiseSamplePos.xyz) + 1.0) / 2.0); + } + else + { + accumFog += (ComputeScattering(dot(rayDirection, light.direction)).rrr * light.color.xyz) * pushConstants.Ambient * ((snoise(noiseSamplePos.xyz) + 1.0) / 2.0); + } } - - CameraView lightView = cameras[light.transformId[0]]; - float4 fragPosLightSpace = mul(lightView.Projection, mul(lightView.View, float4(currentPosition, 1.0))); - float3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; - projCoords.xy = projCoords.xy * 0.5 + 0.5; - - float currentDepth = projCoords.z; - float closestDepth = textures[light.shadowMapTextureId[0]].Sample(mySampler, projCoords.xy).r; - - float3 noiseOffset = float3(pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time); - float3 noiseSamplePos = (currentPosition + noiseOffset) * pushConstants.NoiseScale; - if(closestDepth < currentDepth) + else if(light.type == 1) { - accumFog += (ComputeScattering(dot(rayDirection, light.direction)).rrr * light.color) * pushConstants.Exponant * ((snoise(noiseSamplePos.xyz) + 1.0) / 2.0); + float3 lightToFrag = currentPosition - light.position; + float distance = length(lightToFrag); + float3 lightDir = normalize(-lightToFrag); + float attenuation = 1.0 / (distance * distance); + attenuation = 1.0 - smoothstep(0.0, 3.0f, distance); + float3 noiseOffset = float3(pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time); + float3 noiseSamplePos = (currentPosition + noiseOffset) * pushConstants.NoiseScale; + float lightScatter = (snoise(noiseSamplePos.xyz) + 1.0) * 0.5; + + float3 scatterTerm = ComputeScattering(dot(rayDirection, lightDir)).rrr * light.color.xyz; + + accumFog += scatterTerm * lightScatter * pushConstants.Exponant * attenuation; } - else + else if(light.type == 2) { - accumFog += (ComputeScattering(dot(rayDirection, light.direction)).rrr * light.color) * pushConstants.Ambient * ((snoise(noiseSamplePos.xyz) + 1.0) / 2.0); + float3 lightToFrag = currentPosition - light.position; + float distance = length(lightToFrag); + float3 lightDir = normalize(-lightToFrag); + float attenuation = 1.0 / (distance * distance); + attenuation = 1.0 - smoothstep(0.0, 6.0f, distance); + float3 noiseOffset = float3(pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time); + float3 noiseSamplePos = (currentPosition + noiseOffset) * pushConstants.NoiseScale; + float lightScatter = (snoise(noiseSamplePos.xyz) + 1.0) * 0.5; + + float theta = dot(lightDir, normalize(-light.direction)); + float epsilon = light.innerConeAngle - light.outerConeAngle; + float intensity = clamp((theta - light.outerConeAngle) / epsilon, 0.0, 1.0); + float3 scatterTerm = ComputeScattering(dot(rayDirection, lightDir)).rrr * light.color.xyz; + accumFog += scatterTerm * lightScatter * pushConstants.Exponant * attenuation * intensity; } } + + currentPosition += step ; } diff --git a/Data/Shaders/Vulkan/volumetric.vert b/Data/Shaders/Vulkan/volumetric.vert index 581bfc45..052e57c2 100644 --- a/Data/Shaders/Vulkan/volumetric.vert +++ b/Data/Shaders/Vulkan/volumetric.vert @@ -93,6 +93,7 @@ struct VolumetricConstant float NoiseSpeed; float NoiseScale; float NoiseStrength; + float CSMSplits[4]; }; [[vk::push_constant]] diff --git a/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.cpp b/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.cpp index e6d4aac6..e37453f8 100644 --- a/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.cpp +++ b/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.cpp @@ -226,6 +226,7 @@ SceneRenderPipeline::SceneRenderPipeline() BloomThreshold = CreateRef(ImageFormat::RGBA16F, defaultSize); VolumetricOutput = CreateRef(ImageFormat::RGBA8, defaultSize); + VolumetricBlurOutput = CreateRef(ImageFormat::RGBA8, defaultSize); VolumetricCombineOutput = CreateRef(ImageFormat::RGBA8, defaultSize); RecreatePipeline(); @@ -251,6 +252,7 @@ SceneRenderPipeline::~SceneRenderPipeline() res.RemoveTexture(BloomThreshold); res.RemoveTexture(VolumetricOutput); res.RemoveTexture(VolumetricCombineOutput); + res.RemoveTexture(VolumetricBlurOutput); } void SceneRenderPipeline::SetCamera(UUID camera) @@ -281,8 +283,8 @@ void SceneRenderPipeline::Render(PassRenderContext& ctx) Vector2 resolution = { static_cast(ctx.resolution.x * 0.25f), static_cast(ctx.resolution.y * 0.25f) }; VolumetricOutput = ResizeImage(ctx, VolumetricOutput, glm::clamp(resolution, {1, 1}, ctx.resolution)); + VolumetricBlurOutput = ResizeImage(ctx, VolumetricBlurOutput, ctx.resolution); VolumetricCombineOutput = ResizeImage(ctx, VolumetricCombineOutput, ctx.resolution); - OutlineOutput = ResizeImage(ctx, OutlineOutput, ctx.resolution); Color clearColor = ctx.scene->GetEnvironment()->AmbientColor; @@ -296,6 +298,7 @@ void SceneRenderPipeline::Render(PassRenderContext& ctx) { ShadingOutput }, // Shading { TonemappedOutput }, // Tonemap { VolumetricOutput }, + { VolumetricBlurOutput }, { VolumetricCombineOutput }, { GizmoOutput, GBufferEntityID, GBufferDepth }, // Reusing depth from gBuffer { GizmoCombineOutput }, @@ -640,6 +643,11 @@ void SceneRenderPipeline::RecreatePipeline() volumetricConstant.StepCount = env->mVolumetric->GetStepCount(); volumetricConstant.Exponant = env->mVolumetric->GetFogExponant(); volumetricConstant.Ambient = env->mVolumetric->GetBaseAmbient(); + for (int i = 0; i < CSM_AMOUNT; i++) + { + volumetricConstant.CSMSplits[i] = LightComponent::mCascadeSplitDepth[i]; + } + auto& res = GPUResources::Get(); volumetricConstant.DepthTextureID = res.GetBindlessTextureID(GBufferDepth->GetID()); volumetricConstant.CamViewID = ctx.cameraID; @@ -657,6 +665,47 @@ void SceneRenderPipeline::RecreatePipeline() cmd.DrawIndexed(6); }); + + struct BlurConstant + { + int depthId; + int volumetricId; + }; + + BlurConstant blurConstantData; + auto& volumetricBlurPass = GBufferPipeline.AddPass("VolumetricBlur"); + volumetricBlurPass.SetPushConstant(blurConstant); + volumetricBlurPass.SetShaders(shaderMgr.GetShader("depth_aware_blur_vert"), shaderMgr.GetShader("depth_aware_blur_frag")); + volumetricBlurPass.AddAttachment("VolumetricBlurOutput", VolumetricBlurOutput->GetFormat()); + volumetricBlurPass.SetDepthTest(false); + volumetricBlurPass.SetPreRender([&](PassRenderContext& ctx) + { + Cmd& cmd = ctx.commandBuffer; + auto& layout = ctx.renderPass->PipelineLayout; + auto& res = GPUResources::Get(); + + 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); + }); + volumetricBlurPass.SetRender([&](PassRenderContext& ctx) + { + auto& cmd = ctx.commandBuffer; + + BlurConstant blurConstant; + blurConstant.depthId = GPUResources::Get().GetBindlessTextureID(GBufferDepth->GetID()); + blurConstant.volumetricId = GPUResources::Get().GetBindlessTextureID(VolumetricOutput->GetID()); + cmd.PushConstants(ctx.renderPass->PipelineLayout, sizeof(blurConstant), &blurConstant); + + auto& quadMesh = VkSceneRenderer::QuadMesh; + cmd.BindDescriptorSet(ctx.renderPass->PipelineLayout, quadMesh->GetDescriptorSet(), 1); + cmd.BindIndexBuffer(quadMesh->GetIndexBuffer()->GetBuffer()); + cmd.DrawIndexed(6); + }); + auto& volumetricCombinePass = GBufferPipeline.AddPass("VolumetricCombine"); volumetricCombinePass.SetPushConstant(copyConstant); volumetricCombinePass.SetShaders(shaderMgr.GetShader("copy_vert"), shaderMgr.GetShader("copy_frag")); @@ -679,7 +728,7 @@ void SceneRenderPipeline::RecreatePipeline() { auto& cmd = ctx.commandBuffer; - copyConstant.Source2TextureID = GPUResources::Get().GetBindlessTextureID(VolumetricOutput->GetID()); + copyConstant.Source2TextureID = GPUResources::Get().GetBindlessTextureID(VolumetricBlurOutput->GetID()); copyConstant.SourceTextureID = GPUResources::Get().GetBindlessTextureID(TonemappedOutput->GetID()); copyConstant.Mode = 1; cmd.PushConstants(ctx.renderPass->PipelineLayout, sizeof(copyConstant), ©Constant); @@ -690,6 +739,8 @@ void SceneRenderPipeline::RecreatePipeline() cmd.DrawIndexed(6); }); + + auto& gizmoPass = GBufferPipeline.AddPass("Gizmo"); gizmoPass.SetShaders(shaderMgr.GetShader("gizmo_vert"), shaderMgr.GetShader("gizmo_frag")); gizmoPass.SetPushConstant(debugConstant); diff --git a/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.h b/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.h index 4f826950..df72e477 100644 --- a/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.h +++ b/Nuake/Source/Nuake/Rendering/Vulkan/SceneRenderPipeline.h @@ -102,6 +102,7 @@ namespace Nuake float NoiseSpeed; float NoiseScale; float NoiseStrength; + float CSMSplits[4]; }; struct CopyConstant @@ -175,6 +176,7 @@ namespace Nuake Ref TonemappedOutput; Ref VolumetricOutput; + Ref VolumetricBlurOutput; Ref VolumetricCombineOutput; Ref OutlineOutput; @@ -203,6 +205,7 @@ namespace Nuake BloomConstant bloomConstant; VolumetricConstant volumetricConstant; + RenderPipeline GBufferPipeline; // Delegates diff --git a/Nuake/Source/Nuake/Rendering/Vulkan/ShaderCompiler.cpp b/Nuake/Source/Nuake/Rendering/Vulkan/ShaderCompiler.cpp index eed2b10d..0f64a155 100644 --- a/Nuake/Source/Nuake/Rendering/Vulkan/ShaderCompiler.cpp +++ b/Nuake/Source/Nuake/Rendering/Vulkan/ShaderCompiler.cpp @@ -127,7 +127,7 @@ Ref ShaderCompiler::CompileShader(const std::string& path) Logger::Log("Shader compilation failed: " + errorMsgStr, "DXC", CRITICAL); - throw std::runtime_error("Shader compilation failed: " + errorMsgStr); + throw std::runtime_error("Shader compilation failed: " + errorMsgStr); } else { diff --git a/Nuake/Source/Nuake/Rendering/Vulkan/VulkanRenderer.cpp b/Nuake/Source/Nuake/Rendering/Vulkan/VulkanRenderer.cpp index e61e9037..2730589d 100644 --- a/Nuake/Source/Nuake/Rendering/Vulkan/VulkanRenderer.cpp +++ b/Nuake/Source/Nuake/Rendering/Vulkan/VulkanRenderer.cpp @@ -37,8 +37,11 @@ #include #include -bool NKUseValidationLayer = true; - +#ifdef NK_DEBUG +bool NKUseValidationLayer = true; +#else +bool NKUseValidationLayer = false; +#endif using namespace Nuake; VkRenderer::~VkRenderer() diff --git a/Nuake/Source/Nuake/Rendering/Vulkan/VulkanResources.cpp b/Nuake/Source/Nuake/Rendering/Vulkan/VulkanResources.cpp index 343e30df..52e791c4 100644 --- a/Nuake/Source/Nuake/Rendering/Vulkan/VulkanResources.cpp +++ b/Nuake/Source/Nuake/Rendering/Vulkan/VulkanResources.cpp @@ -295,7 +295,7 @@ void GPUResources::CreateBindlessLayout() vkCreateSampler(device, &sampler, nullptr, &SamplerLinear); VkDescriptorImageInfo textureInfo = {}; - textureInfo.sampler = SamplerNearest; // Your VkSampler object + textureInfo.sampler = SamplerLinear; // Your VkSampler object textureInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkWriteDescriptorSet samplerWrite = {}; diff --git a/Nuake/Source/Nuake/Rendering/Vulkan/VulkanSceneRenderer.cpp b/Nuake/Source/Nuake/Rendering/Vulkan/VulkanSceneRenderer.cpp index d740013e..5a2bf2ea 100644 --- a/Nuake/Source/Nuake/Rendering/Vulkan/VulkanSceneRenderer.cpp +++ b/Nuake/Source/Nuake/Rendering/Vulkan/VulkanSceneRenderer.cpp @@ -417,6 +417,8 @@ void VkSceneRenderer::LoadShaders() shaderMgr.AddShader("blur_vert", shaderCompiler.CompileShader("Resources/Shaders/Vulkan/blur.vert")); shaderMgr.AddShader("volumetric_frag", shaderCompiler.CompileShader("Resources/Shaders/Vulkan/volumetric.frag")); shaderMgr.AddShader("volumetric_vert", shaderCompiler.CompileShader("Resources/Shaders/Vulkan/volumetric.vert")); + shaderMgr.AddShader("depth_aware_blur_vert", shaderCompiler.CompileShader("Resources/Shaders/Vulkan/depth_aware_blur.vert")); + shaderMgr.AddShader("depth_aware_blur_frag", shaderCompiler.CompileShader("Resources/Shaders/Vulkan/depth_aware_blur.frag")); } void VkSceneRenderer::PrepareScenes(const std::vector>& scenes, RenderContext inContext)