@jnoyola wrote:
EDIT: This used to be about hemisphere-oriented SSAO, but I was having too many difficulties with that and read that it's more susceptible to artifacts, so I changed to spherical, but I'm still having problems (although it's much closer!)
I've loosely been following a number of tutorials, but I'm having a few issues with my SSAO.
This screenshot shows world-space normals, encoded depth, and the ambient occlusion map, with the composition in the background. There's darkness on the floor by the right wall, but not at the base of the wall itself. There's also occasionally a strange cloud of darkness around the head of the torch, but nothing around the base. Additionally, it seems like maybe one of my transformations is incorrect, because all of the ambient occlusion varies so much when the camera moves around.
Here are the main bits of my shader:
// Vertex Input Structure struct VSI { float3 Position : POSITION0; float2 UV : TEXCOORD0; }; // Vertex Output Structure struct VSO { float4 Position : POSITION0; float2 UV : TEXCOORD0; float3 ViewRay : TEXCOORD1; }; // Vertex Shader VSO VS(VSI input) { // Initialize Output VSO output; // Pass Position output.Position = float4(input.Position, 1); // Pass Texcoord's output.UV = input.UV; output.ViewRay = float3( -input.Position.x * TanHalfFov * GBufferTextureSize.x / GBufferTextureSize.y, input.Position.y * TanHalfFov, 1); // Return return output; } float3 randomNormal(float2 uv) { float noiseX = (frac(sin(dot(uv, float2(15.8989f, 76.132f) * 1.0f)) * 46336.23745f)); float noiseY = (frac(sin(dot(uv, float2(11.9899f, 62.223f) * 2.0f)) * 34748.34744f)); float noiseZ = (frac(sin(dot(uv, float2(13.3238f, 63.122f) * 3.0f)) * 59998.47362f)); return normalize(float3(noiseX, noiseY, noiseZ)); } //Pixel Shader float4 PS(VSO input) : COLOR0 { //Sample Vectors float3 kernel[8] = { float3(0.355512, -0.709318, -0.102371), float3(0.534186, 0.71511, -0.115167), float3(-0.87866, 0.157139, -0.115167), float3(0.140679, -0.475516, -0.0639818), float3(-0.207641, 0.414286, 0.187755), float3(-0.277332, -0.371262, 0.187755), float3(0.63864, -0.114214, 0.262857), float3(-0.184051, 0.622119, 0.262857) }; // Get Normal from GBuffer half3 normal = DecodeNormalRGB(tex2D(GBuffer1, input.UV).rgb); normal = normalize(mul(normal, ViewIT)); // Get Depth from GBuffer float2 encodedDepth = tex2D(GBuffer2, input.UV).rg; float depth = DecodeFloatRG(encodedDepth) * -FarClip; // Scale ViewRay by Depth float3 position = normalize(input.ViewRay) * depth; // Construct random transformation for the kernel float3 rand = randomNormal(input.UV); // Sample float numSamplesUsed = 0; float occlusion = 0.0; for (int i = 0; i < NUM_SAMPLES; ++i) { // Reflect the sample across a random normal to avoid artifacts float3 sampleVec = reflect(kernel[i], rand); // Negate the sample if it points into the surface sampleVec *= sign(dot(sampleVec, normal)); // Ignore the sample if it's almost parallel with the surface to avoid depth-imprecision artifacts //if (dot(sampleVec, normal) > 0.15) // TODO: is this necessary for our purposes? //{ // Offset the sample by the current pixel's position float4 samplePos = float4(position + sampleVec * SampleRadius, 1); // Project the sample to screen space float2 samplePosUV = float2(dot(samplePos, ProjectionCol1), dot(samplePos, ProjectionCol2)); samplePosUV /= dot(samplePos, ProjectionCol4); // Convert to UV space samplePosUV = (samplePosUV + 1) / 2; // Get sample depth float2 encodedSampleDepth = tex2D(GBuffer2, samplePosUV).rg; float sampleDepth = DecodeFloatRG(encodedSampleDepth) * -FarClip; // Calculate and accumulate occlusion float diff = 1 * max(sampleDepth - depth, 0.0f); occlusion += 1.0f / (1.0f + diff * diff * 0.1); ++numSamplesUsed; //} } occlusion /= numSamplesUsed; return float4(occlusion, occlusion, occlusion, 1.0); }
I'd really appreciate if anyone could give me a hand, because I've been stuck on this for a few days scouring the web and these forums. Thanks!
Posts: 1
Participants: 1