فهرست منبع

WebGLDeferredRenderer: refactored spotlights.

Moved view space light direction and position computations out of the shader.

These are constant for every pixel affected by the light, so computation can be done just once per light in JS and then passed in as uniform.
alteredq 12 سال پیش
والد
کامیت
72dae73940
2فایلهای تغییر یافته به همراه43 افزوده شده و 36 حذف شده
  1. 8 23
      examples/js/ShaderDeferred.js
  2. 35 13
      examples/js/renderers/WebGLDeferredRenderer.js

+ 8 - 23
examples/js/ShaderDeferred.js

@@ -536,12 +536,11 @@ THREE.ShaderDeferred = {
 
 			samplerNormalDepth: { type: "t", value: null },
 			samplerColor: 		{ type: "t", value: null },
-			matView: 		{ type: "m4", value: new THREE.Matrix4() },
 			matProjInverse: { type: "m4", value: new THREE.Matrix4() },
 			viewWidth: 		{ type: "f", value: 800 },
 			viewHeight: 	{ type: "f", value: 600 },
-			lightPositionWS:{ type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
-			lightTargetWS: 	{ type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
+			lightPositionVS :{ type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
+			lightDirectionVS:{ type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
 			lightColor: 	{ type: "c", value: new THREE.Color( 0x000000 ) },
 			lightIntensity: { type: "f", value: 1.0 },
 			lightDistance: 	{ type: "f", value: 1.0 },
@@ -551,6 +550,9 @@ THREE.ShaderDeferred = {
 
 		fragmentShader : [
 
+			"uniform vec3 lightPositionVS;",
+			"uniform vec3 lightDirectionVS;",
+
 			"uniform sampler2D samplerColor;",
 			"uniform sampler2D samplerNormalDepth;",
 
@@ -563,9 +565,6 @@ THREE.ShaderDeferred = {
 
 			"uniform mat4 matProjInverse;",
 
-			"varying vec3 vLightPositionVS;",
-			"varying vec3 vLightDirectionVS;",
-
 			"vec3 float_to_vec3( float data ) {",
 
 				"vec3 uncompressed;",
@@ -610,10 +609,10 @@ THREE.ShaderDeferred = {
 
 				//
 
-				"vec3 surfToLight = normalize( vLightPositionVS.xyz - positionVS.xyz );",
+				"vec3 surfToLight = normalize( lightPositionVS.xyz - positionVS.xyz );",
 				"float dotProduct = max( dot( normal, surfToLight ), 0.0 );",
 
-				"float rho = dot( vLightDirectionVS, -surfToLight );",
+				"float rho = dot( lightDirectionVS, surfToLight );",
 				"float rhoMax = cos( lightAngle * 0.5 );",
 
 				"if ( rho > rhoMax ) {",
@@ -674,23 +673,9 @@ THREE.ShaderDeferred = {
 
 		vertexShader : [
 
-			"uniform vec3 lightPositionWS;",
-			"uniform vec3 lightTargetWS;",
-
-			"uniform mat4 matView;",
-
-			"varying vec3 vLightPositionVS;",
-			"varying vec3 vLightDirectionVS;",
-
 			"void main() { ",
 
-				"vec4 quadPosition = vec4( sign( position.xy ), 0.0, 1.0 );",
-				"gl_Position = quadPosition;",
-
-				"vLightPositionVS = vec3( matView * vec4( lightPositionWS, 1.0 ) );",
-
-				"vec3 lightDirectionWS = lightTargetWS - lightPositionWS;"+
-				"vLightDirectionVS = normalize( mat3( matView ) * lightDirectionWS );",
+				"gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
 
 			"}"
 

+ 35 - 13
examples/js/renderers/WebGLDeferredRenderer.js

@@ -37,6 +37,9 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 	//
 
+	var positionVS = new THREE.Vector3();
+	var directionVS = new THREE.Vector3();
+
 	var geometryLightSphere = new THREE.SphereGeometry( 1, 16, 8 );
 	var geometryLightPlane = new THREE.PlaneGeometry( 2, 2 );
 
@@ -384,9 +387,11 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		// setup light material
 
+		var uniforms = THREE.UniformsUtils.clone( spotLightShader.uniforms );
+
 		var materialLight = new THREE.ShaderMaterial( {
 
-			uniforms:       THREE.UniformsUtils.clone( spotLightShader.uniforms ),
+			uniforms:       uniforms,
 			vertexShader:   spotLightShader.vertexShader,
 			fragmentShader: spotLightShader.fragmentShader,
 
@@ -401,18 +406,27 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		var intensity = light.intensity * light.intensity;
 
-		materialLight.uniforms[ "lightPositionWS" ].value.copy( light.matrixWorld.getPosition() );
-		materialLight.uniforms[ "lightTargetWS" ].value.copy( light.target.matrixWorld.getPosition() );
-		materialLight.uniforms[ "lightIntensity" ].value = intensity;
-		materialLight.uniforms[ "lightAngle" ].value = light.angle;
-		materialLight.uniforms[ "lightDistance" ].value = light.distance;
-		materialLight.uniforms[ "lightColor" ].value.copyGammaToLinear( light.color );
+		positionVS.copy( light.matrixWorld.getPosition() );
+		camera.matrixWorldInverse.multiplyVector3( positionVS );
 
-		materialLight.uniforms[ "viewWidth" ].value = scaledWidth;
-		materialLight.uniforms[ "viewHeight" ].value = scaledHeight;
+		directionVS.copy( light.matrixWorld.getPosition() );
+		directionVS.subSelf( light.target.matrixWorld.getPosition() );
+		directionVS.normalize();
+		camera.matrixWorldInverse.rotateAxis( directionVS );
 
-		materialLight.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
-		materialLight.uniforms[ 'samplerNormalDepth' ].value = compNormalDepth.renderTarget2;
+		uniforms[ "lightPositionVS" ].value.copy( positionVS );
+		uniforms[ "lightDirectionVS" ].value.copy( directionVS );
+
+		uniforms[ "lightIntensity" ].value = intensity;
+		uniforms[ "lightAngle" ].value = light.angle;
+		uniforms[ "lightDistance" ].value = light.distance;
+		uniforms[ "lightColor" ].value.copyGammaToLinear( light.color );
+
+		uniforms[ "viewWidth" ].value = scaledWidth;
+		uniforms[ "viewHeight" ].value = scaledHeight;
+
+		uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
+		uniforms[ 'samplerNormalDepth' ].value = compNormalDepth.renderTarget2;
 
 		// create light proxy mesh
 
@@ -693,8 +707,16 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 			} else if ( originalLight instanceof THREE.SpotLight ) {
 
-				uniforms[ "lightPositionWS" ].value.copy( originalLight.matrixWorld.getPosition() );
-				uniforms[ "lightTargetWS" ].value.copy( originalLight.target.matrixWorld.getPosition() );
+				positionVS.copy( originalLight.matrixWorld.getPosition() );
+				camera.matrixWorldInverse.multiplyVector3( positionVS );
+
+				directionVS.copy( originalLight.matrixWorld.getPosition() );
+				directionVS.subSelf( originalLight.target.matrixWorld.getPosition() );
+				directionVS.normalize();
+				camera.matrixWorldInverse.rotateAxis( directionVS );
+
+				uniforms[ "lightPositionVS" ].value.copy( positionVS );
+				uniforms[ "lightDirectionVS" ].value.copy( directionVS );
 				uniforms[ "lightAngle" ].value = originalLight.angle;
 
 			}