Skip to content
Snippets Groups Projects
Commit 88dcc1e7 authored by Alexander Gauggel's avatar Alexander Gauggel
Browse files

[#82] Separate shadow blur

parent 18f09bac
No related branches found
No related tags found
1 merge request!70Resolve "Voxel cone tracing"
Pipeline #25996 failed
#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
#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
...@@ -3,8 +3,10 @@ ...@@ -3,8 +3,10 @@
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout(set=0, binding=0) uniform texture2D srcTexture; #include "shadowBlur.inc"
layout(set=0, binding=1) uniform sampler depthSampler;
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(set=0, binding=2, rgba16) uniform image2D outImage;
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
...@@ -15,28 +17,9 @@ void main(){ ...@@ -15,28 +17,9 @@ void main(){
return; return;
} }
ivec2 coord = ivec2(gl_GlobalInvocationID.xy); 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); vec2 pixelSize = vec2(1) / textureSize(sampler2D(srcTexture, depthSampler), 0);
float wTotal = 0; vec4 moments = blurMomentShadowMap1D(coord, ivec2(0, 1), srcTexture, depthSampler);
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); imageStore(outImage, coord, moments);
} }
\ No newline at end of file
...@@ -25,10 +25,20 @@ vkcv::ShaderProgram loadDepthToMomentsShader() { ...@@ -25,10 +25,20 @@ vkcv::ShaderProgram loadDepthToMomentsShader() {
return shader; return shader;
} }
vkcv::ShaderProgram loadShadowBlurShader() { vkcv::ShaderProgram loadShadowBlurXShader() {
vkcv::ShaderProgram shader; vkcv::ShaderProgram shader;
vkcv::shader::GLSLCompiler compiler; 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) { [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
shader.addShader(shaderStage, path); shader.addShader(shaderStage, path);
}); });
...@@ -174,19 +184,30 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert ...@@ -174,19 +184,30 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
vkcv::DescriptorWrites depthToMomentDescriptorWrites; vkcv::DescriptorWrites depthToMomentDescriptorWrites;
depthToMomentDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapDepth.getHandle()) }; depthToMomentDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapDepth.getHandle()) };
depthToMomentDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) }; 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); corePtr->writeDescriptorSet(m_depthToMomentsDescriptorSet, depthToMomentDescriptorWrites);
// shadow blur // shadow blur X
vkcv::ShaderProgram shadowBlurShader = loadShadowBlurShader(); vkcv::ShaderProgram shadowBlurXShader = loadShadowBlurXShader();
m_shadowBlurDescriptorSet = corePtr->createDescriptorSet(shadowBlurShader.getReflectedDescriptors()[0]); m_shadowBlurXDescriptorSet = corePtr->createDescriptorSet(shadowBlurXShader.getReflectedDescriptors()[0]);
m_shadowBlurPipe = corePtr->createComputePipeline(shadowBlurShader, { corePtr->getDescriptorSet(m_shadowBlurDescriptorSet).layout }); m_shadowBlurXPipe = corePtr->createComputePipeline(shadowBlurXShader, { corePtr->getDescriptorSet(m_shadowBlurXDescriptorSet).layout });
vkcv::DescriptorWrites shadowBlurDescriptorWrites; vkcv::DescriptorWrites shadowBlurXDescriptorWrites;
shadowBlurDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapIntermediate.getHandle()) }; shadowBlurXDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMap.getHandle()) };
shadowBlurDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) }; shadowBlurXDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) };
shadowBlurDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) }; shadowBlurXDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_shadowMapIntermediate.getHandle()) };
corePtr->writeDescriptorSet(m_shadowBlurDescriptorSet, shadowBlurDescriptorWrites); 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( void ShadowMapping::recordShadowMapRendering(
...@@ -245,22 +266,32 @@ void ShadowMapping::recordShadowMapRendering( ...@@ -245,22 +266,32 @@ void ShadowMapping::recordShadowMapRendering(
const uint32_t msaaSampleCount = msaaToSampleCount(msaa); const uint32_t msaaSampleCount = msaaToSampleCount(msaa);
m_corePtr->prepareImageForStorage(cmdStream, m_shadowMapIntermediate.getHandle()); m_corePtr->prepareImageForStorage(cmdStream, m_shadowMap.getHandle());
m_corePtr->recordComputeDispatchToCmdStream( m_corePtr->recordComputeDispatchToCmdStream(
cmdStream, cmdStream,
m_depthToMomentsPipe, m_depthToMomentsPipe,
dispatchCount, dispatchCount,
{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_depthToMomentsDescriptorSet).vulkanHandle) }, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_depthToMomentsDescriptorSet).vulkanHandle) },
vkcv::PushConstantData((void*)&msaaSampleCount, sizeof(msaaSampleCount))); 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()); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMapIntermediate.getHandle());
// blur // blur Y
m_corePtr->prepareImageForStorage(cmdStream, m_shadowMap.getHandle()); m_corePtr->prepareImageForStorage(cmdStream, m_shadowMap.getHandle());
m_corePtr->recordComputeDispatchToCmdStream( m_corePtr->recordComputeDispatchToCmdStream(
cmdStream, cmdStream,
m_shadowBlurPipe, m_shadowBlurYPipe,
dispatchCount, dispatchCount,
{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowBlurDescriptorSet).vulkanHandle) }, { vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_shadowBlurYDescriptorSet).vulkanHandle) },
vkcv::PushConstantData(nullptr, 0)); vkcv::PushConstantData(nullptr, 0));
m_shadowMap.recordMipChainGeneration(cmdStream); m_shadowMap.recordMipChainGeneration(cmdStream);
m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle()); m_corePtr->prepareImageForSampling(cmdStream, m_shadowMap.getHandle());
......
...@@ -50,6 +50,9 @@ private: ...@@ -50,6 +50,9 @@ private:
vkcv::PipelineHandle m_depthToMomentsPipe; vkcv::PipelineHandle m_depthToMomentsPipe;
vkcv::DescriptorSetHandle m_depthToMomentsDescriptorSet; vkcv::DescriptorSetHandle m_depthToMomentsDescriptorSet;
vkcv::PipelineHandle m_shadowBlurPipe; vkcv::PipelineHandle m_shadowBlurXPipe;
vkcv::DescriptorSetHandle m_shadowBlurDescriptorSet; vkcv::DescriptorSetHandle m_shadowBlurXDescriptorSet;
vkcv::PipelineHandle m_shadowBlurYPipe;
vkcv::DescriptorSetHandle m_shadowBlurYDescriptorSet;
}; };
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment