Visibility Buffer - JuanDiegoMontoya/Frogfood GitHub Wiki
Frogfood uses a visibility buffer to efficiently rasterize a large amount of geometry with minimal bandwidth. The fragment shader for the main scene geometry only outputs 64 bits of data:
- 32-bit depth
- 32-bit unsigned integer with packed data:
- 24 bits for the meshlet instance index
- 8 bits for the primitive index within that meshlet
Resolving
To use the visbuffer for shading, we need to resolve its texels. We do this by fetching the meshlet instance, its transform, and the vertex indices of the triangle. Then, we can fetch and transform the vertices.
Knowing the position of the texel relative to the triangle's vertices, we can find the barycentric coordinates. Finally, we have what is essentially the input to the scene fragment shader of a typical forward or deferred renderer: interpolated texture coordinates, vertex normals, and any other vertex attribute we might have.
But what if we want automatic LoD selection? Since the domain of the shader is "the screen" rather than the actual scene geometry, the partial derivatives we get with dFdx
and dFdy
are useless. Fortunately, some people who are smarter than myself have figured out that you can apply the chain rule here to calculate analytical derivatives which can then be passed to textureGrad
. This is covered in much greater detail in the reference below.
To avoid repeating the relatively costly endeavor of per-pixel triangle interpolation and analytical derivative calculations, we do it once and store the results in a G-buffer:
- Albedo: RGBA8_SRGB (8 bits wasted)
- Metallic, roughness, and baked ambient occlusion: RGBA8_UNORM (8 bits wasted)
- Normal-mapped normal and per-face normal: RGBA16_SNORM (octahedral encoding)
- Non-normal-mapped normal: RG16_SNORM (octahedral encoding)
- Emission: R11G11B10_FLOAT
- Motion: RG16_FLOAT
- Reactive mask (for FSR 2): R8_UNORM
This G-buffer's massiveness is offset by the fact that it's only written to once.
For the curious, you can see what the various normals are used for in ShadeDeferredPbr.frag.glsl.