Skip to content

Commit 05fc79c

Browse files
authored
WebGLRenderer: Remove inline sRGB decode. (mrdoob#23129)
* WebGLRenderer: Remove inline sRGB decode. * Update WebGLTextures.js * VideoTexture: Use inline sRGB decode. * WebGLTexture: Fix video textures with WebGL 1.
1 parent 5655fbe commit 05fc79c

26 files changed

+208
-214
lines changed

examples/jsm/loaders/GLTFLoader.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1478,7 +1478,6 @@ class GLTFMeshStandardSGMaterial extends MeshStandardMaterial {
14781478
'vec3 specularFactor = specular;',
14791479
'#ifdef USE_SPECULARMAP',
14801480
' vec4 texelSpecular = texture2D( specularMap, vUv );',
1481-
' texelSpecular = sRGBToLinear( texelSpecular );',
14821481
' // reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture',
14831482
' specularFactor *= texelSpecular.rgb;',
14841483
'#endif'

examples/jsm/nodes/utils/ColorSpaceNode.js

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ class ColorSpaceNode extends TempNode {
5757

5858
}
5959

60-
fromDecoding( encoding ) {
60+
fromDecoding() {
6161

62-
const components = ColorSpaceNode.getEncodingComponents( encoding );
62+
// TODO: Remove fromDecoding()
63+
64+
const components = ColorSpaceNode.getEncodingComponents( LinearEncoding );
6365

6466
this.method = components[ 0 ] + 'ToLinear';
6567
this.factor = components[ 1 ];
@@ -106,14 +108,6 @@ ColorSpaceNode.Nodes = ( function () {
106108
}`
107109
);
108110

109-
const sRGBToLinear = new FunctionNode( /* glsl */`
110-
vec4 sRGBToLinear( in vec4 value ) {
111-
112-
return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );
113-
114-
}`
115-
);
116-
117111
const LinearTosRGB = new FunctionNode( /* glsl */`
118112
vec4 LinearTosRGB( in vec4 value ) {
119113
@@ -124,15 +118,12 @@ ColorSpaceNode.Nodes = ( function () {
124118

125119
return {
126120
LinearToLinear: LinearToLinear,
127-
sRGBToLinear: sRGBToLinear,
128121
LinearTosRGB: LinearTosRGB
129122
};
130123

131124
} )();
132125

133126
ColorSpaceNode.LINEAR_TO_LINEAR = 'LinearToLinear';
134-
135-
ColorSpaceNode.SRGB_TO_LINEAR = 'sRGBToLinear';
136127
ColorSpaceNode.LINEAR_TO_SRGB = 'LinearTosRGB';
137128

138129
ColorSpaceNode.getEncodingComponents = function ( encoding ) {

examples/jsm/renderers/nodes/display/ColorSpaceNode.js

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import TempNode from '../core/Node.js';
22
import { ShaderNode,
33
vec3,
4-
pow, mul, add, sub, mix, join,
4+
pow, mul, sub, mix, join,
55
lessThanEqual } from '../ShaderNode.js';
66

77
import { LinearEncoding, sRGBEncoding } from '../../../../../build/three.module.js';
@@ -12,22 +12,6 @@ export const LinearToLinear = new ShaderNode( ( inputs ) => {
1212

1313
} );
1414

15-
export const sRGBToLinear = new ShaderNode( ( inputs ) => {
16-
17-
const { value } = inputs;
18-
19-
const rgb = value.rgb;
20-
21-
const a = pow( add( mul( rgb, 0.9478672986 ), vec3( 0.0521327014 ) ), vec3( 2.4 ) );
22-
const b = mul( rgb, 0.0773993808 );
23-
const factor = vec3( lessThanEqual( rgb, vec3( 0.04045 ) ) );
24-
25-
const rgbResult = mix( a, b, factor );
26-
27-
return join( rgbResult.r, rgbResult.g, rgbResult.b, value.a );
28-
29-
} );
30-
3115
export const LinearTosRGB = new ShaderNode( ( inputs ) => {
3216

3317
const { value } = inputs;
@@ -46,7 +30,6 @@ export const LinearTosRGB = new ShaderNode( ( inputs ) => {
4630

4731
const EncodingLib = {
4832
LinearToLinear,
49-
sRGBToLinear,
5033
LinearTosRGB
5134
};
5235

@@ -66,8 +49,6 @@ function getEncodingComponents( encoding ) {
6649
class ColorSpaceNode extends TempNode {
6750

6851
static LINEAR_TO_LINEAR = 'LinearToLinear';
69-
70-
static SRGB_TO_LINEAR = 'sRGBToLinear';
7152
static LINEAR_TO_SRGB = 'LinearTosRGB';
7253

7354
constructor( method, node ) {
@@ -92,9 +73,11 @@ class ColorSpaceNode extends TempNode {
9273

9374
}
9475

95-
fromDecoding( encoding ) {
76+
fromDecoding() {
9677

97-
const components = getEncodingComponents( encoding );
78+
// TODO: Remove fromDecoding()
79+
80+
const components = getEncodingComponents( LinearEncoding );
9881

9982
this.method = components[ 0 ] + 'ToLinear';
10083
this.factor = components[ 1 ];

examples/jsm/utils/RoughnessMipmapper.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,6 @@ function _getMipmapMaterial() {
184184
185185
#define ENVMAP_TYPE_CUBE_UV
186186
187-
vec4 envMapTexelToLinear( vec4 a ) { return a; }
188-
189187
#include <cube_uv_reflection_fragment>
190188
191189
float roughnessToVariance( float roughness ) {

examples/webgl_lightprobe_cubecamera.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
camera.position.set( 0, 0, 30 );
4444

4545
const cubeRenderTarget = new THREE.WebGLCubeRenderTarget( 256, {
46-
encoding: THREE.sRGBEncoding, // since gamma is applied during rendering, the cubeCamera renderTarget texture encoding must be sRGBEncoding
4746
format: THREE.RGBAFormat
4847
} );
4948

examples/webgl_materials_nodes.html

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@
4040
const library = {};
4141
let serialized = false;
4242
const textures = {
43-
brick: { url: 'textures/brick_diffuse.jpg' },
44-
grass: { url: 'textures/terrain/grasslight-big.jpg' },
45-
grassNormal: { url: 'textures/terrain/grasslight-big-nm.jpg' },
46-
decalDiffuse: { url: 'textures/decal/decal-diffuse.png' },
47-
decalNormal: { url: 'textures/decal/decal-normal.jpg' },
48-
cloud: { url: 'textures/lava/cloud.png' },
49-
spherical: { url: 'textures/envmap.png' }
43+
brick: { url: 'textures/brick_diffuse.jpg', encoding: THREE.sRGBEncoding },
44+
grass: { url: 'textures/terrain/grasslight-big.jpg', encoding: THREE.sRGBEncoding },
45+
grassNormal: { url: 'textures/terrain/grasslight-big-nm.jpg', encoding: THREE.LinearEncoding },
46+
decalDiffuse: { url: 'textures/decal/decal-diffuse.png', encoding: THREE.sRGBEncoding },
47+
decalNormal: { url: 'textures/decal/decal-normal.jpg', encoding: THREE.LinearEncoding },
48+
cloud: { url: 'textures/lava/cloud.png', encoding: THREE.sRGBEncoding },
49+
spherical: { url: 'textures/envmap.png', encoding: THREE.sRGBEncoding }
5050
};
5151

5252
const param = { example: new URL( window.location.href ).searchParams.get( 'e' ) || 'mesh-standard' };
@@ -59,6 +59,7 @@
5959

6060
texture = textures[ name ].texture = new THREE.TextureLoader().load( textures[ name ].url );
6161
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
62+
texture.encoding = textures[ name ].encoding;
6263

6364
library[ texture.uuid ] = texture;
6465

@@ -187,7 +188,7 @@
187188
'basic / spherical-reflection': 'spherical-reflection',
188189
'basic / standard': 'standard',
189190
'basic / uv-transform': 'uv-transform',
190-
191+
191192
'adv / bias': 'bias',
192193
'adv / camera-depth': 'camera-depth',
193194
'adv / caustic': 'caustic',
@@ -215,7 +216,7 @@
215216
'node / normal': 'node-normal',
216217
'node / position': 'node-position',
217218
'node / reflect': 'node-reflect',
218-
219+
219220
'misc / basic-material': 'basic-material',
220221
'misc / custom-attribute': 'custom-attribute',
221222
'misc / firefly': 'firefly',

src/constants.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,3 +177,6 @@ export const StreamCopyUsage = 35042;
177177

178178
export const GLSL1 = '100';
179179
export const GLSL3 = '300 es';
180+
181+
export const _SRGBFormat = 1034; // fallback for WebGL 1
182+
export const _SRGBAFormat = 1035; // fallback for WebGL 1

src/extras/ImageUtils.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createElementNS } from '../utils.js';
2+
import { SRGBToLinear } from '../math/Color.js';
23

34
let _canvas;
45

@@ -61,6 +62,68 @@ class ImageUtils {
6162

6263
}
6364

65+
static sRGBToLinear( image ) {
66+
67+
if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
68+
( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
69+
( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {
70+
71+
const canvas = createElementNS( 'canvas' );
72+
73+
canvas.width = image.width;
74+
canvas.height = image.height;
75+
76+
const context = canvas.getContext( '2d' );
77+
context.drawImage( image, 0, 0, image.width, image.height );
78+
79+
const imageData = context.getImageData( 0, 0, image.width, image.height );
80+
const data = imageData.data;
81+
82+
for ( let i = 0; i < data.length; i ++ ) {
83+
84+
data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255;
85+
86+
}
87+
88+
context.putImageData( imageData, 0, 0 );
89+
90+
return canvas;
91+
92+
} else if ( image.data ) {
93+
94+
const data = image.data.slice( 0 );
95+
96+
for ( let i = 0; i < data.length; i ++ ) {
97+
98+
if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) {
99+
100+
data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 );
101+
102+
} else {
103+
104+
// assuming float
105+
106+
data[ i ] = SRGBToLinear( data[ i ] );
107+
108+
}
109+
110+
}
111+
112+
return {
113+
data: data,
114+
width: image.width,
115+
height: image.height
116+
};
117+
118+
} else {
119+
120+
console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' );
121+
return image;
122+
123+
}
124+
125+
}
126+
64127
}
65128

66129
export { ImageUtils };

0 commit comments

Comments
 (0)