Browse Source

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 years ago
parent
commit
72dae73940
2 changed files with 43 additions and 36 deletions
  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;
 
 			}