瀏覽代碼

Fix: CSM lights when shadow maps are disabled (#27358)

* Fix indentation

* Allow shadows to be disabled from GUI

* Fix: when shadows are disabled, light contribution still needs to be considered
Ondřej Španěl 1 年之前
父節點
當前提交
28f99d7da3
共有 2 個文件被更改,包括 70 次插入48 次删除
  1. 52 47
      examples/jsm/csm/CSMShader.js
  2. 18 1
      examples/webgl_shadowmap_csm.html

+ 52 - 47
examples/jsm/csm/CSMShader.js

@@ -62,7 +62,7 @@ IncidentLight directLight;
  	vec4 spotColor;
 	vec3 spotLightCoord;
 	bool inSpotLightMap;
- 
+
 	#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0
 	SpotLightShadow spotLightShadow;
 	#endif
@@ -112,57 +112,57 @@ IncidentLight directLight;
 	#endif
 
 	#if defined( USE_SHADOWMAP ) && defined( CSM_FADE )
-	vec2 cascade;
-	float cascadeCenter;
-	float closestEdge;
-	float margin;
-	float csmx;
-	float csmy;
+		vec2 cascade;
+		float cascadeCenter;
+		float closestEdge;
+		float margin;
+		float csmx;
+		float csmy;
 
-	#pragma unroll_loop_start
-	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
+		#pragma unroll_loop_start
+		for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
 
-		directionalLight = directionalLights[ i ];
-		getDirectionalLightInfo( directionalLight, directLight );
+			directionalLight = directionalLights[ i ];
+			getDirectionalLightInfo( directionalLight, directLight );
 
-	  	#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
-			// NOTE: Depth gets larger away from the camera.
-			// cascade.x is closer, cascade.y is further
-			cascade = CSM_cascades[ i ];
-			cascadeCenter = ( cascade.x + cascade.y ) / 2.0;
-			closestEdge = linearDepth < cascadeCenter ? cascade.x : cascade.y;
-			margin = 0.25 * pow( closestEdge, 2.0 );
-			csmx = cascade.x - margin / 2.0;
-			csmy = cascade.y + margin / 2.0;
-			if( linearDepth >= csmx && ( linearDepth < csmy || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 ) ) {
-
-				float dist = min( linearDepth - csmx, csmy - linearDepth );
-				float ratio = clamp( dist / margin, 0.0, 1.0 );
-
-				vec3 prevColor = directLight.color;
-				directionalLightShadow = directionalLightShadows[ i ];
-				directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
+			#if ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
+				// NOTE: Depth gets larger away from the camera.
+				// cascade.x is closer, cascade.y is further
+				cascade = CSM_cascades[ i ];
+				cascadeCenter = ( cascade.x + cascade.y ) / 2.0;
+				closestEdge = linearDepth < cascadeCenter ? cascade.x : cascade.y;
+				margin = 0.25 * pow( closestEdge, 2.0 );
+				csmx = cascade.x - margin / 2.0;
+				csmy = cascade.y + margin / 2.0;
+				if( linearDepth >= csmx && ( linearDepth < csmy || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 ) ) {
 
-				bool shouldFadeLastCascade = UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 && linearDepth > cascadeCenter;
-				directLight.color = mix( prevColor, directLight.color, shouldFadeLastCascade ? ratio : 1.0 );
+					float dist = min( linearDepth - csmx, csmy - linearDepth );
+					float ratio = clamp( dist / margin, 0.0, 1.0 );
 
-				ReflectedLight prevLight = reflectedLight;
-				RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );
+					vec3 prevColor = directLight.color;
+					directionalLightShadow = directionalLightShadows[ i ];
+					directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
 
-				bool shouldBlend = UNROLLED_LOOP_INDEX != CSM_CASCADES - 1 || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 && linearDepth < cascadeCenter;
-				float blendRatio = shouldBlend ? ratio : 1.0;
+					bool shouldFadeLastCascade = UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 && linearDepth > cascadeCenter;
+					directLight.color = mix( prevColor, directLight.color, shouldFadeLastCascade ? ratio : 1.0 );
 
-				reflectedLight.directDiffuse = mix( prevLight.directDiffuse, reflectedLight.directDiffuse, blendRatio );
-				reflectedLight.directSpecular = mix( prevLight.directSpecular, reflectedLight.directSpecular, blendRatio );
-				reflectedLight.indirectDiffuse = mix( prevLight.indirectDiffuse, reflectedLight.indirectDiffuse, blendRatio );
-				reflectedLight.indirectSpecular = mix( prevLight.indirectSpecular, reflectedLight.indirectSpecular, blendRatio );
+					ReflectedLight prevLight = reflectedLight;
+					RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );
 
-			}
-	  	#endif
+					bool shouldBlend = UNROLLED_LOOP_INDEX != CSM_CASCADES - 1 || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1 && linearDepth < cascadeCenter;
+					float blendRatio = shouldBlend ? ratio : 1.0;
 
-	}
-	#pragma unroll_loop_end
-	#else
+					reflectedLight.directDiffuse = mix( prevLight.directDiffuse, reflectedLight.directDiffuse, blendRatio );
+					reflectedLight.directSpecular = mix( prevLight.directSpecular, reflectedLight.directSpecular, blendRatio );
+					reflectedLight.indirectDiffuse = mix( prevLight.indirectDiffuse, reflectedLight.indirectDiffuse, blendRatio );
+					reflectedLight.indirectSpecular = mix( prevLight.indirectSpecular, reflectedLight.indirectSpecular, blendRatio );
+
+				}
+			#endif
+
+		}
+		#pragma unroll_loop_end
+	#elif defined (USE_SHADOWMAP)
 
 		#pragma unroll_loop_start
 		for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
@@ -170,18 +170,23 @@ IncidentLight directLight;
 			directionalLight = directionalLights[ i ];
 			getDirectionalLightInfo( directionalLight, directLight );
 
-			#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
+			#if ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
 
-			directionalLightShadow = directionalLightShadows[ i ];
-			if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y) directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
+				directionalLightShadow = directionalLightShadows[ i ];
+				if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y) directLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
 
-			if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && (linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1)) RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );
+				if(linearDepth >= CSM_cascades[UNROLLED_LOOP_INDEX].x && (linearDepth < CSM_cascades[UNROLLED_LOOP_INDEX].y || UNROLLED_LOOP_INDEX == CSM_CASCADES - 1)) RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );
 
 			#endif
 
 		}
 		#pragma unroll_loop_end
 
+	#elif ( NUM_DIR_LIGHT_SHADOWS > 0 )
+		// note: no loop here - all CSM lights are in fact one light only
+		getDirectionalLightInfo( directionalLights[0], directLight );
+		RE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );
+
 	#endif
 
 	#if ( NUM_DIR_LIGHTS > NUM_DIR_LIGHT_SHADOWS)

+ 18 - 1
examples/webgl_shadowmap_csm.html

@@ -37,6 +37,7 @@
 			const params = {
 				orthographic: false,
 				fade: false,
+				shadows: true,
 				far: 1000,
 				mode: 'practical',
 				lightX: - 1,
@@ -82,7 +83,7 @@
 				renderer = new THREE.WebGLRenderer( { antialias: true } );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				document.body.appendChild( renderer.domElement );
-				renderer.shadowMap.enabled = true;
+				renderer.shadowMap.enabled = params.shadows;
 				renderer.shadowMap.type = THREE.PCFSoftShadowMap;
 
 				controls = new OrbitControls( camera, renderer.domElement );
@@ -163,6 +164,22 @@
 
 				} );
 
+				gui.add( params, 'shadows' ).onChange( function ( value ) {
+
+					renderer.shadowMap.enabled = value;
+
+					scene.traverse( function ( child ) {
+
+						if ( child.material ) {
+
+							child.material.needsUpdate = true;
+
+						}
+
+					} );
+
+				} );
+
 				gui.add( params, 'far', 1, 5000 ).step( 1 ).name( 'shadow far' ).onChange( function ( value ) {
 
 					csm.maxFar = value;