Skip to content

Commit

Permalink
WebGLRenderer: Make use of SRGB8_ALPHA8. (#22551)
Browse files Browse the repository at this point in the history
* WebGLRenderer: Make use of SRGB8_ALPHA8.

* Update screenshots.

* Updated builds.

* Revert "Update screenshots."

This reverts commit 9f7c6cb.

* Update screenshots.

* Examples: Let SSRPass and SSRrPass work in linear space.

* Examples: Clean up.

* PMREMGenerator: Avoid inline decode/encode when using SRGB8_ALPHA8.

* Updated builds.

* Update screenshots.

* Revert "Updated builds."

This reverts commit 0fd81f8.

* Revert "Updated builds."

This reverts commit 447e88a.
  • Loading branch information
Mugen87 authored Sep 20, 2021
1 parent c789b20 commit cba9457
Show file tree
Hide file tree
Showing 16 changed files with 46 additions and 55 deletions.
21 changes: 0 additions & 21 deletions examples/jsm/loaders/GLTFLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -2761,31 +2761,13 @@ 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 ) {

// Load binary image data from bufferView, if provided.

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 );
Expand Down Expand Up @@ -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 ] || {};

Expand Down
5 changes: 1 addition & 4 deletions examples/jsm/postprocessing/SSRPass.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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;
Expand Down Expand Up @@ -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 ) {
Expand Down
5 changes: 1 addition & 4 deletions examples/jsm/postprocessing/SSRrPass.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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;
Expand Down Expand Up @@ -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 => {
Expand Down
Binary file modified examples/screenshots/webgl_lightprobe.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified examples/screenshots/webgl_loader_md2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified examples/screenshots/webgl_materials_displacementmap.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified examples/screenshots/webgl_postprocessing_ssr.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified examples/screenshots/webgl_postprocessing_ssrr.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions examples/webgl_postprocessing_ssr.html
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 );

//
Expand All @@ -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

Expand Down
5 changes: 3 additions & 2 deletions examples/webgl_postprocessing_ssrr.html
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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 );

Expand Down Expand Up @@ -177,11 +178,11 @@
camera,
width: innerWidth,
height: innerHeight,
encoding: THREE.sRGBEncoding,
selects: selects
} );

composer.addPass( ssrrPass );
composer.addPass( new ShaderPass( GammaCorrectionShader ) );

// GUI

Expand Down
24 changes: 20 additions & 4 deletions src/extras/PMREMGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
RGBDEncoding,
RGBEEncoding,
RGBEFormat,
RGBAFormat,
RGBM16Encoding,
RGBM7Encoding,
UnsignedByteType,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 );

Expand Down Expand Up @@ -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 );
Expand Down
6 changes: 0 additions & 6 deletions src/loaders/TextureLoader.js
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 ) {
Expand Down
8 changes: 7 additions & 1 deletion src/renderers/webgl/WebGLPrograms.js
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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;

}
Expand Down
16 changes: 8 additions & 8 deletions src/renderers/webgl/WebGLTextures.js
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;

}

Expand Down Expand Up @@ -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 );

Expand Down Expand Up @@ -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 );

Expand Down Expand Up @@ -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 ) {

Expand Down Expand Up @@ -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 ) {

Expand Down Expand Up @@ -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 );

Expand Down
3 changes: 1 addition & 2 deletions src/textures/CubeTexture.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { Texture } from './Texture.js';
import { CubeReflectionMapping, RGBFormat } from '../constants.js';
import { CubeReflectionMapping } from '../constants.js';

class CubeTexture extends Texture {

constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {

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 );

Expand Down
3 changes: 2 additions & 1 deletion utils/build/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit cba9457

Please sign in to comment.