openglglslshaderdeferred-renderingssao

Combine SSAO with global light and local lights


I have recently implemented SSAO in my engine(deferred shading), but I am very insecure of how I should combine SSAO with global light and local lights(point light).

Should I do this:

//Global light pass.
vec3 sceneColor = DiffuseBRDF + SpecularBRDF;
float luminance = dot(sceneColor, vec3(0.2126, 0.7152, 0.0722));
sceneColor *= mix(texture(ssaoTexture, texCoord).r, 1.0, luminance);

//Local light pass.
//Use additive blending in this pass, i.e. glBlendFunc(GL_ONE, GL_ONE).
//The final result would be:
vec3 finalColor = sceneColor + pointLight0 + pointLight1 + ... + pointLightN;

or this:

//Global light pass.
vec3 sceneColor = DiffuseBRDF + SpecularBRDF;

//Local light pass.
//Use additive blending in this pass, i.e. glBlendFunc(GL_ONE, GL_ONE).
vec3 finalColor = sceneColor + pointLight0 + pointLight1 + ... + pointLightN;

//Composite pass.
float luminance = dot(finalColor, vec3(0.2126, 0.7152, 0.0722));
finalColor *= mix(texture(ssaoTexture, texCoord).r, 1.0, luminance);

Solution

  • Ambient occlusion is a value that describes how much ambient light can hit a point on the surface. Ambient light is a light that comes from all directions, rather than from a single light source, and usually contains sky lighting, image based lighting, global illumination or a simple flat color. The correct way to apply AO is to multiply it with ambient lighting. Simply put, ambient occlusion is to ambient lighting as shadows are to direct lighting.

    So, if your point lights are "atmospheric" lights and are supposed to represent soft ambient lighting without specular highlights, then you should apply the AO to these point lights only, without any luminance scaling. If the point lights are lights with a well defined source and you don't have any significant ambient lighting, then you should be consistent and apply the AO to all lights equally, with luminance scaling to simulate the look produced by correct AO application.