1
\$\begingroup\$

I am having trouble with my Screen Space Ambient Occlusion shader.

The objects in the game have the correct occlusion applied to them, however the occlusion flips depending on the angle of the camera:

These artefacts can be seen here.

The normal texture looks like this:

Normal Texture

SSAO is calculated from the gDepth and gNormal buffers. The gDepth buffer is set up like this:

uint ID = Gl.GenTexture();
Gl.BindTexture(TextureTarget.Texture2d, ID);
Gl.TexImage2D(TextureTarget.Texture2d, 0, InternalFormat.DepthComponent32, screenWidth, screenHeight, 0, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero);
Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Nearest);
Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureCompareFunc, Gl.LEQUAL);
Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureCompareMode, 0);
Gl.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, TextureTarget.Texture2d, ID, 0);

The gNormal buffer is set up like this:

uint ID = Gl.GenTexture();
Gl.BindTexture(TextureTarget.Texture2d, ID);
Gl.TexImage2D(TextureTarget.Texture2d, 0, InternalFormat.Rgba16f, screenWidth, screenHeight, 0, PixelFormat.Rgba, PixelType.Float, IntPtr.Zero);
Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
Gl.TexParameter(TextureTarget.Texture2d, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Nearest);
Gl.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment1, TextureTarget.Texture2d, ID, 0);

The voxel map is rendered into the gBuffers in the Map Shader.

Map Shader (Vertex Shader):

flat out vec4 color;
flat out vec4 normal;

layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec4 aColor;

uniform mat4 mvp;

void main()
{
    gl_Position = mvp * vec4(aPosition, 1.0);
    normal = vec4(aNormal, 2);
    color = aColor;
}

Map Shader (Fragment Shader):

layout (location = 0) out vec4 gColor;
layout (location = 1) out vec4 gNormal;

flat in vec4 color;
flat in vec4 normal;

void main()
{
    gColor = color;
    gNormal = normal;
}

The gNormal alpha component is used to determine which parts of the screen to apply SSAO to.

The SSAO fragment shader:

layout (location = 0) out vec4 FragColor;

in vec2 texCoords;

layout (binding = 0) uniform sampler2D gColor;
layout (binding = 1) uniform sampler2D gDepth;
layout (binding = 2) uniform sampler2D gNormal;

uniform mat4 projection;
uniform mat4 projectionInverse;

uniform vec3 samples[64];
uniform int kernelSize;

// Reconstruct position from the depth buffer
vec3 getPosition(in float depth)
{
    float z = depth * 2.0 - 1.0;

    vec4 clipSpacePosition = vec4(texCoords * 2.0 - 1.0, z, 1.0);
    vec4 direct = projectionInverse * clipSpacePosition;
    return direct.xyz / direct.w;
}

void main()
{
    float depth = texture(gDepth, texCoords).x;
    vec4 nParts = texture(gNormal, texCoords);

    vec3 Normal = nParts.xyz;
    vec3 FragPos = getPosition(depth);

    float occlusion = 1.0;

    mat3 TBN = mat3(Normal, vec3(0,0,0), Normal);

    if (nParts.a > 1)
    {
        for (int i = kernelSize; i > 0; i--)
        {
            vec3 sam = TBN * samples[i] + FragPos;

            vec4 offset = projection * vec4(sam, 1.0);
            offset.xyz = (offset.xyz / offset.w) * 0.5 + 0.5;   

            float sampleDepth = texture(gDepth, offset.xy).x;

            occlusion += (sampleDepth <= depth ? 1.0 : 0.0);   
        }

        occlusion = 1 - occlusion * 0.3 / kernelSize;
    }

    FragColor = vec4(occlusion, occlusion, occlusion,1);
}

What is causing this occlusion flip?

\$\endgroup\$

0

You must log in to answer this question.

Browse other questions tagged .