Skip to content

Commit

Permalink
Revert "WebGLRenderer: Remove inline sRGB decode. (mrdoob#23129)"
Browse files Browse the repository at this point in the history
This reverts commit 05fc79c.
  • Loading branch information
chubei-oppen committed Mar 16, 2022
1 parent efbfc67 commit c5546e1
Show file tree
Hide file tree
Showing 25 changed files with 214 additions and 210 deletions.
1 change: 1 addition & 0 deletions examples/jsm/loaders/GLTFLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -1477,6 +1477,7 @@ class GLTFMeshStandardSGMaterial extends MeshStandardMaterial {
'vec3 specularFactor = specular;',
'#ifdef USE_SPECULARMAP',
' vec4 texelSpecular = texture2D( specularMap, vUv );',
' texelSpecular = sRGBToLinear( texelSpecular );',
' // reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture',
' specularFactor *= texelSpecular.rgb;',
'#endif'
Expand Down
17 changes: 13 additions & 4 deletions examples/jsm/nodes/utils/ColorSpaceNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,9 @@ class ColorSpaceNode extends TempNode {

}

fromDecoding() {
fromDecoding( encoding ) {

// TODO: Remove fromDecoding()

const components = ColorSpaceNode.getEncodingComponents( LinearEncoding );
const components = ColorSpaceNode.getEncodingComponents( encoding );

this.method = components[ 0 ] + 'ToLinear';
this.factor = components[ 1 ];
Expand Down Expand Up @@ -108,6 +106,14 @@ ColorSpaceNode.Nodes = ( function () {
}`
);

const sRGBToLinear = new FunctionNode( /* glsl */`
vec4 sRGBToLinear( in vec4 value ) {
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 );
}`
);

const LinearTosRGB = new FunctionNode( /* glsl */`
vec4 LinearTosRGB( in vec4 value ) {
Expand All @@ -118,12 +124,15 @@ ColorSpaceNode.Nodes = ( function () {

return {
LinearToLinear: LinearToLinear,
sRGBToLinear: sRGBToLinear,
LinearTosRGB: LinearTosRGB
};

} )();

ColorSpaceNode.LINEAR_TO_LINEAR = 'LinearToLinear';

ColorSpaceNode.SRGB_TO_LINEAR = 'sRGBToLinear';
ColorSpaceNode.LINEAR_TO_SRGB = 'LinearTosRGB';

ColorSpaceNode.getEncodingComponents = function ( encoding ) {
Expand Down
21 changes: 20 additions & 1 deletion examples/jsm/renderers/nodes/display/ColorSpaceNode.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import TempNode from '../core/Node.js';
import { ShaderNode,
vec3,
pow, mul, sub, mix, join,
pow, mul, add, sub, mix, join,
lessThanEqual } from '../ShaderNode.js';

import { LinearEncoding, sRGBEncoding } from 'three';
Expand All @@ -12,6 +12,22 @@ export const LinearToLinear = new ShaderNode( ( inputs ) => {

} );

export const sRGBToLinear = new ShaderNode( ( inputs ) => {

const { value } = inputs;

const rgb = value.rgb;

const a = pow( add( mul( rgb, 0.9478672986 ), vec3( 0.0521327014 ) ), vec3( 2.4 ) );
const b = mul( rgb, 0.0773993808 );
const factor = vec3( lessThanEqual( rgb, vec3( 0.04045 ) ) );

const rgbResult = mix( a, b, factor );

return join( rgbResult.r, rgbResult.g, rgbResult.b, value.a );

} );

export const LinearTosRGB = new ShaderNode( ( inputs ) => {

const { value } = inputs;
Expand All @@ -30,12 +46,15 @@ export const LinearTosRGB = new ShaderNode( ( inputs ) => {

const EncodingLib = {
LinearToLinear,
sRGBToLinear,
LinearTosRGB
};

class ColorSpaceNode extends TempNode {

static LINEAR_TO_LINEAR = 'LinearToLinear';

static SRGB_TO_LINEAR = 'sRGBToLinear';
static LINEAR_TO_SRGB = 'LinearTosRGB';

constructor( method, node ) {
Expand Down
5 changes: 4 additions & 1 deletion examples/webgl_lightprobe_cubecamera.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 0, 30 );

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

cubeCamera = new THREE.CubeCamera( 1, 1000, cubeRenderTarget );

Expand Down
19 changes: 9 additions & 10 deletions examples/webgl_materials_nodes.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@
const library = {};
let serialized = false;
const textures = {
brick: { url: 'textures/brick_diffuse.jpg', encoding: THREE.sRGBEncoding },
grass: { url: 'textures/terrain/grasslight-big.jpg', encoding: THREE.sRGBEncoding },
grassNormal: { url: 'textures/terrain/grasslight-big-nm.jpg', encoding: THREE.LinearEncoding },
decalDiffuse: { url: 'textures/decal/decal-diffuse.png', encoding: THREE.sRGBEncoding },
decalNormal: { url: 'textures/decal/decal-normal.jpg', encoding: THREE.LinearEncoding },
cloud: { url: 'textures/lava/cloud.png', encoding: THREE.sRGBEncoding },
spherical: { url: 'textures/envmap.png', encoding: THREE.sRGBEncoding }
brick: { url: 'textures/brick_diffuse.jpg' },
grass: { url: 'textures/terrain/grasslight-big.jpg' },
grassNormal: { url: 'textures/terrain/grasslight-big-nm.jpg' },
decalDiffuse: { url: 'textures/decal/decal-diffuse.png' },
decalNormal: { url: 'textures/decal/decal-normal.jpg' },
cloud: { url: 'textures/lava/cloud.png' },
spherical: { url: 'textures/envmap.png' }
};

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

texture = textures[ name ].texture = new THREE.TextureLoader().load( textures[ name ].url );
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.encoding = textures[ name ].encoding;

library[ texture.uuid ] = texture;

Expand Down Expand Up @@ -200,7 +199,7 @@
'basic / spherical-reflection': 'spherical-reflection',
'basic / standard': 'standard',
'basic / uv-transform': 'uv-transform',

'adv / bias': 'bias',
'adv / camera-depth': 'camera-depth',
'adv / caustic': 'caustic',
Expand Down Expand Up @@ -228,7 +227,7 @@
'node / normal': 'node-normal',
'node / position': 'node-position',
'node / reflect': 'node-reflect',

'misc / basic-material': 'basic-material',
'misc / custom-attribute': 'custom-attribute',
'misc / firefly': 'firefly',
Expand Down
2 changes: 0 additions & 2 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,5 +175,3 @@ export const StreamCopyUsage = 35042;

export const GLSL1 = '100';
export const GLSL3 = '300 es';

export const _SRGBAFormat = 1035; // fallback for WebGL 1
63 changes: 0 additions & 63 deletions src/extras/ImageUtils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createElementNS } from '../utils.js';
import { SRGBToLinear } from '../math/Color.js';

let _canvas;

Expand Down Expand Up @@ -62,68 +61,6 @@ class ImageUtils {

}

static sRGBToLinear( image ) {

if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||
( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||
( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {

const canvas = createElementNS( 'canvas' );

canvas.width = image.width;
canvas.height = image.height;

const context = canvas.getContext( '2d' );
context.drawImage( image, 0, 0, image.width, image.height );

const imageData = context.getImageData( 0, 0, image.width, image.height );
const data = imageData.data;

for ( let i = 0; i < data.length; i ++ ) {

data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255;

}

context.putImageData( imageData, 0, 0 );

return canvas;

} else if ( image.data ) {

const data = image.data.slice( 0 );

for ( let i = 0; i < data.length; i ++ ) {

if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) {

data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 );

} else {

// assuming float

data[ i ] = SRGBToLinear( data[ i ] );

}

}

return {
data: data,
width: image.width,
height: image.height
};

} else {

console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' );
return image;

}

}

}

export { ImageUtils };
76 changes: 69 additions & 7 deletions src/extras/PMREMGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
NoToneMapping,
NoBlending,
RGBAFormat,
UnsignedByteType,
sRGBEncoding,
HalfFloatType
} from '../constants.js';

Expand Down Expand Up @@ -40,6 +42,11 @@ const TOTAL_LODS = LOD_MAX - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
// samples and exit early, but not recompile the shader.
const MAX_SAMPLES = 20;

const ENCODINGS = {
[ LinearEncoding ]: 0,
[ sRGBEncoding ]: 1
};

const _flatCamera = /*@__PURE__*/ new OrthographicCamera();
const { _lodPlanes, _sizeLods, _sigmas } = /*@__PURE__*/ _createPlanes();
const _clearColor = /*@__PURE__*/ new Color();
Expand Down Expand Up @@ -335,6 +342,20 @@ class PMREMGenerator {

}

_setEncoding( uniform, texture ) {

if ( this._renderer.capabilities.isWebGL2 === true && texture.format === RGBAFormat && texture.type === UnsignedByteType && texture.encoding === sRGBEncoding ) {

uniform.value = ENCODINGS[ LinearEncoding ];

} else {

uniform.value = ENCODINGS[ texture.encoding ];

}

}

_textureToCubeUV( texture, cubeUVRenderTarget ) {

const renderer = this._renderer;
Expand Down Expand Up @@ -374,6 +395,8 @@ class PMREMGenerator {

}

this._setEncoding( uniforms[ 'inputEncoding' ], texture );

_setViewport( cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );

renderer.setRenderTarget( cubeUVRenderTarget );
Expand Down Expand Up @@ -648,6 +671,8 @@ function _getBlurShader( maxSamples ) {
uniform float mipInt;
uniform vec3 poleAxis;
${ _getEncodings() }
#define ENVMAP_TYPE_CUBE_UV
#include <cube_uv_reflection_fragment>
Expand Down Expand Up @@ -714,7 +739,8 @@ function _getEquirectShader() {

uniforms: {
'envMap': { value: null },
'texelSize': { value: texelSize }
'texelSize': { value: texelSize },
'inputEncoding': { value: ENCODINGS[ LinearEncoding ] }
},

vertexShader: _getCommonVertexShader(),
Expand All @@ -729,6 +755,8 @@ function _getEquirectShader() {
uniform sampler2D envMap;
uniform vec2 texelSize;
${ _getEncodings() }
#include <common>
void main() {
Expand All @@ -740,13 +768,13 @@ function _getEquirectShader() {
vec2 f = fract( uv / texelSize - 0.5 );
uv -= f * texelSize;
vec3 tl = texture2D ( envMap, uv ).rgb;
vec3 tl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
uv.x += texelSize.x;
vec3 tr = texture2D ( envMap, uv ).rgb;
vec3 tr = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
uv.y += texelSize.y;
vec3 br = texture2D ( envMap, uv ).rgb;
vec3 br = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
uv.x -= texelSize.x;
vec3 bl = texture2D ( envMap, uv ).rgb;
vec3 bl = envMapTexelToLinear( texture2D ( envMap, uv ) ).rgb;
vec3 tm = mix( tl, tr, f.x );
vec3 bm = mix( bl, br, f.x );
Expand All @@ -773,7 +801,8 @@ function _getCubemapShader() {

uniforms: {
'envMap': { value: null },
'flipEnvMap': { value: - 1 }
'flipEnvMap': { value: - 1 },
'inputEncoding': { value: ENCODINGS[ LinearEncoding ] }
},

vertexShader: _getCommonVertexShader(),
Expand All @@ -789,9 +818,11 @@ function _getCubemapShader() {
uniform samplerCube envMap;
${ _getEncodings() }
void main() {
gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );
gl_FragColor = envMapTexelToLinear( textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) ) );
}
`,
Expand Down Expand Up @@ -869,4 +900,35 @@ function _getCommonVertexShader() {

}

function _getEncodings() {

return /* glsl */`
uniform int inputEncoding;
#include <encodings_pars_fragment>
vec4 inputTexelToLinear( vec4 value ) {
if ( inputEncoding == 0 ) {
return value;
} else {
return sRGBToLinear( value );
}
}
vec4 envMapTexelToLinear( vec4 color ) {
return inputTexelToLinear( color );
}
`;

}

export { PMREMGenerator };
Loading

0 comments on commit c5546e1

Please sign in to comment.