Browse Source

Optimize number of shadow uniforms for spot and directional lights

Olli Etuaho 5 years ago
parent
commit
b5ca27676d

+ 4 - 0
src/renderers/WebGLRenderer.js

@@ -1610,7 +1610,9 @@ function WebGLRenderer( parameters ) {
 			uniforms.ambientLightColor.value = lights.state.ambient;
 			uniforms.ambientLightColor.value = lights.state.ambient;
 			uniforms.lightProbe.value = lights.state.probe;
 			uniforms.lightProbe.value = lights.state.probe;
 			uniforms.directionalLights.value = lights.state.directional;
 			uniforms.directionalLights.value = lights.state.directional;
+			uniforms.directionalLightShadows.value = lights.state.directionalShadow;
 			uniforms.spotLights.value = lights.state.spot;
 			uniforms.spotLights.value = lights.state.spot;
+			uniforms.spotLightShadows.value = lights.state.spotShadow;
 			uniforms.rectAreaLights.value = lights.state.rectArea;
 			uniforms.rectAreaLights.value = lights.state.rectArea;
 			uniforms.pointLights.value = lights.state.point;
 			uniforms.pointLights.value = lights.state.point;
 			uniforms.pointLightShadows.value = lights.state.pointShadow;
 			uniforms.pointLightShadows.value = lights.state.pointShadow;
@@ -2594,9 +2596,11 @@ function WebGLRenderer( parameters ) {
 		uniforms.lightProbe.needsUpdate = value;
 		uniforms.lightProbe.needsUpdate = value;
 
 
 		uniforms.directionalLights.needsUpdate = value;
 		uniforms.directionalLights.needsUpdate = value;
+		uniforms.directionalLightShadows.needsUpdate = value;
 		uniforms.pointLights.needsUpdate = value;
 		uniforms.pointLights.needsUpdate = value;
 		uniforms.pointLightShadows.needsUpdate = value;
 		uniforms.pointLightShadows.needsUpdate = value;
 		uniforms.spotLights.needsUpdate = value;
 		uniforms.spotLights.needsUpdate = value;
+		uniforms.spotLightShadows.needsUpdate = value;
 		uniforms.rectAreaLights.needsUpdate = value;
 		uniforms.rectAreaLights.needsUpdate = value;
 		uniforms.hemisphereLights.needsUpdate = value;
 		uniforms.hemisphereLights.needsUpdate = value;
 
 

+ 10 - 2
src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js

@@ -56,6 +56,9 @@ IncidentLight directLight;
 #if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )
 #if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )
 
 
 	SpotLight spotLight;
 	SpotLight spotLight;
+	#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0
+	SpotLightShadow spotLightShadow;
+	#endif
 
 
 	#pragma unroll_loop
 	#pragma unroll_loop
 	for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {
 	for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {
@@ -65,7 +68,8 @@ IncidentLight directLight;
 		getSpotDirectLightIrradiance( spotLight, geometry, directLight );
 		getSpotDirectLightIrradiance( spotLight, geometry, directLight );
 
 
 		#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )
 		#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )
-		directLight.color *= all( bvec3( spotLight.shadow, directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;
+		spotLightShadow = spotLightShadows[ i ];
+		directLight.color *= all( bvec3( spotLightShadow.shadow, directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;
 		#endif
 		#endif
 
 
 		RE_Direct( directLight, geometry, material, reflectedLight );
 		RE_Direct( directLight, geometry, material, reflectedLight );
@@ -77,6 +81,9 @@ IncidentLight directLight;
 #if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )
 #if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )
 
 
 	DirectionalLight directionalLight;
 	DirectionalLight directionalLight;
+	#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0
+	DirectionalLightShadow directionalLightShadow;
+	#endif
 
 
 	#pragma unroll_loop
 	#pragma unroll_loop
 	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
 	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
@@ -86,7 +93,8 @@ IncidentLight directLight;
 		getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );
 		getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );
 
 
 		#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
 		#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )
-		directLight.color *= all( bvec3( directionalLight.shadow, directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
+		directionalLightShadow = directionalLightShadows[ i ];
+		directLight.color *= all( bvec3( directionalLightShadow.shadow, directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
 		#endif
 		#endif
 
 
 		RE_Direct( directLight, geometry, material, reflectedLight );
 		RE_Direct( directLight, geometry, material, reflectedLight );

+ 27 - 10
src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js

@@ -59,15 +59,24 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 	struct DirectionalLight {
 	struct DirectionalLight {
 		vec3 direction;
 		vec3 direction;
 		vec3 color;
 		vec3 color;
-
-		int shadow;
-		float shadowBias;
-		float shadowRadius;
-		vec2 shadowMapSize;
 	};
 	};
 
 
 	uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
 	uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
 
 
+	#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0
+
+		struct DirectionalLightShadow {
+			int shadow;
+			float shadowBias;
+			float shadowRadius;
+			vec2 shadowMapSize;
+		};
+
+		uniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];
+
+	#endif
+
+
 	void getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {
 	void getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {
 
 
 		directLight.color = directionalLight.color;
 		directLight.color = directionalLight.color;
@@ -132,15 +141,23 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 		float decay;
 		float decay;
 		float coneCos;
 		float coneCos;
 		float penumbraCos;
 		float penumbraCos;
-
-		int shadow;
-		float shadowBias;
-		float shadowRadius;
-		vec2 shadowMapSize;
 	};
 	};
 
 
 	uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];
 	uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];
 
 
+	#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0
+
+		struct SpotLightShadow {
+			int shadow;
+			float shadowBias;
+			float shadowRadius;
+			vec2 shadowMapSize;
+		};
+
+		uniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];
+
+	#endif
+
 	// directLight is an out parameter as having it as a return value caused compiler errors on some devices
 	// directLight is an out parameter as having it as a return value caused compiler errors on some devices
 	void getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  ) {
 	void getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  ) {
 
 

+ 4 - 4
src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js

@@ -7,12 +7,12 @@ float getShadowMask() {
 
 
 	#if NUM_DIR_LIGHT_SHADOWS > 0
 	#if NUM_DIR_LIGHT_SHADOWS > 0
 
 
-	DirectionalLight directionalLight;
+	DirectionalLightShadow directionalLight;
 
 
 	#pragma unroll_loop
 	#pragma unroll_loop
 	for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {
 	for ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {
 
 
-		directionalLight = directionalLights[ i ];
+		directionalLight = directionalLightShadows[ i ];
 		shadow *= all( bvec2( directionalLight.shadow, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
 		shadow *= all( bvec2( directionalLight.shadow, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;
 
 
 	}
 	}
@@ -21,12 +21,12 @@ float getShadowMask() {
 
 
 	#if NUM_SPOT_LIGHT_SHADOWS > 0
 	#if NUM_SPOT_LIGHT_SHADOWS > 0
 
 
-	SpotLight spotLight;
+	SpotLightShadow spotLight;
 
 
 	#pragma unroll_loop
 	#pragma unroll_loop
 	for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {
 	for ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {
 
 
-		spotLight = spotLights[ i ];
+		spotLight = spotLightShadows[ i ];
 		shadow *= all( bvec2( spotLight.shadow, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;
 		shadow *= all( bvec2( spotLight.shadow, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;
 
 
 	}
 	}

+ 10 - 0
src/renderers/shaders/UniformsLib.d.ts

@@ -67,6 +67,11 @@ export let UniformsLib: {
 			properties: {
 			properties: {
 				direction: {};
 				direction: {};
 				color: {};
 				color: {};
+			};
+		};
+		directionalLightShadows: {
+			value: any[];
+			properties: {
 				shadow: {};
 				shadow: {};
 				shadowBias: {};
 				shadowBias: {};
 				shadowRadius: {};
 				shadowRadius: {};
@@ -85,6 +90,11 @@ export let UniformsLib: {
 				coneCos: {};
 				coneCos: {};
 				penumbraCos: {};
 				penumbraCos: {};
 				decay: {};
 				decay: {};
+			};
+		};
+		spotLightShadows: {
+			value: any[];
+			properties: {
 				shadow: {};
 				shadow: {};
 				shadowBias: {};
 				shadowBias: {};
 				shadowRadius: {};
 				shadowRadius: {};

+ 6 - 2
src/renderers/shaders/UniformsLib.js

@@ -114,8 +114,10 @@ var UniformsLib = {
 
 
 		directionalLights: { value: [], properties: {
 		directionalLights: { value: [], properties: {
 			direction: {},
 			direction: {},
-			color: {},
+			color: {}
+		} },
 
 
+		directionalLightShadows: { value: [], properties: {
 			shadow: {},
 			shadow: {},
 			shadowBias: {},
 			shadowBias: {},
 			shadowRadius: {},
 			shadowRadius: {},
@@ -132,8 +134,10 @@ var UniformsLib = {
 			distance: {},
 			distance: {},
 			coneCos: {},
 			coneCos: {},
 			penumbraCos: {},
 			penumbraCos: {},
-			decay: {},
+			decay: {}
+		} },
 
 
+		spotLightShadows: { value: [], properties: {
 			shadow: {},
 			shadow: {},
 			shadowBias: {},
 			shadowBias: {},
 			shadowRadius: {},
 			shadowRadius: {},

+ 2 - 0
src/renderers/webgl/WebGLLights.d.ts

@@ -20,9 +20,11 @@ export class WebGLLights {
 		ambient: Array<number>;
 		ambient: Array<number>;
 		probe: Array<any>;
 		probe: Array<any>;
 		directional: Array<any>;
 		directional: Array<any>;
+		directionalShadow: Array<any>;
 		directionalShadowMap: Array<any>;
 		directionalShadowMap: Array<any>;
 		directionalShadowMatrix: Array<any>;
 		directionalShadowMatrix: Array<any>;
 		spot: Array<any>;
 		spot: Array<any>;
+		spotShadow: Array<any>;
 		spotShadowMap: Array<any>;
 		spotShadowMap: Array<any>;
 		spotShadowMatrix: Array<any>;
 		spotShadowMatrix: Array<any>;
 		rectArea: Array<any>;
 		rectArea: Array<any>;

+ 20 - 21
src/renderers/webgl/WebGLLights.js

@@ -29,11 +29,6 @@ function UniformsCache() {
 					uniforms = {
 					uniforms = {
 						direction: new Vector3(),
 						direction: new Vector3(),
 						color: new Color(),
 						color: new Color(),
-
-						shadow: false,
-						shadowBias: 0,
-						shadowRadius: 1,
-						shadowMapSize: new Vector2()
 					};
 					};
 					break;
 					break;
 
 
@@ -46,11 +41,6 @@ function UniformsCache() {
 						coneCos: 0,
 						coneCos: 0,
 						penumbraCos: 0,
 						penumbraCos: 0,
 						decay: 0,
 						decay: 0,
-
-						shadow: false,
-						shadowBias: 0,
-						shadowRadius: 1,
-						shadowMapSize: new Vector2()
 					};
 					};
 					break;
 					break;
 
 
@@ -77,7 +67,6 @@ function UniformsCache() {
 						position: new Vector3(),
 						position: new Vector3(),
 						halfWidth: new Vector3(),
 						halfWidth: new Vector3(),
 						halfHeight: new Vector3()
 						halfHeight: new Vector3()
-						// TODO (abelnation): set RectAreaLight shadow uniforms
 					};
 					};
 					break;
 					break;
 
 
@@ -140,6 +129,8 @@ function ShadowUniformsCache() {
 					};
 					};
 					break;
 					break;
 
 
+				// TODO (abelnation): set RectAreaLight shadow uniforms
+
 			}
 			}
 
 
 			lights[ light.id ] = uniforms;
 			lights[ light.id ] = uniforms;
@@ -187,9 +178,11 @@ function WebGLLights() {
 		ambient: [ 0, 0, 0 ],
 		ambient: [ 0, 0, 0 ],
 		probe: [],
 		probe: [],
 		directional: [],
 		directional: [],
+		directionalShadow: [],
 		directionalShadowMap: [],
 		directionalShadowMap: [],
 		directionalShadowMatrix: [],
 		directionalShadowMatrix: [],
 		spot: [],
 		spot: [],
+		spotShadow: [],
 		spotShadowMap: [],
 		spotShadowMap: [],
 		spotShadowMatrix: [],
 		spotShadowMatrix: [],
 		rectArea: [],
 		rectArea: [],
@@ -261,16 +254,18 @@ function WebGLLights() {
 				uniforms.direction.sub( vector3 );
 				uniforms.direction.sub( vector3 );
 				uniforms.direction.transformDirection( viewMatrix );
 				uniforms.direction.transformDirection( viewMatrix );
 
 
-				uniforms.shadow = light.castShadow;
-
 				if ( light.castShadow ) {
 				if ( light.castShadow ) {
 
 
 					var shadow = light.shadow;
 					var shadow = light.shadow;
 
 
-					uniforms.shadowBias = shadow.bias;
-					uniforms.shadowRadius = shadow.radius;
-					uniforms.shadowMapSize = shadow.mapSize;
+					var shadowUniforms = shadowCache.get( light );
 
 
+					shadowUniforms.shadow = light.castShadow;
+					shadowUniforms.shadowBias = shadow.bias;
+					shadowUniforms.shadowRadius = shadow.radius;
+					shadowUniforms.shadowMapSize = shadow.mapSize;
+
+					state.directionalShadow[ directionalLength ] = shadowUniforms;
 					state.directionalShadowMap[ directionalLength ] = shadowMap;
 					state.directionalShadowMap[ directionalLength ] = shadowMap;
 					state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
 					state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
 
 
@@ -301,16 +296,18 @@ function WebGLLights() {
 				uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
 				uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
 				uniforms.decay = light.decay;
 				uniforms.decay = light.decay;
 
 
-				uniforms.shadow = light.castShadow;
-
 				if ( light.castShadow ) {
 				if ( light.castShadow ) {
 
 
 					var shadow = light.shadow;
 					var shadow = light.shadow;
 
 
-					uniforms.shadowBias = shadow.bias;
-					uniforms.shadowRadius = shadow.radius;
-					uniforms.shadowMapSize = shadow.mapSize;
+					var shadowUniforms = shadowCache.get( light );
+
+					shadowUniforms.shadow = light.castShadow;
+					shadowUniforms.shadowBias = shadow.bias;
+					shadowUniforms.shadowRadius = shadow.radius;
+					shadowUniforms.shadowMapSize = shadow.mapSize;
 
 
+					state.spotShadow[ spotLength ] = shadowUniforms;
 					state.spotShadowMap[ spotLength ] = shadowMap;
 					state.spotShadowMap[ spotLength ] = shadowMap;
 					state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
 					state.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
 
 
@@ -430,9 +427,11 @@ function WebGLLights() {
 			state.point.length = pointLength;
 			state.point.length = pointLength;
 			state.hemi.length = hemiLength;
 			state.hemi.length = hemiLength;
 
 
+			state.directionalShadow.length = numDirectionalShadows;
 			state.directionalShadowMap.length = numDirectionalShadows;
 			state.directionalShadowMap.length = numDirectionalShadows;
 			state.pointShadow.length = numPointShadows;
 			state.pointShadow.length = numPointShadows;
 			state.pointShadowMap.length = numPointShadows;
 			state.pointShadowMap.length = numPointShadows;
+			state.spotShadow.length = numSpotShadows;
 			state.spotShadowMap.length = numSpotShadows;
 			state.spotShadowMap.length = numSpotShadows;
 			state.directionalShadowMatrix.length = numDirectionalShadows;
 			state.directionalShadowMatrix.length = numDirectionalShadows;
 			state.pointShadowMatrix.length = numPointShadows;
 			state.pointShadowMatrix.length = numPointShadows;