BrdfLuts

class BrdfLuts

Bases: ReferenceCount

The split-sum DFG lookup table of the PBR shader, generated on the CPU.

For a view angle mu = N.V and a perceptual roughness r (GGX alpha = r^2), the specular BRDF f = D G2 F / (4 N.L N.V) with GGX D, the height-correlated Smith G2 (the same one the shader’s direct lobe uses) and Schlick’s F = f0 + (f90 - f0)(1 - V.H)^5 integrates over the hemisphere to

E(mu, r) = integral of f cos = f0 (G - R) + f90 R

where the table holds, per texel, R = integral of D G2 / (4 N.L N.V) (1 - V.H)^5 cos theta_l (red) G = integral of D G2 / (4 N.L N.V) cos theta_l (green) Green is also the directional albedo of a white (f0 = f90 = 1) surface, the single-scattering energy that the multiscatter compensation restores (Kulla and Conty 2017; Fdez-Aguera 2019; Filament’s layout). Blue is reserved (0) for the sheen lobe and alpha is 1.

Texel (x, y) holds mu = (x + 0.5) / size, r = (y + 0.5) / size, so a linearly filtered lookup at (mu, r) with clamping is exact at the centres. Each texel is a GGX importance-sampled estimate over a Hammersley set (Karis 2013), in double precision: deterministic. The stored values are clamped to their bounds (R <= G <= 1) against the estimate’s noise near the mirror limit. The texture is RGBA16F.

Inheritance diagram

digraph inheritance49c8b5f143 { bgcolor=transparent; rankdir=BT; size="8.0, 12.0"; "BrdfLuts" [URL="acron.shading.BrdfLuts.html#acron.shading.BrdfLuts",fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=11,height=0.25,shape=box,style="",target="_top",tooltip="/**"]; "ReferenceCount" -> "BrdfLuts" [arrowsize=0.75,style=""]; "DTOOL_SUPER_BASE" [fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=11,height=0.25,shape=box,style=""]; "ReferenceCount" [URL="acron.core.ReferenceCount.html#acron.core.ReferenceCount",fillcolor=white,fontname="Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans",fontsize=11,height=0.25,shape=box,style="",target="_top",tooltip="/**"]; "DTOOL_SUPER_BASE" -> "ReferenceCount" [arrowsize=0.75,style=""]; }
BrdfLuts.__init__()

Generates the table: size x size texels, samples GGX samples each.

static BrdfLuts.d_ggx()

The GGX (Trowbridge-Reitz) normal distribution, alpha = roughness^2.

static BrdfLuts.float_to_half()

IEEE 754 binary16 from a float, rounded to nearest even.

static BrdfLuts.get_default()

The process-wide table, sized by shading-dfg-lut-size and shading-dfg-lut-samples; generated on first use.

BrdfLuts.get_samples()

Importance samples per texel.

BrdfLuts.get_size()

The table’s width and height.

BrdfLuts.get_texel()

The generated value of a texel, in single precision (x: N.V, y: roughness).

BrdfLuts.get_texel_fp16()

The texel as the texture stores it (rounded to half precision).

BrdfLuts.get_texture()

The table as an RGBA16F texture (linear filtering, clamped, no mipmaps), made on first call. The shader reads it as pbr_dfg_lut.

static BrdfLuts.half_to_float()

A float from IEEE 754 binary16.

static BrdfLuts.integrate_dfg()

One texel’s integrals (R, G) at any N.V and perceptual roughness, by GGX importance sampling of the half vector over samples Hammersley points. With pdf(L) = D N.H / (4 V.H), each sample weighs f cos / pdf = V * 4 N.L V.H / N.H (times F).

static BrdfLuts.radical_inverse()

Van der Corput’s radical inverse in base 2 (the second Hammersley coordinate).

BrdfLuts.sample()

The table at (N.V, perceptual roughness), bilinearly filtered and clamped at the edges, as the GPU reads it.

static BrdfLuts.v_smith_ggx_correlated()

The height-correlated Smith visibility V = G2 / (4 N.L N.V) for GGX (Heitz 2014, “Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs”, eq. 99, in the form of Lagarde and de Rousiers 2014): 0.5 / (N.L sqrt(N.V^2 (1 - a^2) + a^2) + N.V sqrt(N.L^2 (1 - a^2) + a^2)).