playcanvas / playcanvas/engine
Blinn-Phong Fallback is Not glTF Compliant
@mvaligursky is already working on this.
Since Dec 21, 2025.
- Dominant language
- JavaScript
- Stars
- 16.8k
- Forks
- 2k
- Avg merge
- 4h 32m
- Merged PRs (30d)
- 222
Description
When LIT_GGX_SPECULAR is not enabled, PlayCanvas falls back to Blinn-Phong specular, which is not compliant with the glTF 2.0 PBR specification.
Current Behavior
From litForwardPostCode.js:
#ifdef LIT_SPECULAR
#ifdef LIT_LIGHTING
#ifdef LIT_GGX_SPECULAR
#include "lightSpecularAnisoGGXPS"
#else
#include "lightSpecularBlinnPS" // <-- Non-glTF fallback
#endif
#endif
#endif
The Blinn-Phong implementation:
// lightSpecularBlinn.js
float calcLightSpecular(float gloss, vec3 worldNormal, vec3 h) {
float nh = max(dot(h, worldNormal), 0.0);
float specPow = exp2(gloss * 11.0);
return pow(nh, specPow) * (specPow + 2.0) / 8.0;
}
Problem
- Blinn-Phong produces visually different results from GGX
- Materials authored for glTF will look incorrect when GGX is disabled
- No roughness-based response curve matching glTF expectations
- The highlight shape and falloff characteristics differ significantly
Visual Comparison
| Aspect | GGX (glTF) | Blinn-Phong |
|---|---|---|
| Highlight shape | Long tail, soft falloff | Sharp cutoff |
| Roughness response | Perceptually linear | Exponential |
| Energy conservation | Built-in | Requires normalization |
| Physical basis | Microfacet theory | Empirical |
Suggested Solutions
Option A: Always use GGX for PBR materials
Remove the Blinn-Phong path entirely for standard materials. Keep Blinn-Phong only for legacy/custom materials that explicitly request it.
Option B: Make GGX the default
Change enableGGXSpecular to default to true for StandardMaterial. Deprecate the Blinn-Phong path with a console warning.
Option C: Rename for clarity
Rename enableGGXSpecular to something like useLegacyBlinnPhong (inverted logic). Make GGX the implicit default, requiring explicit opt-in for legacy behavior.
Recommended Approach
Option B is recommended as it:
- Maintains backward compatibility
- Guides users toward correct behavior
- Allows deprecation over time
// In StandardMaterial constructor
this.enableGGXSpecular = true; // Changed from false
// Add deprecation warning
if (options.enableGGXSpecular === false) {
Debug.warnOnce('Blinn-Phong specular is deprecated. Use GGX for glTF compliance.');
}
Files Affected
src/scene/shader-lib/glsl/chunks/lit/frag/pass-forward/litForwardPostCode.jssrc/scene/shader-lib/programs/lit-shader.jssrc/scene/materials/standard-material.js
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.