I have a strange issue in my engine where my SSAO effect will extremely darken or lighten based on my camera angle:
In that example, I'm just outputting the ssao texture to the screen. The texture is stored as a single (red) 8 bit channel.
I've been following a few tutorials here and there for building my SSAO shader, primarily this and that, so my code is pretty much identical.
I've done some research beforehand, however I couldn't really find anything that matched my error.
The only thing I found was that some people who were doing SSAO do this thing where they offsetted their scene's normals before saving it:
normalTexture = normal * 2.0f - 1.0f;
And then when needing to access the scene's normals, they revert the offset such as:
vec3 normal = texture2D(normalTexture) * 0.5f + 0.5f;
This type of thing I can almost understand, but I've never come across this is any tutorial that I've been following for any of the shading I've been doing up to this point. Further, the normals are normalized so much anyways. Regardless, if I do this or not, surfaces running parallel to different axes do the exact same thing anyways in my SSAO shader.
During my geometry pass, where I fill my GBuffer with the current frame's textures, this is how I calculate the normals:
...
layout (location = 2) out vec3 NormalOut;
...
void main()
{
vec3 Normal = normalize(Normal0); // The geometry's physical normal, in world space
vec3 Tangent = normalize(Tangent0); // The geometry's physical tangent, in world space
Tangent = (Tangent - dot(Tangent, Normal) * Normal);
vec3 Bitangent = cross(Tangent, Normal);
vec3 BumpMapNormal = texture(NormalTexture, TexCoord0.xy).xyz; // The bumpmap texture for the skin of the object
BumpMapNormal = (BumpMapNormal * 2.0 - 1.0);
mat3 TBN = mat3(Tangent, Bitangent, Normal);
vec3 NormalFinal = normalize((TBN * BumpMapNormal));
NormalOut = normalize(0.5 * NormalFinal + 0.5); // Final normal
}
My SSAO fragment shader:
in vec2 TexCoord;
layout (location = 0) out float FragColor;
uniform sampler2D ViewPosMap;
uniform sampler2D NormalMap;
uniform sampler2D NoiseMap;
const int MAX_KERNEL_SIZE = 128;
uniform vec3 Kernel[MAX_KERNEL_SIZE];
uniform int USABLE_KERNEL_SIZE;
uniform vec2 NoiseScale;
uniform float SampleRadius;
uniform mat4 pMatrix;
void main()
{
vec3 Pos = texture(ViewPosMap, TexCoord).xyz;
vec3 Normal = texture(NormalMap, TexCoord).xyz * 2.0 - 1.0 ;
vec3 RandomVec = texture(NoiseMap, TexCoord * NoiseScale).xyz;
vec3 Tangent = normalize(RandomVec - Normal * dot(RandomVec, Normal));
vec3 Bitangent = cross(Normal, Tangent);
mat3 TBN = mat3(Tangent, Bitangent, Normal);
float occlusion = 0.0;
for (int i = 0 ; i < USABLE_KERNEL_SIZE ; i++) {
vec3 sample = TBN * Kernel[i]; // From tangent to view-space
sample = Pos + sample * SampleRadius;
// project sample position (to sample texture) (to get position on screen/texture)
vec4 offset = vec4(sample, 1.0);
offset = pMatrix * offset; // from view to clip-space
offset.xyz /= offset.w; // perspective divide
offset.xyz = offset.xyz * 0.5 + 0.5; // transform to range 0.0 - 1.0
// get sample depth
float sampleDepth = texture(ViewPosMap, offset.xy).z; // Get depth value of kernel sample
// range check & accumulate
float rangeCheck = smoothstep(0.0, 1.0, SampleRadius / abs(Pos.z - sampleDepth));
occlusion += (sampleDepth >= sample.z ? 1.0 : 0.0) * rangeCheck;
}
occlusion = 1.0 - (occlusion / USABLE_KERNEL_SIZE);
FragColor = occlusion;
}
And here is a sample of what the normals look like in the scene:
I feel like I'm banging my head against the wall here, I'm not quite sure why I'm getting the results that I am. If anyone wants any further information, I'll post it as soon as I can.
The solution provided in this thread was exactly what I needed. I created an additional GBuffer texture, one which held the scene's normals but in viewspace. I then sent this texture to my ssao shader, and it corrected the issue I was having.