diff --git a/projects/voxelization/resources/shaders/shadowBlur.comp b/projects/voxelization/resources/shaders/shadowBlur.comp deleted file mode 100644 index 3cf744ab79108c5a9c619524dd8824c39886b357..0000000000000000000000000000000000000000 --- a/projects/voxelization/resources/shaders/shadowBlur.comp +++ /dev/null @@ -1,42 +0,0 @@ -#version 450 -#extension GL_GOOGLE_include_directive : enable - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -layout(set=0, binding=0) uniform texture2D srcTexture; -layout(set=0, binding=1) uniform sampler depthSampler; -layout(set=0, binding=2, rgba16) uniform image2D outImage; - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -void main(){ - - if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))){ - return; - } - ivec2 coord = ivec2(gl_GlobalInvocationID.xy); - - int blurRadius = 9; - int minOffset = -(blurRadius-1) / 2; - int maxOffset = -minOffset; - - vec2 pixelSize = vec2(1) / textureSize(sampler2D(srcTexture, depthSampler), 0); - - float wTotal = 0; - vec4 moments = vec4(0); - - float weights1D[4] = { 0.5, 0.25, 0.125, 0.0625 }; // gaussian - - for(int x = minOffset; x <= maxOffset; x++){ - for(int y = minOffset; y <= maxOffset; y++){ - vec2 uv = (coord + ivec2(x, y)) * pixelSize; - uv += 0.5 * pixelSize * sign(vec2(x, y)); // half pixel shift to take advantage of bilinear filtering - float w = weights1D[abs(x)] * weights1D[abs(y)]; - moments += w * texture(sampler2D(srcTexture, depthSampler), uv); - wTotal += w; - } - } - moments /= wTotal; - - imageStore(outImage, coord, moments); -} \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/shadowBlur.inc b/projects/voxelization/resources/shaders/shadowBlur.inc new file mode 100644 index 0000000000000000000000000000000000000000..06147415f118dca9badd15813b431a68682ce0b0 --- /dev/null +++ b/projects/voxelization/resources/shaders/shadowBlur.inc @@ -0,0 +1,27 @@ +#ifndef SHADOW_BLUR_INC +#define SHADOW_BLUR_INC + +vec4 blurMomentShadowMap1D(ivec2 coord, ivec2 blurDirection, texture2D srcTexture, sampler depthSampler){ + + int blurRadius = 9; + int minOffset = -(blurRadius-1) / 2; + int maxOffset = -minOffset; + + vec2 pixelSize = vec2(1) / textureSize(sampler2D(srcTexture, depthSampler), 0); + + float wTotal = 0; + vec4 moments = vec4(0); + + float weights1D[4] = { 0.5, 0.25, 0.125, 0.0625 }; // gaussian + + for(int i = minOffset; i <= maxOffset; i++){ + vec2 uv = (coord + i * blurDirection) * pixelSize; + uv += 0.5 * pixelSize * blurDirection * sign(i); // half pixel shift to take advantage of bilinear filtering + float w = weights1D[abs(i)]; + moments += w * texture(sampler2D(srcTexture, depthSampler), uv); + wTotal += w; + } + return moments / wTotal; +} + +#endif // #ifndef SHADOW_BLUR_INC \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/shadowBlurX.comp b/projects/voxelization/resources/shaders/shadowBlurX.comp new file mode 100644 index 0000000000000000000000000000000000000000..45b91aad71673347dbf607fecef92463ef1c3c88 --- /dev/null +++ b/projects/voxelization/resources/shaders/shadowBlurX.comp @@ -0,0 +1,23 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#include "shadowBlur.inc" + +layout(set=0, binding=0) uniform texture2D srcTexture; +layout(set=0, binding=1) uniform sampler depthSampler; +layout(set=0, binding=2, rgba16) uniform image2D outImage; + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +void main(){ + + if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))){ + return; + } + ivec2 coord = ivec2(gl_GlobalInvocationID.xy); + vec4 moments = blurMomentShadowMap1D(coord, ivec2(1, 0), srcTexture, depthSampler); + + imageStore(outImage, coord, moments); +} \ No newline at end of file diff --git a/projects/voxelization/resources/shaders/shadowBlurY.comp b/projects/voxelization/resources/shaders/shadowBlurY.comp new file mode 100644 index 0000000000000000000000000000000000000000..51d4df054b0d99e54149863a5967143518f61dd2 --- /dev/null +++ b/projects/voxelization/resources/shaders/shadowBlurY.comp @@ -0,0 +1,25 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#include "shadowBlur.inc" + +layout(set=0, binding=0) uniform texture2D srcTexture; +layout(set=0, binding=1) uniform sampler depthSampler; +layout(set=0, binding=2, rgba16) uniform image2D outImage; + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +void main(){ + + if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))){ + return; + } + ivec2 coord = ivec2(gl_GlobalInvocationID.xy); + vec2 pixelSize = vec2(1) / textureSize(sampler2D(srcTexture, depthSampler), 0); + + vec4 moments = blurMomentShadowMap1D(coord, ivec2(0, 1), srcTexture, depthSampler); + + imageStore(outImage, coord, moments); +} \ No newline at end of file diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp index e27895ae030e902a2b41bc1c80a3e2db68dca61f..b50a5f98b55a9b9260c374296a1c24aab597fd72 100644 --- a/projects/voxelization/src/ShadowMapping.cpp +++ b/projects/voxelization/src/ShadowMapping.cpp @@ -25,10 +25,20 @@ vkcv::ShaderProgram loadDepthToMomentsShader() { return shader; } -vkcv::ShaderProgram loadShadowBlurShader() { +vkcv::ShaderProgram loadShadowBlurXShader() { vkcv::ShaderProgram shader; vkcv::shader::GLSLCompiler compiler; - compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/shadowBlur.comp", + compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/shadowBlurX.comp", + [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { + shader.addShader(shaderStage, path); + }); + return shader; +} + +vkcv::ShaderProgram loadShadowBlurYShader() { + vkcv::ShaderProgram shader; + vkcv::shader::GLSLCompiler compiler; + compiler.compile(vkcv::ShaderStage::COMPUTE, "resources/shaders/shadowBlurY.comp", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { shader.addShader(shaderStage, path); }); @@ -174,19 +184,30 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert vkcv::DescriptorWrites depthToMomentDescriptorWrites; depthToMomentDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapDepth.getHandle()) }; depthToMomentDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) }; - depthToMomentDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_shadowMapIntermediate.getHandle()) }; + depthToMomentDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) }; corePtr->writeDescriptorSet(m_depthToMomentsDescriptorSet, depthToMomentDescriptorWrites); - // shadow blur - vkcv::ShaderProgram shadowBlurShader = loadShadowBlurShader(); - m_shadowBlurDescriptorSet = corePtr->createDescriptorSet(shadowBlurShader.getReflectedDescriptors()[0]); - m_shadowBlurPipe = corePtr->createComputePipeline(shadowBlurShader, { corePtr->getDescriptorSet(m_shadowBlurDescriptorSet).layout }); - - vkcv::DescriptorWrites shadowBlurDescriptorWrites; - shadowBlurDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapIntermediate.getHandle()) }; - shadowBlurDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) }; - shadowBlurDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) }; - corePtr->writeDescriptorSet(m_shadowBlurDescriptorSet, shadowBlurDescriptorWrites); + // shadow blur X + vkcv::ShaderProgram shadowBlurXShader = loadShadowBlurXShader(); + m_shadowBlurXDescriptorSet = corePtr->createDescriptorSet(shadowBlurXShader.getReflectedDescriptors()[0]); + m_shadowBlurXPipe = corePtr->createComputePipeline(shadowBlurXShader, { corePtr->getDescriptorSet(m_shadowBlurXDescriptorSet).layout }); + + vkcv::DescriptorWrites shadowBlurXDescriptorWrites; + shadowBlurXDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMap.getHandle()) }; + shadowBlurXDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) }; + shadowBlurXDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_shadowMapIntermediate.getHandle()) }; + corePtr->writeDescriptorSet(m_shadowBlurXDescriptorSet, shadowBlurXDescriptorWrites); + + // shadow blur Y + vkcv::ShaderProgram shadowBlurYShader = loadShadowBlurYShader(); + m_shadowBlurYDescriptorSet = corePtr->createDescriptorSet(shadowBlurYShader.getReflectedDescriptors()[0]); + m_shadowBlurYPipe = corePtr->createComputePipeline(shadowBlurYShader, { corePtr->getDescriptorSet(m_shadowBlurYDescriptorSet).layout }); + + vkcv::DescriptorWrites shadowBlurYDescriptorWrites; + shadowBlurYDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapIntermediate.getHandle()) }; + shadowBlurYDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) }; + shadowBlurYDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) }; + corePtr->writeDescriptorSet(m_shadowBlurYDescriptorSet, shadowBlurYDescriptorWrites); } void ShadowMapping::recordShadowMapRendering( @@ -245,22 +266,32 @@ void ShadowMapping::recordShadowMapRendering( const uint32_t msaaSampleCount = msaaToSampleCount(msaa); - m_corePtr->prepareImageForStorage(cmdStream, m_shadowMapIntermediate.getHandle()); + m_corePtr->prepareImageForStorage(cmdStream, m_shadowMap.getHandle()); m_corePtr->recordComputeDispatchToCmdStream( cmdStream, m_depthToMomentsPipe, dispatchCount, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_depthToMomentsDescriptorSet).vulkanHandle) }, vkcv::PushConstantData((void*)&msaaSampleCount, sizeof(msaaSampleCount))); + m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle()); + + // blur X + m_corePtr->prepareImageForStorage(cmdStream, m_shadowMapIntermediate.getHandle()); + m_corePtr->recordComputeDispatchToCmdStream( + cmdStream, + m_shadowBlurXPipe, + dispatchCount, + { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowBlurXDescriptorSet).vulkanHandle) }, + vkcv::PushConstantData(nullptr, 0)); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMapIntermediate.getHandle()); - // blur + // blur Y m_corePtr->prepareImageForStorage(cmdStream, m_shadowMap.getHandle()); m_corePtr->recordComputeDispatchToCmdStream( cmdStream, - m_shadowBlurPipe, + m_shadowBlurYPipe, dispatchCount, - { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowBlurDescriptorSet).vulkanHandle) }, + { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowBlurYDescriptorSet).vulkanHandle) }, vkcv::PushConstantData(nullptr, 0)); m_shadowMap.recordMipChainGeneration(cmdStream); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle()); diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp index 2b25220bfc06ba1646003d61ef05c66920e1b1b6..7e06fb58f492837b7a646dfa52c5dd50993df04e 100644 --- a/projects/voxelization/src/ShadowMapping.hpp +++ b/projects/voxelization/src/ShadowMapping.hpp @@ -50,6 +50,9 @@ private: vkcv::PipelineHandle m_depthToMomentsPipe; vkcv::DescriptorSetHandle m_depthToMomentsDescriptorSet; - vkcv::PipelineHandle m_shadowBlurPipe; - vkcv::DescriptorSetHandle m_shadowBlurDescriptorSet; + vkcv::PipelineHandle m_shadowBlurXPipe; + vkcv::DescriptorSetHandle m_shadowBlurXDescriptorSet; + + vkcv::PipelineHandle m_shadowBlurYPipe; + vkcv::DescriptorSetHandle m_shadowBlurYDescriptorSet; }; \ No newline at end of file