CNA-GAP-032: Engine-layer PBR limits: one punctual light per PbrEffect draw, 8-bit environment cubes, no back-face normal flip for double-sided materials, no alpha-tested shadow casters

CNA snapshot 009d40f5  ·  Known Issues › Functional gaps  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

PbrEffect takes one punctual light, EnvironmentProcessor builds its cubes as SurfaceFormat::Color, no stock or engine-layer shader reads a front-facing input to flip normals, and the shadow-caster shaders write depth without an alpha test.

Identifier
CNA-GAP-032
Category
Functional gap
Subsystem
Graphics & renderers
Status
Open
Verified against
CNA 009d40f5 (009d40f5dd085c4e674d3479675fac84b12b3e0a)
Evidence basis
Source-verified: read at TARGET, not executed
Tests touching this area
Yes: see Current tests
Affected contract
PbrEffect::setPunctualLightEXT; CNA::Graphics::EnvironmentProcessor; PbrEffect::getDoubleSidedEXTProperty; the engine layer's shadow-caster passes

Expected behaviour

glTF 2.0 reverses the normal of a back face of a double-sided material before lighting and lets alpha-mask materials cut out their shadows; HDR image-based lighting keeps radiance above 1.0.

Actual behaviour at TARGET

PbrEffect.hpp holds a single PunctualLightEXT (documented as a deliberate ceiling in cnaext-engine-layer.md). EnvironmentProcessor.cpp creates every generated cube as SurfaceFormat::Color. The doubleSided mapping in gltf-limitations.md selects CullNone; no shader under modules/ used by the stock PBR or engine-layer paths reads gl_FrontFacing, SV_IsFrontFace or a WGSL/MSL front-facing builtin, so back faces are lit with the front normal. The shadow-caster shaders in modules/graphics-ext/src/shaders/shadow_caster sample no texture and never discard, so alpha-tested geometry casts solid shadows.

Source locations

Evidence

Checked by reading at 009d40f5 (the front-facing search was a grep of all of modules/); not executed. The four limits were reported by the living-room-simulator sample @ 2bf3f56b against an earlier CNA revision and re-established individually here.

Independent re-verification: Checked by reading at 009d40f5 (the front-facing search was a grep of all of modules/, docs and tools: front-facing inputs appear only in compiled-effect translation, the Software compiled-effect runtime and PortableGL's rasteriser, not in the stock PBR or engine-layer shaders; doubleSided never reaches GpuDrawParams); not executed. The four limits were reported by the living-room-simulator sample @ 2bf3f56b against an earlier CNA revision and re-established individually here. Tests: engine-layer shadow, IBL and PBR tests exist; the EasyGL_Gltf_AlphaBlend example draws a double-sided back face under CullNone but with ambient-only lighting and no directional light, so no test lights a back face, casts an alpha-masked shadow, or carries HDR radiance through an environment cube.

Focused reproduction

No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.

Current tests

Engine-layer shadow, IBL and PBR tests exist; none draws a double-sided back face, an alpha-masked shadow caster or HDR environment radiance.

Regression test

Per limit, once lifted: a back-face lighting pixel test, an alpha-mask shadow test, an IBL test with radiance above 1.0, and a two-punctual-light draw.

Blast radius

glTF scenes with double-sided foliage or cloth, cut-out shadow casters, bright HDR environments, or several shadowed punctual lights per object.

Workaround

Duplicate double-sided geometry with flipped normals; split draws per punctual light.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.