playcanvas / playcanvas/engine

Blinn-Phong Fallback is Not glTF Compliant

Open
#8,296 0 comments 0 reactions 1 assignee View on GitHub

@mvaligursky is already working on this.

Since Dec 21, 2025.

area: graphics
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.js
  • src/scene/shader-lib/programs/lit-shader.js
  • src/scene/materials/standard-material.js

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.