From 26680da6624534f5eb882da2726086438b5b1acb Mon Sep 17 00:00:00 2001 From: Cyrus Date: Fri, 24 Nov 2023 19:51:45 +0800 Subject: [PATCH 1/3] add sRGBToLinearWithShader to Texture --- src/renderers/WebGLRenderer.js | 2 +- src/renderers/webgl/WebGLTextures.js | 14 +++++++------- src/textures/Texture.js | 5 +++++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index dff73c594f1be8..9f8bd79b134173 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -599,7 +599,7 @@ function WebGLRenderer( parameters = {} ) { } - if ( capabilities.isWebGL2 && Texture.useSrgbTextures && map && map.isTexture && map.format === RGBAFormat && map.type === UnsignedByteType && map.encoding === sRGBEncoding ) { + if ( capabilities.isWebGL2 && map && map.isTexture && map.format === RGBAFormat && map.type === UnsignedByteType && map.encoding === sRGBEncoding && !map.sRGBToLinearWithShader ) { encoding = LinearEncoding; // disable inline decode for sRGB textures in WebGL 2 diff --git a/src/renderers/webgl/WebGLTextures.js b/src/renderers/webgl/WebGLTextures.js index 5b27370f8ebac6..32d61bcb073469 100644 --- a/src/renderers/webgl/WebGLTextures.js +++ b/src/renderers/webgl/WebGLTextures.js @@ -131,7 +131,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - function getInternalFormat( internalFormatName, glFormat, glType, encoding ) { + function getInternalFormat( internalFormatName, glFormat, glType, encoding, sRGBToLinearWithShader = !Texture.useSrgbTextures ) { if ( isWebGL2 === false ) return glFormat; @@ -165,7 +165,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; - if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( isWebGL2 && Texture.useSrgbTextures && encoding === sRGBEncoding ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( isWebGL2 && encoding === sRGBEncoding && !sRGBToLinearWithShader ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4; if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1; @@ -562,7 +562,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, glFormat = utils.convert( texture.format, texture.encoding ); let glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.sRGBToLinearWithShader ); setTextureParameters( textureType, texture, supportsMips ); @@ -921,7 +921,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, supportsMips = isPowerOfTwo( image ) || isWebGL2, glFormat = utils.convert( texture.format, texture.encoding ), glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.sRGBToLinearWithShader ); const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true ); const allocateMemory = ( textureProperties.__version === undefined ); @@ -1086,7 +1086,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glFormat = utils.convert( texture.format, texture.encoding ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.sRGBToLinearWithShader ); const renderTargetProperties = properties.get( renderTarget ); if ( ! renderTargetProperties.__hasExternalTextures ) { @@ -1194,7 +1194,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glFormat = utils.convert( texture.format, texture.encoding ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.sRGBToLinearWithShader ); const samples = getRenderTargetSamples( renderTarget ); if ( isMultisample && renderTarget.useRenderbuffer ) { @@ -1419,7 +1419,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glFormat = utils.convert( texture.format, texture.encoding ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding, texture.sRGBToLinearWithShader ); const samples = getRenderTargetSamples( renderTarget ); _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); diff --git a/src/textures/Texture.js b/src/textures/Texture.js index a3d145ac9be0aa..5b58edbc1c3a17 100644 --- a/src/textures/Texture.js +++ b/src/textures/Texture.js @@ -73,6 +73,11 @@ class Texture extends EventDispatcher { this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not this.needsPMREMUpdate = false; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) + // In WebGL2, sRGB textures can be trancoded to Linear automatically, but reference to this issue: https://github.com/mrdoob/three.js/issues/26183 + // there're performance issues when doing this, so you can set the sRGBToLinearWithShader to false to transcode the sRGB texture to Linear with + // shader, especially to those textures that are updated in each frame + this.sRGBToLinearWithShader = !Texture.useSrgbTextures; + } updateMatrix() { From e342da5cf2502fe9137ac9fc3411d3c0e1c98b2c Mon Sep 17 00:00:00 2001 From: Cyrus Date: Fri, 24 Nov 2023 19:59:02 +0800 Subject: [PATCH 2/3] add space after ! --- src/renderers/WebGLRenderer.js | 2 +- src/renderers/webgl/WebGLTextures.js | 4 ++-- src/textures/Texture.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 9f8bd79b134173..4eaa3313cdc063 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -599,7 +599,7 @@ function WebGLRenderer( parameters = {} ) { } - if ( capabilities.isWebGL2 && map && map.isTexture && map.format === RGBAFormat && map.type === UnsignedByteType && map.encoding === sRGBEncoding && !map.sRGBToLinearWithShader ) { + if ( capabilities.isWebGL2 && map && map.isTexture && map.format === RGBAFormat && map.type === UnsignedByteType && map.encoding === sRGBEncoding && ! map.sRGBToLinearWithShader ) { encoding = LinearEncoding; // disable inline decode for sRGB textures in WebGL 2 diff --git a/src/renderers/webgl/WebGLTextures.js b/src/renderers/webgl/WebGLTextures.js index 32d61bcb073469..e2299e06fb8a2a 100644 --- a/src/renderers/webgl/WebGLTextures.js +++ b/src/renderers/webgl/WebGLTextures.js @@ -131,7 +131,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - function getInternalFormat( internalFormatName, glFormat, glType, encoding, sRGBToLinearWithShader = !Texture.useSrgbTextures ) { + function getInternalFormat( internalFormatName, glFormat, glType, encoding, sRGBToLinearWithShader = ! Texture.useSrgbTextures ) { if ( isWebGL2 === false ) return glFormat; @@ -165,7 +165,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F; if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F; - if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( isWebGL2 && encoding === sRGBEncoding && !sRGBToLinearWithShader ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( isWebGL2 && encoding === sRGBEncoding && ! sRGBToLinearWithShader ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4; if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1; diff --git a/src/textures/Texture.js b/src/textures/Texture.js index 5b58edbc1c3a17..0454b620ed6d6c 100644 --- a/src/textures/Texture.js +++ b/src/textures/Texture.js @@ -76,7 +76,7 @@ class Texture extends EventDispatcher { // In WebGL2, sRGB textures can be trancoded to Linear automatically, but reference to this issue: https://github.com/mrdoob/three.js/issues/26183 // there're performance issues when doing this, so you can set the sRGBToLinearWithShader to false to transcode the sRGB texture to Linear with // shader, especially to those textures that are updated in each frame - this.sRGBToLinearWithShader = !Texture.useSrgbTextures; + this.sRGBToLinearWithShader = ! Texture.useSrgbTextures; } From 68476cfb7414b9445faa5074de27235fdb38b370 Mon Sep 17 00:00:00 2001 From: Cyrus Date: Mon, 27 Nov 2023 12:14:42 +0800 Subject: [PATCH 3/3] fix test of webgl_srgb_textures --- examples/webgl_srgb_textures.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/webgl_srgb_textures.html b/examples/webgl_srgb_textures.html index 30d1fde11294e9..d5d0b3afecc26e 100644 --- a/examples/webgl_srgb_textures.html +++ b/examples/webgl_srgb_textures.html @@ -35,7 +35,7 @@ import * as THREE from '@oppentech/three'; - let camera, scene, renderer1, renderer2; + let camera, scene, renderer1, renderer2, texture; init(); @@ -52,8 +52,9 @@ const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); - new THREE.TextureLoader().load('textures/checkboard.png', ( texture ) => { + new THREE.TextureLoader().load('textures/checkboard.png', ( tex ) => { + texture = tex; texture.encoding = THREE.sRGBEncoding; material.map = texture; animate(); @@ -80,10 +81,10 @@ requestAnimationFrame( animate ); - THREE.Texture.useSrgbTextures = true; + texture.sRGBToLinearWithShader = false; renderer1.render( scene, camera ); - THREE.Texture.useSrgbTextures = false; + texture.sRGBToLinearWithShader = true; renderer2.render( scene, camera ); }