SSAO is fully implemented

This commit is contained in:
Brandon Mak 2022-11-01 20:10:59 +08:00
parent 78545889da
commit b0d08d27fd
7 changed files with 97 additions and 20 deletions

View File

@ -21,7 +21,7 @@ layout(set = 4, binding = 0, rgba32f) uniform image2D positions;
layout(set = 4, binding = 1, rgba32f) uniform image2D normals; layout(set = 4, binding = 1, rgba32f) uniform image2D normals;
layout(set = 4, binding = 2, rgba8) uniform image2D albedo; layout(set = 4, binding = 2, rgba8) uniform image2D albedo;
layout(set = 4, binding = 3, r32ui) uniform uimage2D lightLayerData; layout(set = 4, binding = 3, r32ui) uniform uimage2D lightLayerData;
layout(set = 4, binding = 4, rgba32f) uniform image2D ssaoImage; layout(set = 4, binding = 4, r8) uniform image2D ssaoBlurredImage;
layout(set = 4, binding = 5, rgba8) uniform image2D targetImage; layout(set = 4, binding = 5, rgba8) uniform image2D targetImage;
layout(set = 1, binding = 0) uniform LightCounts layout(set = 1, binding = 0) uniform LightCounts
@ -55,7 +55,7 @@ void main()
vec3 positionView = imageLoad (positions, globalThread).rgb; vec3 positionView = imageLoad (positions, globalThread).rgb;
// normal of fragment // normal of fragment
vec3 normalView = -imageLoad(normals, globalThread).rgb; vec3 normalView = imageLoad(normals, globalThread).rgb;
vec3 fragColor = vec3 (0.0f); vec3 fragColor = vec3 (0.0f);
@ -78,9 +78,11 @@ void main()
fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength); fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength);
} }
float ssaoVal = imageLoad (ssaoBlurredImage, globalThread).r;
fragColor *= ssaoVal;
// store result into result image // store result into result image
//imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(normalView, 1.0f)); imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor.rgb, 1.0f));
//imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor, 1.0f)); //imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(ssaoVal.rrr, 1.0f));
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(imageLoad(ssaoImage, globalThread).rgba/*, 1.0f*/));
} }

View File

@ -0,0 +1,58 @@
#version 450
#define BLUR_WIDTH 5
#define BLUR_HALF_WIDTH BLUR_WIDTH / 2
#define SHM_WIDTH BLUR_WIDTH + 16 - 1
layout(local_size_x = 16, local_size_y = 16) in;
layout(set = 4, binding = 0, r8) uniform image2D ssaoImage;
layout(set = 4, binding = 1, r8) uniform image2D ssaoBlurImage;
float GetSSAOValue(ivec2 uv, ivec2 imageSize)
{
if (uv.x >= 0 && uv.y >= 0 && uv.x < imageSize.x && uv.y < imageSize.y)
{
return imageLoad (ssaoImage, uv).r;
}
return 0.0f;
}
shared float sharedPixels[16 + BLUR_WIDTH - 1][16 + BLUR_WIDTH - 1];
void main()
{
ivec2 globalThread = ivec2 (gl_GlobalInvocationID.xy);
ivec2 localThread = ivec2 (gl_LocalInvocationID.xy);
ivec2 inputImageSize = imageSize(ssaoImage);
// Load color into shared memory
ivec2 start = ivec2 (gl_WorkGroupID) * ivec2 (gl_WorkGroupSize) - (BLUR_HALF_WIDTH);
for (int i = localThread.x; i < SHM_WIDTH; i += int (gl_WorkGroupSize.x))
{
for (int j = localThread.y; j < SHM_WIDTH; j += int (gl_WorkGroupSize.y))
{
float value = GetSSAOValue (start + ivec2 (i, j), inputImageSize);
sharedPixels[i][j] = value;
}
}
// wait for all shared memory to load
barrier();
ivec2 shmStart = ivec2 (localThread + (BLUR_HALF_WIDTH));
float sum = 0;
for (int i = -BLUR_HALF_WIDTH; i <= BLUR_HALF_WIDTH; ++i)
{
for (int j = -BLUR_HALF_WIDTH; j <= BLUR_HALF_WIDTH; ++j)
{
float sharedVal = sharedPixels[shmStart.x + i][shmStart.y + j];
sum += sharedVal;
}
}
sum /= (BLUR_WIDTH * BLUR_WIDTH);
imageStore(ssaoBlurImage, globalThread, vec4(sum.rrr, 1.0f));
}

Binary file not shown.

View File

@ -36,37 +36,45 @@ layout(set = 2, binding = 0) uniform CameraData
void main() void main()
{ {
ivec2 size = imageSize (outputImage); // image size of the SSAO image
ivec2 ssaoSize = imageSize (outputImage);
// global thread
ivec2 globalThread = ivec2 (gl_GlobalInvocationID.xy); ivec2 globalThread = ivec2 (gl_GlobalInvocationID.xy);
// load all the necessary variables // load all the necessary variables
vec3 viewSpacePos = imageLoad (positions, globalThread).rgb; vec3 viewSpacePos = imageLoad (positions, globalThread).rgb;
vec3 viewSpaceNormal = normalize (imageLoad (normals, globalThread).rgb); vec3 viewSpaceNormal = normalize (imageLoad (normals, globalThread).rgb);
//viewSpaceNormal = -viewSpaceNormal;
// Get the noise dimension. This should be 4x4
vec2 noiseDim = vec2 (textureSize(noiseTexture, 0)); vec2 noiseDim = vec2 (textureSize(noiseTexture, 0));
vec2 threadUV = (vec2(globalThread) + vec2 (0.5f)) / vec2(size);
vec2 noiseUVMult = vec2 (vec2(size) / noiseDim); // Get normlized thread UV coordinates
vec2 threadUV = (vec2(globalThread)) / vec2(ssaoSize);
vec2 noiseUVMult = vec2 (vec2(ssaoSize) / noiseDim);
noiseUVMult *= threadUV; noiseUVMult *= threadUV;
// sample from the noise
vec3 randomVec = texture(noiseTexture, noiseUVMult).rgb; vec3 randomVec = texture(noiseTexture, noiseUVMult).rgb;
// Gram schmidt // Gram schmidt
vec3 tangent = normalize (randomVec - (viewSpaceNormal * dot(viewSpaceNormal, randomVec))); vec3 tangent = normalize (randomVec - (viewSpaceNormal * dot(viewSpaceNormal, randomVec)));
vec3 bitangent = normalize (cross (tangent, viewSpaceNormal)); vec3 bitangent = normalize (cross (tangent, viewSpaceNormal));
// matrix for tangent to view // matrix for tangent space to view space
mat3 TBN = mat3(tangent, bitangent, viewSpaceNormal); mat3 TBN = mat3(tangent, bitangent, viewSpaceNormal);
float occlusion = 0.0f; float occlusion = 0.0f;
for (int i = 0; i < NUM_SAMPLES; ++i) for (int i = 0; i < NUM_SAMPLES; ++i)
{ {
// We want to get a position at an offset from the view space position. Offset scaled by radius. // We want to get a position at an offset from the view space position. Offset scaled by radius.
vec3 samplePos = TBN * ssaoData.samples[i].rgb; vec3 displacementVector = TBN * ssaoData.samples[i].rgb;
samplePos = viewSpacePos + samplePos * RADIUS;
// Why are we adding positions?
displacementVector = viewSpacePos + displacementVector * RADIUS;
// Now we take that offset position and bring it to clip space // Now we take that offset position and bring it to clip space
vec4 offsetPos = vec4 (samplePos, 1.0f); vec4 offsetPos = vec4 (displacementVector, 1.0f);
offsetPos = cameraData.projMat * offsetPos; offsetPos = cameraData.projMat * offsetPos;
// then we do perspective division // then we do perspective division
@ -74,20 +82,23 @@ void main()
// and bring it from [-1, 1] to screen coordinates // and bring it from [-1, 1] to screen coordinates
offsetPos.xyz = ((offsetPos.xyz * 0.5f) + 0.5f); offsetPos.xyz = ((offsetPos.xyz * 0.5f) + 0.5f);
offsetPos.xy *= vec2(size.xy); offsetPos.xy *= vec2(ssaoSize.xy);
// Now we attempt to get a position at that point.
float sampleDepth = imageLoad (positions, ivec2 (offsetPos.xy)).z; float sampleDepth = imageLoad (positions, ivec2 (offsetPos.xy)).z;
// skip checks
if (sampleDepth == 0.0f) if (sampleDepth == 0.0f)
continue; continue;
// if sampled fragment is in front of current fragment, just occlude
float rangeCheck = smoothstep (0.0f, 1.0f, RADIUS / abs (viewSpacePos.z - sampleDepth)); float rangeCheck = smoothstep (0.0f, 1.0f, RADIUS / abs (viewSpacePos.z - sampleDepth));
occlusion += (sampleDepth <= samplePos.z - BIAS ? 1.0f : 0.0f) * rangeCheck; occlusion += (sampleDepth <= displacementVector.z - BIAS ? 1.0f : 0.0f) * rangeCheck;
//occlusion += (sampleDepth <= samplePos.z + BIAS ? 1.0f : 0.0f);
} }
occlusion = 1.0f - (occlusion / float(NUM_SAMPLES)); occlusion = 1.0f - (occlusion / float(NUM_SAMPLES));
// store result into result image // store result into result image
imageStore(outputImage, globalThread, vec4(occlusion.rrr, 1.0f)); imageStore(outputImage, globalThread, occlusion.rrrr);
} }

Binary file not shown.

View File

@ -115,6 +115,7 @@ namespace SHADE
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_FS.glsl"); SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_FS.glsl");
SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl"); SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl");
SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl"); SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl");
SHAssetManager::CompileAsset("../../Assets/Shaders/SSAOBlur_CS.glsl");
shaderModuleLibrary.ImportAllShaderSource(device); shaderModuleLibrary.ImportAllShaderSource(device);
shaderModuleLibrary.ReflectAllShaderModules(); shaderModuleLibrary.ReflectAllShaderModules();
@ -169,7 +170,8 @@ namespace SHADE
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second); worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("SSAO", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); worldRenderGraph->AddResource("SSAO", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
worldRenderGraph->AddResource("SSAO Blur", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* MAIN NODE */ /* MAIN NODE */
@ -184,7 +186,8 @@ namespace SHADE
"Albedo", "Albedo",
"Depth Buffer", "Depth Buffer",
"Scene", "Scene",
"SSAO" "SSAO",
"SSAO Blur"
}, },
{}); // no predecessors {}); // no predecessors
@ -225,12 +228,15 @@ namespace SHADE
auto viewSamplerLayout = ssaoStorage->GetViewSamplerLayout(); auto viewSamplerLayout = ssaoStorage->GetViewSamplerLayout();
ssaoPass->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_IMAGE_BINDING, {&viewSamplerLayout, 1}); ssaoPass->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_IMAGE_BINDING, {&viewSamplerLayout, 1});
auto ssaoBlurShader = shaderModuleLibrary.GetBuiltInShaderModule("SSAOBlur_CS");
Handle<SHRenderGraphNodeCompute> ssaoBlurPass = gBufferNode->AddNodeCompute(ssaoBlurShader, { "SSAO", "SSAO Blur"});
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* DEFERRED COMPOSITE SUBPASS INIT */ /* DEFERRED COMPOSITE SUBPASS INIT */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
auto deferredCompositeShader = shaderModuleLibrary.GetBuiltInShaderModule("DeferredComposite_CS"); auto deferredCompositeShader = shaderModuleLibrary.GetBuiltInShaderModule("DeferredComposite_CS");
gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO", "Scene" }); gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene" });
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* DUMMY SUBPASS TO TRANSITION SCENE FOR PRESENT USAGE */ /* DUMMY SUBPASS TO TRANSITION SCENE FOR PRESENT USAGE */