Fragment Shaders, Color & Blending

Colors are usually in [0, 1] for 8-bit (UNORM) targets — values are clamped; floating-point targets (RGBA16F/32F) store HDR values.

14.1 Outputs

Colors are usually in [0, 1] for 8-bit (UNORM) targets — values are clamped; floating-point targets (RGBA16F/32F) store HDR values.

#version 330 core
layout (location = 0) out vec4 outColor;      // render target 0
layout (location = 1) out vec4 outNormal;     // render target 1 (MRT, §29)

void main() {
    outColor = vec4(1.0, 0.5, 0.2, 1.0);
    outNormal = vec4(0.0, 0.0, 1.0, 0.0);
}

14.2 Discard & alpha testing

vec4 tex = texture(uAlbedo, vUV);
if (tex.a < 0.5) discard;          // cutout foliage, fences (disables some early-Z optimizations)
outColor = tex;

14.3 Blending (configured on the host)

Transparent objects: render opaque first, then transparent sorted back-to-front with depth writes disabled — or use order-independent transparency (weighted blended OIT, per-pixel linked lists with SSBOs/atomics).

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);   // standard alpha blending
glBlendFunc(GL_ONE, GL_ONE);                          // additive (glow, particles)
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);          // premultiplied alpha (recommended)

14.4 Depth

gl_FragDepth = computedDepth;         // custom depth (e.g., ray-marched geometry); disables early-Z
float linearDepth(float d, float n, float f) {   // convert non-linear depth-buffer value to view distance
    float z = d * 2.0 - 1.0;                     // back to NDC (OpenGL)
    return (2.0 * n * f) / (f + n - z * (f - n));
}

14.5 Visual debugging with color

Output intermediate values as colors: normals (n * 0.5 + 0.5), UVs (vec3(uv, 0)), depth, NaN detection (isnan(x) ? magenta : ...). This is the shader programmer's printf.