Skip to content

Commit 7ca7427

Browse files
authored
[BREAKING] Use linear space for vertex colors in gLTF (#8122)
* use linear space for vertex colors in glb parser * move gamma to vertex shader * default to false * add test * ignore vertexColorGamma option
1 parent c131b5d commit 7ca7427

File tree

14 files changed

+61
-11
lines changed

14 files changed

+61
-11
lines changed

src/scene/materials/standard-material-options-builder.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ class StandardMaterialOptionsBuilder {
289289
options.litOptions.useDynamicRefraction = stdMat.useDynamicRefraction;
290290
options.litOptions.dispersion = stdMat.dispersion > 0;
291291
options.litOptions.shadowCatcher = stdMat.shadowCatcher;
292+
293+
options.litOptions.useVertexColorGamma = stdMat.vertexColorGamma;
292294
}
293295

294296
_updateEnvOptions(options, stdMat, scene, cameraShaderParams) {

src/scene/materials/standard-material-options.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class StandardMaterialOptions {
4747

4848
lightMapEncoding = 'linear';
4949

50+
vertexColorGamma = false;
51+
5052
/**
5153
* If normal map contains X in RGB, Y in Alpha, and Z must be reconstructed.
5254
*

src/scene/materials/standard-material-parameters.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ const standardMaterialParameterTypes = {
3333
..._textureParameter('diffuseDetail', true, false),
3434
diffuseDetailMode: 'string',
3535

36+
vertexColorGamma: 'boolean',
37+
3638
specular: 'rgb',
3739
specularTint: 'boolean',
3840
..._textureParameter('specular'),

src/scene/materials/standard-material.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,11 @@ const _tempColor = new Color();
523523
* backfaces.
524524
* @property {boolean} shadowCatcher When enabled, the material will output accumulated directional
525525
* shadow value in linear space as the color.
526+
* @property {boolean} vertexColorGamma When set to true, the vertex shader converts vertex colors
527+
* from gamma to linear space to ensure correct interpolation in the fragment shader. This flag is
528+
* provided for backwards compatibility, allowing users to mark their materials to handle vertex
529+
* colors in gamma space. Defaults to false, which indicates that vertex colors are stored in
530+
* linear space.
526531
*
527532
* @category Graphics
528533
*/
@@ -1194,6 +1199,7 @@ function _defineMaterialProps() {
11941199
_defineFlag('opacityDither', DITHER_NONE);
11951200
_defineFlag('opacityShadowDither', DITHER_NONE);
11961201
_defineFlag('shadowCatcher', false);
1202+
_defineFlag('vertexColorGamma', false);
11971203

11981204
_defineTex2D('diffuse');
11991205
_defineTex2D('specular');

src/scene/shader-lib/glsl/chunks/lit/vert/litMain.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ mat4 dModelMatrix;
6363
6464
#include "litUserCodeVS"
6565
66+
#ifdef VERTEX_COLOR
67+
vec3 decodeGamma(vec3 raw) {
68+
return pow(raw, vec3(2.2));
69+
}
70+
vec4 gammaCorrectInput(vec4 color) {
71+
return vec4(decodeGamma(color.xyz), color.w);
72+
}
73+
#endif
74+
6675
void main(void) {
6776
6877
#include "litUserMainStartVS"
@@ -102,7 +111,11 @@ void main(void) {
102111
#include "uvTransformVS, UV_TRANSFORMS_COUNT"
103112
104113
#ifdef VERTEX_COLOR
105-
vVertexColor = vertex_color;
114+
#ifdef STD_VERTEX_COLOR_GAMMA
115+
vVertexColor = gammaCorrectInput(vertex_color);
116+
#else
117+
vVertexColor = vertex_color;
118+
#endif
106119
#endif
107120
108121
#ifdef LINEAR_DEPTH

src/scene/shader-lib/glsl/chunks/standard/frag/diffuse.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ void getAlbedo() {
2020
#endif
2121
2222
#ifdef STD_DIFFUSE_VERTEX
23-
dAlbedo *= gammaCorrectInput(saturate(vVertexColor.{STD_DIFFUSE_VERTEX_CHANNEL}));
23+
dAlbedo *= saturate(vVertexColor.{STD_DIFFUSE_VERTEX_CHANNEL});
2424
#endif
2525
}
2626
`;

src/scene/shader-lib/glsl/chunks/standard/frag/emissive.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ void getEmission() {
1010
#endif
1111
1212
#ifdef STD_EMISSIVE_VERTEX
13-
dEmission *= gammaCorrectInput(saturate(vVertexColor.{STD_EMISSIVE_VERTEX_CHANNEL}));
13+
dEmission *= saturate(vVertexColor.{STD_EMISSIVE_VERTEX_CHANNEL});
1414
#endif
1515
}
1616
`;

src/scene/shader-lib/programs/lit-shader-options.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ class LitShaderOptions {
8383

8484
vertexColors = false;
8585

86+
useVertexColorGamma = false;
87+
8688
lightMapEnabled = false;
8789

8890
dirLightMapEnabled = false;

src/scene/shader-lib/programs/lit-shader.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ class LitShader {
293293
attributes.vertex_color = SEMANTIC_COLOR;
294294
vDefines.set('VERTEX_COLOR', true);
295295
varyings.set('vVertexColor', 'vec4');
296+
if (options.useVertexColorGamma) {
297+
vDefines.set('STD_VERTEX_COLOR_GAMMA', '');
298+
}
296299
}
297300

298301
if (options.useMsdf && options.msdfTextAttribute) {

src/scene/shader-lib/programs/standard.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,8 @@ class ShaderGeneratorStandard extends ShaderGenerator {
8888
return expression;
8989
}
9090

91-
_validateMapChunk(propName, chunkName, chunks) {
91+
_validateMapChunk(code, propName, chunkName, chunks) {
9292
Debug.call(() => {
93-
// strip comments from the chunk
94-
const code = chunks.get(chunkName).replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1');
95-
9693
const requiredChangeStrings = [];
9794

9895
// Helper function to add a formatted change string if the old syntax is found
@@ -170,7 +167,16 @@ class ShaderGeneratorStandard extends ShaderGenerator {
170167
// log errors if the chunk format is deprecated (format changed in engine 2.7)
171168
Debug.call(() => {
172169
if (chunkCode) {
173-
this._validateMapChunk(propNameCaps, chunkName, chunks);
170+
// strip comments from the chunk
171+
const code = chunks.get(chunkName).replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1');
172+
173+
this._validateMapChunk(code, propNameCaps, chunkName, chunks);
174+
175+
if (vertexColorOption) {
176+
if (code.includes('gammaCorrectInputVec3(saturate3(vVertexColor.') || code.includes('gammaCorrectInput(saturate(vVertexColor.')) {
177+
Debug.errorOnce(`Shader chunk ${chunkName} contains gamma correction code which is incompatible with vertexColorGamma=true. Please remove gamma correction calls from the chunk.`, { code: code });
178+
}
179+
}
174180
}
175181
});
176182

0 commit comments

Comments
 (0)