Working notes: rendering primer
Not part of the article. Context for the author and for a fresh Claude Code session picking this up.
Where this came from
Drafted between 2026-09-03 and 2026-09-08 in ~/maritime_ws/src/bluerobotics_models, as docs/reference/rendering-primer.md, alongside an audit of that repository’s glTF parts library. It was moved here on 2026-09-08 because the content is general background and nothing in it is specific to that project. The originating repository keeps its own project-specific documents (model-spec.md, VISUAL_ASSET_PIPELINE_REVIEW.md, pbr-and-gltf.md); this article deliberately shares none of their content.
Full history is in the git log of bluerobotics_models under docs/reference/rendering-primer.md, ending at commit f94df76.
Stage
Stage 2, annotated outline, per AUTHOR_WORKFLOW.md. About 5,600 words, nearly all of it italic notes describing what each subsection will say. Front matter carries draft: true and no AI disclosure callout, since disclosure is added at stage 3.
Settled content that should survive into the draft rather than being rewritten:
- the two tables in section 1, shading models and formats;
- the naming table and the terminology paragraph in section 1;
- the BRDF expression and the notes under 1.1.1;
- the rendered figure and its caption.
Audience and voice
Written for a general engineer who does not work in graphics, does not work in CAD, and is not a computer vision specialist. Ordinary engineering vocabulary; graphics jargon is defined at first use or not used.
The terminology, and how it was settled
This took several rounds and is the spine of the article. Do not re-open it without cause.
shading model = reflection model + parameterization. The shading model is the package a renderer evaluates at a point on a surface. Its two halves are the reflection model, the equation, and the parameterization, the author-facing values plus the rule mapping them onto the equation’s variables.
“Shading model” is the name used, and the overload is disclosed rather than avoided. An earlier draft banned the phrase over a claimed collision. That was wrong. The collision is with “Phong shading” alone, which also names a per-pixel renderer technique; “shading model” itself is safe and is the term Marschner and Shirley, Hoffman, Burley, Unreal and OpenPBR all use. Section 1 carries a table of the five names in use and says which sources use which.
“Material model” is avoided because glTF already uses material for the data object holding a shading model’s parameters, so the two would sit one word apart.
The reflection model and the parameterization are not one to one. One reflection model can take several parameterizations: Cook-Torrance takes metallic-roughness and specular-glossiness. The reverse never happens. That asymmetry is the reason the two are named separately at all.
Empirical against physically based is a statement about derivation, not a test. The checkable test is physically plausible, from Lewis 1994: energy conserving and reciprocal. The two do not nest. Normalized Blinn-Phong is empirical yet passes; shipped physically based models routinely fail because real-time renderers approximate. Section 2.3 holds both cases. An earlier draft got this backwards.
The layered supersets are not parameterizations. Disney principled, Standard Surface and OpenPBR add lobes, so both halves grow. They live in section 2.2.4, not section 3. Section 3 covers only the two genuine parameterizations of one reflection model.
Section 2 is named for reflection models, not shading models. Settled during the first PMR. Section 2’s subsections treat Phong, Lambert, Cook-Torrance and the rest, and those are reflection models; only paired with a parameterization do they become the shading models of the 1.1.3 table. Section 2 is therefore “The reflection models in common use”, 2.1 and 2.2 likewise, and 2.2.2 says explicitly that Cook-Torrance is the reflection model half and section 3 makes the pairing. Section 3 remains parameterizations, and 1.1.3 remains the place the two are put together.
Names are used consistently. The table in 1.1.3 names shading models by their pairing, so “Cook-Torrance with metallic-roughness”. The format table uses those same names. The article notes that most sources shorten this to “metallic-roughness”, letting the parameterization stand for the pair.
SDF and URDF were removed as off topic. They describe scenes rather than carry geometry, and the question that prompted them was answered elsewhere.
What was verified, and against what
Everything factual was checked against a primary source rather than recalled. Sources actually consulted:
| Source | Used for |
|---|---|
| Marschner and Shirley, Fundamentals of Computer Graphics, 4th ed. | ch. 4.5 shading; 8.2.5 the Phong shading name collision; ch. 10 surface shading; 18.1 radiometry and the BRDF definition; 18.3 photometry; ch. 24 reflection models, the plausibility test, the coupled model, the Phong tuning quote |
| Eck, Introduction to Computer Graphics | ch. 4 the five empirical coefficients; 4.1.3 flat and smooth shading; the PBR glossary entry; declines to cover PBR in the body |
| glTF 2.0 specification source | §3.9 materials; Appendix B the full BRDF, the metallic blend, the squared-roughness statement, and its own admission that its Fresnel mix breaks energy conservation |
| Filament PBR documentation | the BSDF decomposition sentence; the split of Standard model from Parameterization; roughness remapping; clearcoat as a second specular lobe; multiscattering energy loss |
| Hoffman, SIGGRAPH 2013 course notes | the D and G slot point; plausibility as reciprocity plus energy conservation |
| Burley, SIGGRAPH 2012 | the five principles, quoted from page 12; the parameter list; the metallic blend as the ancestor of metallic-roughness |
| pbrt 4th ed. | the alternative taxonomy by origin: measured, phenomenological, simulation, wave optics, geometric optics |
| OpenPBR specification | the slab model and the fixed layer order |
The two textbook PDFs now sit in refs/ beside this file. That directory is gitignored (**/refs/ in the repository’s .gitignore) and is local only: they are source texts consulted while drafting, not article assets, and this repository publishes to a public site. Text was extracted with pdftotext -layout.
Claims that did not survive checking, and are now stated correctly: that a physically based model must take measurable parameters (Burley’s first principle says the opposite); that Disney principled is the common ancestor of both parameterizations (specular-glossiness predates it); that COLLADA and OpenGL materials have four coefficients (five, with emission).
The figure
shading_models.png, generated by shading_models_figure.py, which needs only numpy and pillow. Eight spheres, one per row of the table in 1.1.3, identical geometry and identical lighting in every panel so the shading model is the only variable. The Cook-Torrance panels follow glTF Appendix B: GGX distribution, height-correlated Smith visibility, Schlick Fresnel, the dielectric and metal BRDFs mixed by metallic. Lighting is computed in linear space and encoded to sRGB at the end.
Two things the figure is meant to demonstrate rather than assert. The constant sphere reads as a flat disc, which makes the case for lighting better than a sentence. And the metallic-roughness and specular-glossiness panels are identical to within 4e-15, which is the parameterization argument of 1.1.2 shown rather than claimed. Verify with:
python3 -c "
import numpy as np, shading_models_figure as R
n,mask=R.sphere_normals(); v=np.zeros_like(n); v[...,2]=1.0
a=R.PANELS[6][2](n,v)[mask]; b=R.PANELS[7][2](n,v)[mask]
print(np.abs(a-b).max())"
Rerun python3 shading_models_figure.py after any change; it writes beside itself.
brdf_lobes.png, generated by lobe_figure.py, added during the first PMR to answer the author’s request for a visual demonstration of the lobe with units. Six polar plots, the light fixed at 45 degrees, radius the BRDF value in inverse steradians on a logarithmic scale spanning six decades, the same scale in every panel. It imports _ggx and _smith_vis from shading_models_figure.py so both figures use one implementation. The captions state measured numbers, so rerun and re-measure before changing them: peaks run 0.159 for Lambert to 8,266 for Cook-Torrance at roughness 0.03, and the full width at half maximum is 1.48 degrees at roughness 0.1 and 0.13 degrees at 0.03.
Building it exposed a bug in _ggx, now fixed: the denominator carried an additive 1e-9, which is negligible at the roughness the sphere figure uses but dominates it for a smooth surface, where the denominator falls to alpha squared. It capped the roughness 0.03 peak at 17 instead of 8,266. The guard is now multiplicative, np.maximum(np.pi * d * d, 1e-30). shading_models.png regenerates bit-identical across the change, so nothing in the settled figure moved.