1
0
Эх сурвалжийг харах

WebGLRenderer: Add `ReversedCoordinateSystem`, fix shadows with `reverseDepthBuffer`. (#31370)

Cody Bennett 7 сар өмнө
parent
commit
36c2b6665b

+ 15 - 2
examples/jsm/shaders/UnpackDepthRGBAShader.js

@@ -43,8 +43,21 @@ const UnpackDepthRGBAShader = {
 
 		void main() {
 
-			float depth = 1.0 - unpackRGBAToDepth( texture2D( tDiffuse, vUv ) );
-			gl_FragColor = vec4( vec3( depth ), opacity );
+			float depth = unpackRGBAToDepth( texture2D( tDiffuse, vUv ) );
+
+			#ifdef USE_REVERSEDEPTHBUF
+
+				if ( depth == 1.0 ) depth = 0.0; // wrong clear value?
+
+				// [0, 1] -> [-1, 1]
+				depth = depth * 2.0 - 1.0;
+
+				// Reverse to forward depth (precision is already destroyed at this point)
+				depth = 1.0 - depth;
+
+			#endif
+
+			gl_FragColor = vec4( vec3( 1.0 - depth ), opacity );
 
 		}`
 

+ 8 - 2
examples/webgl_reverse_depth_buffer.html

@@ -107,7 +107,7 @@
 			import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
 			import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
 
-			let stats, camera, scene;
+			let stats, camera, reversedCamera, scene;
 			let normalRenderer, logarithmicRenderer, reverseRenderer;
 			let normalComposer, logarithmicComposer, reverseComposer;
 			const meshes = [];
@@ -129,6 +129,9 @@
 				camera = new THREE.PerspectiveCamera( 72, 0.33 * window.innerWidth / window.innerHeight, 5, 9999 );
 				camera.position.z = 12;
 
+				reversedCamera = camera.clone();
+				reversedCamera.coordinateSystem = THREE.ReversedCoordinateSystem;
+
 				scene = new THREE.Scene();
 
 				const xCount = 1;
@@ -236,7 +239,7 @@
 				reverseContainer.appendChild( reverseRenderer.domElement );
 
 				reverseComposer = new EffectComposer( reverseRenderer, renderTarget );
-				reverseComposer.addPass( new RenderPass( scene, camera ) );
+				reverseComposer.addPass( new RenderPass( scene, reversedCamera ) );
 				reverseComposer.addPass( new OutputPass() );
 
 				window.addEventListener( 'resize', onWindowResize );
@@ -289,6 +292,9 @@
 				camera.aspect = 0.33 * window.innerWidth / window.innerHeight;
 				camera.updateProjectionMatrix();
 
+				reversedCamera.aspect = 0.33 * window.innerWidth / window.innerHeight;
+				reversedCamera.updateProjectionMatrix();
+
 			}
 		</script>
 

+ 8 - 1
examples/webgl_shadowmap.html

@@ -102,12 +102,19 @@
 
 				// RENDERER
 
-				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer = new THREE.WebGLRenderer( { antialias: true, reverseDepthBuffer: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.setAnimationLoop( animate );
 				container.appendChild( renderer.domElement );
 
+				if ( renderer.capabilities.reverseDepthBuffer ) {
+
+					camera.coordinateSystem = THREE.ReversedCoordinateSystem;
+					camera.updateProjectionMatrix();
+
+				}
+
 				renderer.autoClear = false;
 
 				//

+ 12 - 2
src/constants.js

@@ -1564,7 +1564,7 @@ export const GLSL1 = '100';
 export const GLSL3 = '300 es';
 
 /**
- * WebGL coordinate system.
+ * WebGL coordinate system [-1, 1].
  *
  * @type {number}
  * @constant
@@ -1572,13 +1572,23 @@ export const GLSL3 = '300 es';
 export const WebGLCoordinateSystem = 2000;
 
 /**
- * WebGPU coordinate system.
+ * WebGPU coordinate system [0, 1].
  *
  * @type {number}
  * @constant
  */
 export const WebGPUCoordinateSystem = 2001;
 
+/**
+ * Reversed coordinate system [1, 0].
+ *
+ * Used for reverse depth buffer.
+ *
+ * @type {number}
+ * @constant
+ */
+export const ReversedCoordinateSystem = 2002;
+
 /**
  * Represents the different timestamp query types.
  *

+ 11 - 1
src/math/Matrix4.js

@@ -1,4 +1,4 @@
-import { WebGLCoordinateSystem, WebGPUCoordinateSystem } from '../constants.js';
+import { WebGLCoordinateSystem, WebGPUCoordinateSystem, ReversedCoordinateSystem } from '../constants.js';
 import { Vector3 } from './Vector3.js';
 
 /**
@@ -1126,6 +1126,11 @@ class Matrix4 {
 			c = - far / ( far - near );
 			d = ( - far * near ) / ( far - near );
 
+		} else if ( coordinateSystem === ReversedCoordinateSystem ) {
+
+			c = far / ( far - near ) - 1;
+			d = ( far * near ) / ( far - near );
+
 		} else {
 
 			throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem );
@@ -1176,6 +1181,11 @@ class Matrix4 {
 			z = near * p;
 			zInv = - 1 * p;
 
+		} else if ( coordinateSystem === ReversedCoordinateSystem ) {
+
+			z = - near * p - 1;
+			zInv = 1 * p;
+
 		} else {
 
 			throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem );

+ 6 - 2
src/renderers/WebGLRenderer.js

@@ -17,7 +17,8 @@ import {
 	UnsignedInt248Type,
 	UnsignedShort4444Type,
 	UnsignedShort5551Type,
-	WebGLCoordinateSystem
+	WebGLCoordinateSystem,
+	ReversedCoordinateSystem
 } from '../constants.js';
 import { Color } from '../math/Color.js';
 import { Frustum } from '../math/Frustum.js';
@@ -2382,7 +2383,10 @@ class WebGLRenderer {
 
 				const reverseDepthBuffer = state.buffers.depth.getReversed();
 
-				if ( reverseDepthBuffer ) {
+				if ( reverseDepthBuffer && camera.coordinateSystem !== ReversedCoordinateSystem ) {
+
+					// @deprecated, r179
+					warnOnce( 'THREE.WebGLRenderer: reverseDepthBuffer must be used with camera.coordinateSystem = THREE.ReversedCoordinateSystem for correct results. Automatic conversion will be removed in r189.' );
 
 					_currentProjectionMatrix.copy( camera.projectionMatrix );
 

+ 21 - 2
src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js

@@ -75,7 +75,18 @@ export default /* glsl */`
 
 	float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {
 
-		return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );
+		float depth = unpackRGBAToDepth( texture2D( depths, uv ) );
+
+		#ifdef USE_REVERSEDEPTHBUF
+
+			if ( depth == 1.0 ) depth = 0.0; // wrong clear value?
+			return step( depth, compare );
+
+		#else
+
+			return step( compare, depth );
+
+		#endif
 
 	}
 
@@ -91,7 +102,15 @@ export default /* glsl */`
 
 		vec2 distribution = texture2DDistribution( shadow, uv );
 
-		float hard_shadow = step( compare , distribution.x ); // Hard Shadow
+		#ifdef USE_REVERSEDEPTHBUF
+
+			float hard_shadow = step( distribution.x, compare ); // Hard Shadow
+
+		#else
+
+			float hard_shadow = step( compare , distribution.x ); // Hard Shadow
+
+		#endif
 
 		if (hard_shadow != 1.0 ) {
 

+ 12 - 1
src/renderers/webgl/WebGLShadowMap.js

@@ -1,4 +1,4 @@
-import { FrontSide, BackSide, DoubleSide, NearestFilter, PCFShadowMap, VSMShadowMap, RGBADepthPacking, NoBlending } from '../../constants.js';
+import { FrontSide, BackSide, DoubleSide, NearestFilter, PCFShadowMap, VSMShadowMap, RGBADepthPacking, NoBlending, ReversedCoordinateSystem } from '../../constants.js';
 import { WebGLRenderTarget } from '../WebGLRenderTarget.js';
 import { MeshDepthMaterial } from '../../materials/MeshDepthMaterial.js';
 import { MeshDistanceMaterial } from '../../materials/MeshDistanceMaterial.js';
@@ -150,6 +150,17 @@ function WebGLShadowMap( renderer, objects, capabilities ) {
 				shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
 				shadow.map.texture.name = light.name + '.shadowMap';
 
+				// @deprecated, r179
+				if ( capabilities.reverseDepthBuffer === true && camera.coordinateSystem !== ReversedCoordinateSystem ) {
+
+					shadow.camera.coordinateSystem = ReversedCoordinateSystem;
+
+				} else {
+
+					shadow.camera.coordinateSystem = camera.coordinateSystem;
+
+				}
+
 				shadow.camera.updateProjectionMatrix();
 
 			}

粤ICP备19079148号