Răsfoiți Sursa

HalfFloat PMREM (#22998)

* changed format

* PMREM RGBE->HalfFloat

* fixed toneMapping problem

* update screenshots

* Update WebGLRenderer.js

* Update WebGLRenderer.js

Co-authored-by: Michael Herzog <[email protected]>
Emmett Lalish 3 ani în urmă
părinte
comite
2768965fb5

BIN
examples/screenshots/webgl_materials_envmaps_hdr_nodes.jpg


BIN
examples/screenshots/webgl_materials_envmaps_pmrem_nodes.jpg


+ 12 - 72
src/extras/PMREMGenerator.js

@@ -4,17 +4,17 @@ import {
 	CubeUVReflectionMapping,
 	GammaEncoding,
 	LinearEncoding,
+	LinearFilter,
 	NoToneMapping,
-	NearestFilter,
 	NoBlending,
 	RGBDEncoding,
 	RGBEEncoding,
 	RGBAFormat,
-	RGBEFormat,
 	RGBM16Encoding,
 	RGBM7Encoding,
 	UnsignedByteType,
-	sRGBEncoding
+	sRGBEncoding,
+	HalfFloatType
 } from '../constants.js';
 
 import { BufferAttribute } from '../core/BufferAttribute.js';
@@ -234,12 +234,12 @@ class PMREMGenerator {
 	_allocateTargets( texture ) { // warning: null texture is valid
 
 		const params = {
-			magFilter: NearestFilter,
-			minFilter: NearestFilter,
+			magFilter: LinearFilter,
+			minFilter: LinearFilter,
 			generateMipmaps: false,
-			type: UnsignedByteType,
-			format: RGBEFormat,
-			encoding: _isLDR( texture ) ? texture.encoding : RGBEEncoding,
+			type: HalfFloatType,
+			format: RGBAFormat,
+			encoding: LinearEncoding,
 			depthBuffer: false
 		};
 
@@ -267,12 +267,10 @@ class PMREMGenerator {
 		const renderer = this._renderer;
 
 		const originalAutoClear = renderer.autoClear;
-		const outputEncoding = renderer.outputEncoding;
 		const toneMapping = renderer.toneMapping;
 		renderer.getClearColor( _clearColor );
 
 		renderer.toneMapping = NoToneMapping;
-		renderer.outputEncoding = LinearEncoding;
 		renderer.autoClear = false;
 
 		const backgroundMaterial = new MeshBasicMaterial( {
@@ -342,7 +340,6 @@ class PMREMGenerator {
 		backgroundBox.material.dispose();
 
 		renderer.toneMapping = toneMapping;
-		renderer.outputEncoding = outputEncoding;
 		renderer.autoClear = originalAutoClear;
 		scene.background = background;
 
@@ -400,7 +397,6 @@ class PMREMGenerator {
 		}
 
 		this._setEncoding( uniforms[ 'inputEncoding' ], texture );
-		this._setEncoding( uniforms[ 'outputEncoding' ], cubeUVRenderTarget.texture );
 
 		_setViewport( cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
 
@@ -532,9 +528,6 @@ class PMREMGenerator {
 		blurUniforms[ 'dTheta' ].value = radiansPerPixel;
 		blurUniforms[ 'mipInt' ].value = LOD_MAX - lodIn;
 
-		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 );
 		const y = ( lodOut === 0 ? 0 : 2 * SIZE_MAX ) + 2 * outputSize * ( lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0 );
@@ -547,14 +540,6 @@ class PMREMGenerator {
 
 }
 
-function _isLDR( texture ) {
-
-	if ( texture === undefined || texture.type !== UnsignedByteType ) return false;
-
-	return texture.encoding === LinearEncoding || texture.encoding === sRGBEncoding || texture.encoding === GammaEncoding;
-
-}
-
 function _createPlanes() {
 
 	const _lodPlanes = [];
@@ -667,9 +652,7 @@ function _getBlurShader( maxSamples ) {
 			'latitudinal': { value: false },
 			'dTheta': { value: 0 },
 			'mipInt': { value: 0 },
-			'poleAxis': { value: poleAxis },
-			'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
-			'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
+			'poleAxis': { value: poleAxis }
 		},
 
 		vertexShader: _getCommonVertexShader(),
@@ -735,8 +718,6 @@ function _getBlurShader( maxSamples ) {
 
 				}
 
-				gl_FragColor = linearToOutputTexel( gl_FragColor );
-
 			}
 		`,
 
@@ -760,8 +741,7 @@ function _getEquirectShader() {
 		uniforms: {
 			'envMap': { value: null },
 			'texelSize': { value: texelSize },
-			'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
-			'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
+			'inputEncoding': { value: ENCODINGS[ LinearEncoding ] }
 		},
 
 		vertexShader: _getCommonVertexShader(),
@@ -801,8 +781,6 @@ function _getEquirectShader() {
 				vec3 bm = mix( bl, br, f.x );
 				gl_FragColor.rgb = mix( tm, bm, f.y );
 
-				gl_FragColor = linearToOutputTexel( gl_FragColor );
-
 			}
 		`,
 
@@ -824,8 +802,7 @@ function _getCubemapShader() {
 
 		uniforms: {
 			'envMap': { value: null },
-			'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
-			'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
+			'inputEncoding': { value: ENCODINGS[ LinearEncoding ] }
 		},
 
 		vertexShader: _getCommonVertexShader(),
@@ -843,9 +820,7 @@ function _getCubemapShader() {
 
 			void main() {
 
-				gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
-				gl_FragColor.rgb = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) ).rgb;
-				gl_FragColor = linearToOutputTexel( gl_FragColor );
+				gl_FragColor = envMapTexelToLinear( textureCube( envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ) ) );
 
 			}
 		`,
@@ -928,7 +903,6 @@ function _getEncodings() {
 	return /* glsl */`
 
 		uniform int inputEncoding;
-		uniform int outputEncoding;
 
 		#include <encodings_pars_fragment>
 
@@ -966,40 +940,6 @@ function _getEncodings() {
 
 		}
 
-		vec4 linearToOutputTexel( vec4 value ) {
-
-			if ( outputEncoding == 0 ) {
-
-				return value;
-
-			} else if ( outputEncoding == 1 ) {
-
-				return LinearTosRGB( value );
-
-			} else if ( outputEncoding == 2 ) {
-
-				return LinearToRGBE( value );
-
-			} else if ( outputEncoding == 3 ) {
-
-				return LinearToRGBM( value, 7.0 );
-
-			} else if ( outputEncoding == 4 ) {
-
-				return LinearToRGBM( value, 16.0 );
-
-			} else if ( outputEncoding == 5 ) {
-
-				return LinearToRGBD( value, 256.0 );
-
-			} else {
-
-				return LinearToGamma( value, 2.2 );
-
-			}
-
-		}
-
 		vec4 envMapTexelToLinear( vec4 color ) {
 
 			return inputTexelToLinear( color );

+ 6 - 0
src/renderers/WebGLRenderer.js

@@ -1410,6 +1410,7 @@ function WebGLRenderer( parameters = {} ) {
 		materialProperties.numIntersection = parameters.numClipIntersection;
 		materialProperties.vertexAlphas = parameters.vertexAlphas;
 		materialProperties.vertexTangents = parameters.vertexTangents;
+		materialProperties.toneMapping = parameters.toneMapping;
 
 	}
 
@@ -1428,6 +1429,7 @@ function WebGLRenderer( parameters = {} ) {
 		const morphTargets = !! geometry.morphAttributes.position;
 		const morphNormals = !! geometry.morphAttributes.normal;
 		const morphTargetsCount = !! geometry.morphAttributes.position ? geometry.morphAttributes.position.length : 0;
+		const toneMapping = material.toneMapped ? _this.toneMapping : NoToneMapping;
 
 		const materialProperties = properties.get( material );
 		const lights = currentRenderState.state.lights;
@@ -1509,6 +1511,10 @@ function WebGLRenderer( parameters = {} ) {
 
 				needsProgramChange = true;
 
+			} else if ( materialProperties.toneMapping !== toneMapping ) {
+
+				needsProgramChange = true;
+
 			} else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) {
 
 				needsProgramChange = true;

+ 2 - 24
src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js

@@ -89,11 +89,7 @@ export default /* glsl */`
 
 		float texelSize = 1.0 / ( 3.0 * cubeUV_maxTileSize );
 
-		vec2 uv = getUV( direction, face ) * ( faceSize - 1.0 );
-
-		vec2 f = fract( uv );
-
-		uv += 0.5 - f;
+		vec2 uv = getUV( direction, face ) * ( faceSize - 1.0 ) + 0.5;
 
 		if ( face > 2.0 ) {
 
@@ -117,25 +113,7 @@ export default /* glsl */`
 
 		uv *= texelSize;
 
-		vec3 tl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;
-
-		uv.x += texelSize;
-
-		vec3 tr = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;
-
-		uv.y += texelSize;
-
-		vec3 br = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;
-
-		uv.x -= texelSize;
-
-		vec3 bl = envMapTexelToLinear( texture2D( envMap, uv ) ).rgb;
-
-		vec3 tm = mix( tl, tr, f.x );
-
-		vec3 bm = mix( bl, br, f.x );
-
-		return mix( tm, bm, f.y );
+		return texture2D( envMap, uv ).rgb;
 
 	}