Discard
Task
You are given a 3D cube with each face mapped using UV coordinates ranging from (0.0, 0.0) in the bottom-left to (1.0, 1.0) in the top-right corner of each face. Your task is to create a visual circular hole in the center of each face, with a radius of 0.25 in UV space.
Theory
The discard statement in GLSL/HLSL instructs the GPU to completely discard the current fragment, meaning it won’t be drawn or participate in further operations like depth testing or blending.
In a fragment shader, you can write:
if (alpha < 0.1)
discard;
This tells the GPU: “don’t draw this fragment if it’s mostly transparent.” The fragment is skipped entirely - it produces no color, no depth, no stencil output.
Use discard in fragment shaders when you need binary visibility - for example, cutting out parts of textures (like alpha-masked leaves or fences), procedural holes, or stylized effects where fragments should either fully render or not render at all. It's especially useful for hard-edged transparency or selectively skipping fragments based on custom logic.
Early Z-Testing
In the GPU’s rendering pipeline, early Z-testing (also called early depth testing) allows the GPU to reject fragments before they enter the expensive fragment shader stage - based on whether they’ll be visible or hidden behind other geometry.
This optimization saves time by avoiding work on pixels that won’t be seen anyway.
How discard breaks Early Z
Once you use discard in your fragment shader, the GPU can’t know in advance whether a fragment will be discarded - because that decision now depends on shader logic.
As a result:
early Z is disabled
late Z-testing is used after fragment shading
That means every fragment is fully shaded, regardless of whether it ends up being visible. If you’re drawing lots of geometry with alpha-masked transparency (like grass, hair, or foliage), this can drastically increase fragment shader workload.