diff --git a/examples/jsm/loaders/GLTFLoader.js b/examples/jsm/loaders/GLTFLoader.js index 65c85b96290e83..18c9114d3adbaa 100644 --- a/examples/jsm/loaders/GLTFLoader.js +++ b/examples/jsm/loaders/GLTFLoader.js @@ -2761,11 +2761,6 @@ class GLTFParser { let sourceURI = source.uri || ''; let isObjectURL = false; - let hasAlpha = true; - - const isJPEG = sourceURI.search( /\.jpe?g($|\?)/i ) > 0 || sourceURI.search( /^data\:image\/jpeg/ ) === 0; - - if ( source.mimeType === 'image/jpeg' || isJPEG ) hasAlpha = false; if ( source.bufferView !== undefined ) { @@ -2773,19 +2768,6 @@ class GLTFParser { sourceURI = parser.getDependency( 'bufferView', source.bufferView ).then( function ( bufferView ) { - if ( source.mimeType === 'image/png' ) { - - // Inspect the PNG 'IHDR' chunk to determine whether the image could have an - // alpha channel. This check is conservative — the image could have an alpha - // channel with all values == 1, and the indexed type (colorType == 3) only - // sometimes contains alpha. - // - // https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header - const colorType = new DataView( bufferView, 25, 1 ).getUint8( 0, false ); - hasAlpha = colorType === 6 || colorType === 4 || colorType === 3; - - } - isObjectURL = true; const blob = new Blob( [ bufferView ], { type: source.mimeType } ); sourceURI = URL.createObjectURL( blob ); @@ -2836,9 +2818,6 @@ class GLTFParser { if ( textureDef.name ) texture.name = textureDef.name; - // When there is definitely no alpha channel in the texture, set RGBFormat to save space. - if ( ! hasAlpha ) texture.format = RGBFormat; - const samplers = json.samplers || {}; const sampler = samplers[ textureDef.sampler ] || {}; diff --git a/examples/jsm/postprocessing/SSRPass.js b/examples/jsm/postprocessing/SSRPass.js index f3230968b035a8..bfd994155df7e5 100644 --- a/examples/jsm/postprocessing/SSRPass.js +++ b/examples/jsm/postprocessing/SSRPass.js @@ -24,7 +24,7 @@ import { CopyShader } from '../shaders/CopyShader.js'; class SSRPass extends Pass { - constructor( { renderer, scene, camera, width, height, selects, encoding, bouncing = false, groundReflector } ) { + constructor( { renderer, scene, camera, width, height, selects, bouncing = false, groundReflector } ) { super(); @@ -44,8 +44,6 @@ class SSRPass extends Pass { this.maxDistance = SSRShader.uniforms.maxDistance.value; this.thickness = SSRShader.uniforms.thickness.value; - this.encoding = encoding; - this.tempColor = new Color(); this._selects = selects; @@ -359,7 +357,6 @@ class SSRPass extends Pass { // render beauty and depth - if ( this.encoding ) this.beautyRenderTarget.texture.encoding = this.encoding; renderer.setRenderTarget( this.beautyRenderTarget ); renderer.clear(); if ( this.groundReflector ) { diff --git a/examples/jsm/postprocessing/SSRrPass.js b/examples/jsm/postprocessing/SSRrPass.js index ceba0eeabbca56..8719e28dea3c92 100644 --- a/examples/jsm/postprocessing/SSRrPass.js +++ b/examples/jsm/postprocessing/SSRrPass.js @@ -24,7 +24,7 @@ import { CopyShader } from '../shaders/CopyShader.js'; class SSRrPass extends Pass { - constructor( { renderer, scene, camera, width, height, selects, encoding } ) { + constructor( { renderer, scene, camera, width, height, selects } ) { super(); @@ -44,8 +44,6 @@ class SSRrPass extends Pass { this.maxDistance = SSRrShader.uniforms.maxDistance.value; this.surfDist = SSRrShader.uniforms.surfDist.value; - this.encoding = encoding; - this.tempColor = new Color(); this.selects = selects; @@ -274,7 +272,6 @@ class SSRrPass extends Pass { // render beauty and depth - if ( this.encoding ) this.beautyRenderTarget.texture.encoding = this.encoding; renderer.setRenderTarget( this.beautyRenderTarget ); renderer.clear(); this.scene.children.forEach( child => { diff --git a/examples/screenshots/webgl_lightprobe.jpg b/examples/screenshots/webgl_lightprobe.jpg index 688274f6582824..b74517ab08c8ca 100644 Binary files a/examples/screenshots/webgl_lightprobe.jpg and b/examples/screenshots/webgl_lightprobe.jpg differ diff --git a/examples/screenshots/webgl_loader_md2.jpg b/examples/screenshots/webgl_loader_md2.jpg index c03788ba5c9e47..25fa51c4ce291c 100644 Binary files a/examples/screenshots/webgl_loader_md2.jpg and b/examples/screenshots/webgl_loader_md2.jpg differ diff --git a/examples/screenshots/webgl_materials_displacementmap.jpg b/examples/screenshots/webgl_materials_displacementmap.jpg index 10e701f8c44a5d..716fa699d79904 100644 Binary files a/examples/screenshots/webgl_materials_displacementmap.jpg and b/examples/screenshots/webgl_materials_displacementmap.jpg differ diff --git a/examples/screenshots/webgl_postprocessing_ssr.jpg b/examples/screenshots/webgl_postprocessing_ssr.jpg index 879d7ee80648c1..45e3fef142b0fe 100644 Binary files a/examples/screenshots/webgl_postprocessing_ssr.jpg and b/examples/screenshots/webgl_postprocessing_ssr.jpg differ diff --git a/examples/screenshots/webgl_postprocessing_ssrr.jpg b/examples/screenshots/webgl_postprocessing_ssrr.jpg index da04b215a20652..4ba4dcc598d6aa 100644 Binary files a/examples/screenshots/webgl_postprocessing_ssrr.jpg and b/examples/screenshots/webgl_postprocessing_ssrr.jpg differ diff --git a/examples/webgl_postprocessing_ssr.html b/examples/webgl_postprocessing_ssr.html index 76b4302f7bf8b0..f27bf2e36fbe66 100644 --- a/examples/webgl_postprocessing_ssr.html +++ b/examples/webgl_postprocessing_ssr.html @@ -27,6 +27,8 @@ import { GUI } from './jsm/libs/dat.gui.module.js'; import { EffectComposer } from './jsm/postprocessing/EffectComposer.js'; import { SSRPass } from './jsm/postprocessing/SSRPass.js'; + import { ShaderPass } from './jsm/postprocessing/ShaderPass.js'; + import { GammaCorrectionShader } from './jsm/shaders/GammaCorrectionShader.js'; import { ReflectorForSSRPass } from './jsm/objects/ReflectorForSSRPass.js'; import { DRACOLoader } from './jsm/loaders/DRACOLoader.js'; @@ -144,7 +146,6 @@ // renderer renderer = new THREE.WebGLRenderer( { antialias: false } ); renderer.setSize( window.innerWidth, window.innerHeight ); - renderer.outputEncoding = THREE.sRGBEncoding; container.appendChild( renderer.domElement ); // @@ -171,12 +172,12 @@ camera, width: innerWidth, height: innerHeight, - encoding: THREE.sRGBEncoding, groundReflector: params.groundReflector ? groundReflector : null, selects: params.groundReflector ? selects : null } ); composer.addPass( ssrPass ); + composer.addPass( new ShaderPass( GammaCorrectionShader ) ); // GUI diff --git a/examples/webgl_postprocessing_ssrr.html b/examples/webgl_postprocessing_ssrr.html index 6c879a6d02ea58..7425073ecd993e 100644 --- a/examples/webgl_postprocessing_ssrr.html +++ b/examples/webgl_postprocessing_ssrr.html @@ -28,6 +28,8 @@ import { GUI } from './jsm/libs/dat.gui.module.js'; import { EffectComposer } from './jsm/postprocessing/EffectComposer.js'; import { SSRrPass } from './jsm/postprocessing/SSRrPass.js'; + import { ShaderPass } from './jsm/postprocessing/ShaderPass.js'; + import { GammaCorrectionShader } from './jsm/shaders/GammaCorrectionShader.js'; import { DRACOLoader } from './jsm/loaders/DRACOLoader.js'; @@ -147,7 +149,6 @@ // renderer renderer = new THREE.WebGLRenderer( { antialias: false } ); renderer.setSize( window.innerWidth, window.innerHeight ); - renderer.outputEncoding = THREE.sRGBEncoding; renderer.autoClear = false; container.appendChild( renderer.domElement ); @@ -177,11 +178,11 @@ camera, width: innerWidth, height: innerHeight, - encoding: THREE.sRGBEncoding, selects: selects } ); composer.addPass( ssrrPass ); + composer.addPass( new ShaderPass( GammaCorrectionShader ) ); // GUI diff --git a/src/extras/PMREMGenerator.js b/src/extras/PMREMGenerator.js index 2fd04d65c44f2c..1a81229965e7e4 100644 --- a/src/extras/PMREMGenerator.js +++ b/src/extras/PMREMGenerator.js @@ -8,6 +8,7 @@ import { RGBDEncoding, RGBEEncoding, RGBEFormat, + RGBAFormat, RGBM16Encoding, RGBM7Encoding, UnsignedByteType, @@ -345,6 +346,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; @@ -380,8 +395,8 @@ class PMREMGenerator { } - uniforms[ 'inputEncoding' ].value = ENCODINGS[ texture.encoding ]; - uniforms[ 'outputEncoding' ].value = ENCODINGS[ cubeUVRenderTarget.texture.encoding ]; + this._setEncoding( uniforms[ 'inputEncoding' ], texture ); + this._setEncoding( uniforms[ 'outputEncoding' ], cubeUVRenderTarget.texture ); _setViewport( cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX ); @@ -512,8 +527,9 @@ class PMREMGenerator { blurUniforms[ 'dTheta' ].value = radiansPerPixel; blurUniforms[ 'mipInt' ].value = LOD_MAX - lodIn; - blurUniforms[ 'inputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ]; - blurUniforms[ 'outputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ]; + + this._setEncoding( blurUniforms[ 'inputEncoding' ], targetIn.texture ); + this._setEncoding( blurUniforms[ 'outputEncoding' ], targetIn.texture ); const outputSize = _sizeLods[ lodOut ]; const x = 3 * Math.max( 0, SIZE_MAX - 2 * outputSize ); diff --git a/src/loaders/TextureLoader.js b/src/loaders/TextureLoader.js index c66af88bfac643..4adc1ec8fa4aed 100644 --- a/src/loaders/TextureLoader.js +++ b/src/loaders/TextureLoader.js @@ -1,4 +1,3 @@ -import { RGBAFormat, RGBFormat } from '../constants.js'; import { ImageLoader } from './ImageLoader.js'; import { Texture } from '../textures/Texture.js'; import { Loader } from './Loader.js'; @@ -22,11 +21,6 @@ class TextureLoader extends Loader { loader.load( url, function ( image ) { texture.image = image; - - // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB. - const isJPEG = url.search( /\.jpe?g($|\?)/i ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0; - - texture.format = isJPEG ? RGBFormat : RGBAFormat; texture.needsUpdate = true; if ( onLoad !== undefined ) { diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js index 132b452f7bcc11..aa6b797006a5eb 100644 --- a/src/renderers/webgl/WebGLPrograms.js +++ b/src/renderers/webgl/WebGLPrograms.js @@ -1,4 +1,4 @@ -import { BackSide, DoubleSide, CubeUVRefractionMapping, CubeUVReflectionMapping, LinearEncoding, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping } from '../../constants.js'; +import { BackSide, DoubleSide, CubeUVRefractionMapping, CubeUVReflectionMapping, LinearEncoding, sRGBEncoding, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping, RGBAFormat, UnsignedByteType } from '../../constants.js'; import { WebGLProgram } from './WebGLProgram.js'; import { ShaderLib } from '../shaders/ShaderLib.js'; import { UniformsUtils } from '../shaders/UniformsUtils.js'; @@ -106,6 +106,12 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities } + if ( isWebGL2 && map && map.isTexture && map.format === RGBAFormat && map.type === UnsignedByteType && map.encoding === sRGBEncoding ) { + + encoding = LinearEncoding; // disable inline decode for sRGB textures in WebGL 2 + + } + return encoding; } diff --git a/src/renderers/webgl/WebGLTextures.js b/src/renderers/webgl/WebGLTextures.js index 887c4bada18a4a..65214c15298d3f 100644 --- a/src/renderers/webgl/WebGLTextures.js +++ b/src/renderers/webgl/WebGLTextures.js @@ -1,4 +1,4 @@ -import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBFormat, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping } from '../../constants.js'; +import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBFormat, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, sRGBEncoding } from '../../constants.js'; import * as MathUtils from '../../math/MathUtils.js'; import { createElementNS } from '../../utils.js'; @@ -132,7 +132,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } - function getInternalFormat( internalFormatName, glFormat, glType ) { + function getInternalFormat( internalFormatName, glFormat, glType, encoding ) { if ( isWebGL2 === false ) return glFormat; @@ -166,7 +166,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 = _gl.RGBA8; + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( encoding === sRGBEncoding ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8; } @@ -532,7 +532,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, glFormat = utils.convert( texture.format ); let glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); setTextureParameters( textureType, texture, supportsMips ); @@ -758,7 +758,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, supportsMips = isPowerOfTwo( image ) || isWebGL2, glFormat = utils.convert( texture.format ), glType = utils.convert( texture.type ), - glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType ); + glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips ); @@ -857,7 +857,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glFormat = utils.convert( texture.format ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) { @@ -938,7 +938,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glFormat = utils.convert( texture.format ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); if ( isMultisample ) { @@ -1131,7 +1131,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, const glFormat = utils.convert( texture.format ); const glType = utils.convert( texture.type ); - const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType ); + const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.encoding ); const samples = getRenderTargetSamples( renderTarget ); _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height ); diff --git a/src/textures/CubeTexture.js b/src/textures/CubeTexture.js index 8cb64a1692fdbb..84db191d0bdbdb 100644 --- a/src/textures/CubeTexture.js +++ b/src/textures/CubeTexture.js @@ -1,5 +1,5 @@ import { Texture } from './Texture.js'; -import { CubeReflectionMapping, RGBFormat } from '../constants.js'; +import { CubeReflectionMapping } from '../constants.js'; class CubeTexture extends Texture { @@ -7,7 +7,6 @@ class CubeTexture extends Texture { images = images !== undefined ? images : []; mapping = mapping !== undefined ? mapping : CubeReflectionMapping; - format = format !== undefined ? format : RGBFormat; super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); diff --git a/utils/build/rollup.config.js b/utils/build/rollup.config.js index 1a4362ef345dbb..50097ed82da026 100644 --- a/utils/build/rollup.config.js +++ b/utils/build/rollup.config.js @@ -158,7 +158,8 @@ export function glconstants() { MAX_SAMPLES: 36183, READ_FRAMEBUFFER: 36008, DRAW_FRAMEBUFFER: 36009, - SAMPLE_ALPHA_TO_COVERAGE: 32926 + SAMPLE_ALPHA_TO_COVERAGE: 32926, + SRGB8_ALPHA8: 35907 }; return {