Преглед изворни кода

WebGLRenderer: Better shadows (MeshPhongMaterial and MeshStandardMaterial only). See #6420.

Mr.doob пре 9 година
родитељ
комит
48d8c5a911

+ 28 - 2
src/renderers/WebGLRenderer.js

@@ -2324,6 +2324,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 						var valueProperty = value[ propertyName ];
 
 						switch( property.type ) {
+							case 'i':
+								_gl.uniform1i( locationProperty, valueProperty );
+								break;
 							case 'f':
 								_gl.uniform1f( locationProperty, valueProperty );
 								break;
@@ -2357,6 +2360,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 							var valueProperty = value[i][ propertyName ];
 
 							switch( property.type ) {
+								case 'i':
+									_gl.uniform1i( locationProperty, valueProperty );
+									break;
 								case 'f':
 									_gl.uniform1f( locationProperty, valueProperty );
 									break;
@@ -2667,7 +2673,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 				if( ! light.__webglUniforms ) {
 					light.__webglUniforms = {
 						direction: new THREE.Vector3(),
-						color: new THREE.Color()
+						color: new THREE.Color(),
+						shadow: -1
 					}
 				}
 
@@ -2681,8 +2688,14 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( light.castShadow ) {
 
+					uniforms.shadow = shadowsLength;
+
 					_lights.shadows[ shadowsLength ++ ] = light;
 
+				} else {
+
+					uniforms.shadow = -1;
+
 				}
 
 				_lights.directional[ directionalLength ++ ] = uniforms;
@@ -2694,7 +2707,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 						position: new THREE.Vector3(),
 						color: new THREE.Color(),
 						distance: 0,
-						decay: 0
+						decay: 0,
+						shadow: -1
 					}
 				}
 
@@ -2709,9 +2723,15 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( light.castShadow ) {
 
+					uniforms.shadow = shadowsLength;
+
 					_lights.shadows[ shadowsLength ++ ] = light;
 					_lights.shadowsPointLight ++;
 
+				} else {
+
+					uniforms.shadow = -1;
+
 				}
 
 				_lights.point[ pointLength ++ ] = uniforms;
@@ -2748,8 +2768,14 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( light.castShadow ) {
 
+					uniforms.shadow = shadowsLength;
+
 					_lights.shadows[ shadowsLength ++ ] = light;
 
+				} else {
+
+					uniforms.shadow = -1;
+
 				}
 
 				_lights.spot[ spotLength ++ ] = uniforms;

+ 3 - 0
src/renderers/shaders/ShaderChunk/lights_pars.glsl

@@ -11,6 +11,7 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 	struct DirectionalLight {
 	  vec3 direction;
 	  vec3 color;
+	  int shadow;
 	};
 
 	uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];
@@ -36,6 +37,7 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 	  vec3 color;
 	  float distance;
 	  float decay;
+	  int shadow;
 	};
 
 	uniform PointLight pointLights[ NUM_POINT_LIGHTS ];
@@ -67,6 +69,7 @@ vec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {
 	  float decay;
 	  float angleCos;
 	  float exponent;
+	  int shadow;
 	};
 
 	uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];

+ 38 - 2
src/renderers/shaders/ShaderChunk/lights_template.glsl

@@ -19,8 +19,20 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 
 	for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {
 
+		PointLight pointLight = pointLights[ i ];
+
 		IncidentLight directLight = getPointDirectLight( pointLights[ i ], geometry );
 
+		#ifdef USE_SHADOWMAP
+		if ( pointLight.shadow > - 1 ) {
+			for ( int j = 0; j < NUM_SHADOWS; j ++ ) {
+				if ( j == pointLight.shadow ) {
+					directLight.color *= shadows[ j ];
+				}
+			}
+		}
+		#endif
+
 		Material_RE_DirectLight( directLight, geometry, material, reflectedLight );
 
 	}
@@ -31,7 +43,19 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 
 	for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {
 
-		IncidentLight directLight = getSpotDirectLight( spotLights[ i ], geometry );
+		SpotLight spotLight = spotLights[ i ];
+
+		IncidentLight directLight = getSpotDirectLight( spotLight, geometry );
+
+		#ifdef USE_SHADOWMAP
+		if ( spotLight.shadow > - 1 ) {
+			for ( int j = 0; j < NUM_SHADOWS; j ++ ) {
+				if ( j == spotLight.shadow ) {
+					directLight.color *= shadows[ j ];
+				}
+			}
+		}
+		#endif
 
 		Material_RE_DirectLight( directLight, geometry, material, reflectedLight );
 
@@ -43,7 +67,19 @@ GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal
 
 	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
 
-		IncidentLight directLight = getDirectionalDirectLight( directionalLights[ i ], geometry );
+		DirectionalLight directionalLight = directionalLights[ i ];
+
+		IncidentLight directLight = getDirectionalDirectLight( directionalLight, geometry );
+
+		#ifdef USE_SHADOWMAP
+		if ( directionalLight.shadow > - 1 ) {
+			for ( int j = 0; j < NUM_SHADOWS; j ++ ) {
+				if ( j == directionalLight.shadow ) {
+					directLight.color *= shadows[ j ];
+				}
+			}
+		}
+		#endif
 
 		Material_RE_DirectLight( directLight, geometry, material, reflectedLight );
 

+ 4 - 0
src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl

@@ -2,6 +2,8 @@
 
 	vec3 shadowMask = vec3( 1.0 );
 
+	float shadows[ NUM_SHADOWS ];
+
 	for ( int i = 0; i < NUM_SHADOWS; i ++ ) {
 
 		float texelSizeY =  1.0 / shadowMapSize[ i ].y;
@@ -259,6 +261,8 @@
 
 		shadowMask = shadowMask * vec3( 1.0 - shadow );
 
+		shadows[ i ] = 1.0 - shadow;
+
 	}
 
 #endif

+ 4 - 9
src/renderers/shaders/ShaderLib.js

@@ -380,6 +380,8 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "normal_phong_fragment" ],
 				THREE.ShaderChunk[ "emissivemap_fragment" ],
 
+				THREE.ShaderChunk[ "shadowmap_fragment" ],
+
 				// accumulation
 				THREE.ShaderChunk[ "lights_phong_fragment" ],
 				THREE.ShaderChunk[ "lights_template" ],
@@ -387,10 +389,6 @@ THREE.ShaderLib = {
 
 				// modulation
 				THREE.ShaderChunk[ "aomap_fragment" ],
-				THREE.ShaderChunk[ "shadowmap_fragment" ],
-
-				"reflectedLight.directDiffuse *= shadowMask;",
-				"reflectedLight.directSpecular *= shadowMask;",
 
 				"vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveLight;",
 
@@ -555,6 +553,8 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "normal_phong_fragment" ], // use phong chunk for now
 				THREE.ShaderChunk[ "emissivemap_fragment" ],
 
+				THREE.ShaderChunk[ "shadowmap_fragment" ],
+
 				// accumulation
 				THREE.ShaderChunk[ "lights_standard_fragment" ],
 				THREE.ShaderChunk[ "lights_template" ],
@@ -563,11 +563,6 @@ THREE.ShaderLib = {
 				// modulation
 				THREE.ShaderChunk[ "aomap_fragment" ],
 
-				THREE.ShaderChunk[ "shadowmap_fragment" ],
-
-				"reflectedLight.directDiffuse *= shadowMask;",
-				"reflectedLight.directSpecular *= shadowMask;",
-
 				"vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveLight;",
 
 				THREE.ShaderChunk[ "linear_to_gamma_fragment" ],

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

@@ -97,7 +97,8 @@ THREE.UniformsLib = {
 
 		"directionalLights" : { type: "sa", value: [], properties: {
 			"direction": { type: "v3" },
-			"color": { type: "c" }
+			"color": { type: "c" },
+			"shadow": { type: "i" }
 		} },
 
 		"hemisphereLights" : { type: "sa", value: [], properties: {
@@ -110,7 +111,8 @@ THREE.UniformsLib = {
 			"color": { type: "c" },
 			"position": { type: "v3" },
 			"decay": { type: "f" },
-			"distance": { type: "f" }
+			"distance": { type: "f" },
+			"shadow": { type: "i" }
 		} },
 
 		"spotLights" : { type: "sa", value: [], properties: {
@@ -120,7 +122,8 @@ THREE.UniformsLib = {
 			"distance": { type: "f" },
 			"angleCos": { type: "f" },
 			"exponent": { type: "f" },
-			"decay": { type: "f" }
+			"decay": { type: "f" },
+			"shadow": { type: "i" }
 		} }