Deferred Shading & Screen-Space Effects
Pros: many lights cheaply, decoupled geometry/lighting.
29.1 Deferred shading
Geometry pass: render all objects once into a G-buffer (multiple render targets): position/depth, normal, albedo, material parameters.
Lighting pass: for each pixel, read the G-buffer and accumulate all lights (fullscreen pass, light volumes, or tiled/clustered).
Pros: many lights cheaply, decoupled geometry/lighting. Cons: memory bandwidth, transparency and MSAA are harder, limited material variety. Alternatives: Forward+ / clustered forward (light lists per screen tile/cluster built by a compute shader), visibility buffer rendering.
// Geometry pass fragment shader
layout (location = 0) out vec4 gAlbedoMetal; // rgb albedo, a metallic
layout (location = 1) out vec4 gNormalRough; // xyz normal (or octahedral-encoded), w roughness
layout (location = 2) out vec4 gEmissive;
void main() {
gAlbedoMetal = vec4(texture(uAlbedo, vUV).rgb, metallic);
gNormalRough = vec4(normalize(vTBN * sampledNormal) * 0.5 + 0.5, roughness);
gEmissive = vec4(emissive, 1.0);
}
// Lighting pass: reconstruct world position from depth + inverse view-projection
vec3 worldFromDepth(vec2 uv, float depth) {
vec4 ndc = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
vec4 world = uInvViewProj * ndc;
return world.xyz / world.w;
}29.2 Screen-space ambient occlusion (SSAO)
Modern variants: HBAO+, GTAO (ground-truth AO).
uniform sampler2D gDepth, gNormal, uNoise;
uniform vec3 uSamples[64]; // hemisphere kernel, denser near the origin
uniform mat4 uProjection;
float ssao(vec3 viewPos, vec3 viewN, vec2 uv) {
vec3 randomVec = texture(uNoise, uv * uNoiseScale).xyz;
vec3 T = normalize(randomVec - viewN * dot(randomVec, viewN));
mat3 TBN = mat3(T, cross(viewN, T), viewN);
float occlusion = 0.0;
for (int i = 0; i < 64; ++i) {
vec3 samplePos = viewPos + TBN * uSamples[i] * uRadius;
vec4 offset = uProjection * vec4(samplePos, 1.0);
offset.xy = (offset.xy / offset.w) * 0.5 + 0.5;
float sceneZ = viewSpaceZFromDepth(texture(gDepth, offset.xy).r);
float rangeCheck = smoothstep(0.0, 1.0, uRadius / abs(viewPos.z - sceneZ));
occlusion += (sceneZ >= samplePos.z + 0.025 ? 1.0 : 0.0) * rangeCheck;
}
return 1.0 - occlusion / 64.0; // blur afterwards to remove noise
}29.3 Other screen-space techniques
SSR (screen-space reflections): ray march the depth buffer along the reflection vector (hierarchical Z for speed).
Screen-space shadows / contact shadows.
Temporal anti-aliasing (TAA): jitter the projection each frame, reproject the previous frame with motion vectors, clamp history to neighborhood colors.
Motion blur & depth of field using velocity and depth buffers.
Decals (deferred decals project textures onto the G-buffer).