فهرست منبع

Merge pull request #3620 from lostink/master

Projection Texture added to newest coset
sebavan 7 سال پیش
والد
کامیت
262e010675

+ 64 - 3
src/Lights/babylon.light.ts

@@ -1,4 +1,4 @@
-module BABYLON {
+module BABYLON {
     export class Light extends Node {
 
         //lightmapMode Consts
@@ -384,7 +384,59 @@
             }
             return b.renderPriority - a.renderPriority;
         }
+        // Projection texture, if needed
+        protected _computeTextureMatrix(): void{
+            //Leave out for different light type
+        }
+        protected _light_far  :number;
+        @serialize()
+        /**
+         * Allows reading the far clip of the Spotlight for texture projection.
+         */
+        public get light_far(): number {
+            return this._light_far;
+        }
+        /**
+         * Allows setting the far clip of the Spotlight for texture projection.
+         */
+        public set light_far(value: number) {
+            this._light_far = value;
+            this._computeTextureMatrix();
+        }
+
+        protected _light_near :number;
+        @serialize()
+        /**
+         * Allows reading the near clip of the Spotlight for texture projection.
+         */
+        public get light_near(): number {
+            return this._light_near;
+        }
+        /**
+         * Allows setting the near clip of the Spotlight for texture projection.
+         */
+        public set light_near(value: number) {
+            this._light_near = value;
+            this._computeTextureMatrix();
+        }
 
+        @serializeAsTexture("projectedLightTexture")
+        private _projectedLightTexture: Nullable<BaseTexture>;;
+        /** 
+         * Allows reading the projection texture of the light.
+        */
+        public get projectedLightTexture(): Nullable<BaseTexture> {
+            return this._projectedLightTexture;
+        }
+        /**
+        * Allows setting the projection texture of the light.
+        */
+        public set projectedLightTexture(value: Nullable<BaseTexture>) {
+            this._projectedLightTexture = value;
+            this._light_far = 1000.0;
+            this._light_near = 1e-6;
+            this._computeTextureMatrix();
+        }
         /**
          * Disposes the light.  
          */
@@ -397,8 +449,15 @@
             // Animations
             this.getScene().stopAnimation(this);
 
-            this._uniformBuffer.dispose();
+            // Remove from meshes
+            for (var mesh of this.getScene().meshes) {
+                mesh._removeLightSource(this);
+            }
 
+            this._uniformBuffer.dispose();
+            if (this._projectedLightTexture){
+                this._projectedLightTexture.dispose();
+            }
             // Remove from scene
             this.getScene().removeLight(this);
             super.dispose();
@@ -658,7 +717,6 @@
             }
             return photometricScale;
         }
-
         public _reorderLightsInScene(): void {
             var scene = this.getScene();
             if (this._renderPriority != 0) {
@@ -666,5 +724,8 @@
             }
             this.getScene().sortLightsByPriority();
         }
+
+
+
     }
 }

+ 71 - 1
src/Lights/babylon.spotLight.ts

@@ -1,5 +1,55 @@
 module BABYLON {
     export class SpotLight extends ShadowLight {
+        /**
+            upVector , rightVector and direction will form the coordinate system for this spot light. 
+            These three vectors will be used as projection matrix when doing texture projection.
+            
+            Also we have the following rules always holds:
+            direction cross up   = right
+            right cross dirction = up
+            up cross right       = forward
+
+            light_near and light_far will control the range of the texture projection. If a plane is 
+            out of the range in spot light space, there is no texture projection.
+
+            Warning:
+            Change the angle of the Spotlight, direction of the SpotLight will not re-compute the 
+            projection matrix. Need to call computeTextureMatrix() to recompute manually. Add inheritance
+            to the setting function of the 2 attributes will solve the problem.
+        */
+        /**
+         * Main function for light texture projection matrix computing.
+         */
+        protected _computeTextureMatrix(): void{    
+
+            var viewLightMatrix = Matrix.Zero();
+            Matrix.LookAtLHToRef(this.position, this.position.add(this.direction), Vector3.Up(), viewLightMatrix);
+
+            var light_far = this.light_far;
+            var light_near = this.light_near;
+
+            var P = light_far / (light_far - light_near);
+            var Q = - P * light_near;
+            var S = 1.0 / Math.tan(this._angle / 2.0);
+            var A = 1.0;
+            
+            var projectionLightMatrix = Matrix.Zero();
+            Matrix.FromValuesToRef(S/A, 0.0, 0.0, 0.0,
+                0.0, S, 0.0, 0.0,
+                0.0, 0.0, P, 1.0,
+                0.0, 0.0, Q, 0.0, projectionLightMatrix);
+
+            var scaleMatrix = Matrix.Zero();
+            Matrix.FromValuesToRef(0.5, 0.0, 0.0, 0.0,
+                0.0, 0.5, 0.0, 0.0,
+                0.0, 0.0, 0.5, 0.0,
+                0.5, 0.5, 0.5, 1.0, scaleMatrix);
+                
+            this._textureProjectionMatrix.copyFrom(viewLightMatrix);
+            this._textureProjectionMatrix.multiplyToRef(projectionLightMatrix, this._textureProjectionMatrix);
+            this._textureProjectionMatrix.multiplyToRef(scaleMatrix, this._textureProjectionMatrix);
+        }
+
         private _angle: number;
         @serialize()
         public get angle(): number {
@@ -25,9 +75,24 @@
             this._shadowAngleScale = value;
             this.forceProjectionMatrixCompute();
         }
-
         @serialize()
         public exponent: number;
+
+        private _textureProjectionMatrix = Matrix.Zero();
+        @serialize()
+        /**
+        * Allows reading the projecton texture
+        */
+        public get textureMatrix(): Matrix{
+            return this._textureProjectionMatrix;
+        }
+        /**
+        * Allows setting the value of projection texture
+        */
+        public set textureMatrix(value: Matrix) {
+            this._textureProjectionMatrix = value;
+        }
+
         
         /**
          * Creates a SpotLight object in the scene with the passed parameters :   
@@ -123,6 +188,11 @@
                 normalizeDirection.z,
                 Math.cos(this.angle * 0.5),
                 lightIndex);
+
+            effect.setMatrix("textureProjectionMatrix" + lightIndex, this._textureProjectionMatrix);
+            if (this.projectedLightTexture){
+                effect.setTexture("projectionLightSampler" + lightIndex, this.projectedLightTexture);
+            }
             return this;
         }
     }

+ 13 - 1
src/Materials/babylon.materialHelper.ts

@@ -1,4 +1,4 @@
-module BABYLON {
+module BABYLON {
     export class MaterialHelper {
 
         public static BindEyePosition(effect: Effect, scene: Scene): void {
@@ -207,6 +207,12 @@
                         defines["LIGHTMAPNOSPECULAR" + lightIndex] = false;
                     }
 
+                    //Projection texture
+                    if (light.projectedLightTexture){
+                        defines["PROJECTEDLIGHTTEXTURE" + lightIndex] = true;
+                    }else{
+                        defines["PROJECTEDLIGHTTEXTURE" + lightIndex] = false;                        
+                    }
                     lightIndex++;
                     if (lightIndex === maxSimultaneousLights)
                         break;
@@ -285,6 +291,12 @@
                 }
 
                 samplersList.push("shadowSampler" + lightIndex);
+                if (defines["PROJECTEDLIGHTTEXTURE" + lightIndex]){
+                    samplersList.push("projectionLightSampler" + lightIndex,);
+                    uniformsList.push(
+                        "textureProjectionMatrix" + lightIndex,
+                    );
+                }
             }
 
             if (defines["NUM_MORPH_INFLUENCERS"]) {

+ 3 - 0
src/Shaders/ShadersInclude/lightFragment.fx

@@ -23,6 +23,9 @@
 				info = computeLighting(viewDirectionW, normalW, light{X}.vLightData, light{X}.vLightDiffuse.rgb, light{X}.vLightSpecular, light{X}.vLightDiffuse.a, glossiness);
 			#endif
 		#endif
+		#ifdef PROJECTEDLIGHTTEXTURE{X}
+			info = computeProjectionTexture(info,projectionLightSampler{X},textureProjectionMatrix{X});
+		#endif
     #endif
 	#ifdef SHADOW{X}
 		#ifdef SHADOWCLOSEESM{X}

+ 4 - 0
src/Shaders/ShadersInclude/lightFragmentDeclaration.fx

@@ -25,4 +25,8 @@
 	#ifdef HEMILIGHT{X}
 		uniform vec3 vLightGround{X};
 	#endif
+	#ifdef PROJECTEDLIGHTTEXTURE{X}
+		uniform mat4 textureProjectionMatrix{X};
+		uniform sampler2D projectionLightSampler{X};
+	#endif
 #endif

+ 4 - 1
src/Shaders/ShadersInclude/lightUboDeclaration.fx

@@ -13,7 +13,10 @@
 		vec4 shadowsInfo;
 		vec2 depthValues;
 	} light{X};
-
+#ifdef PROJECTEDLIGHTTEXTURE{X}
+	uniform mat4 textureProjectionMatrix{X};
+	uniform sampler2D projectionLightSampler{X};
+#endif
 #ifdef SHADOW{X}
 	#if defined(SHADOWCUBE{X})
 		uniform samplerCube shadowSampler{X};

+ 10 - 5
src/Shaders/ShadersInclude/lightsFragmentFunctions.fx

@@ -1,4 +1,4 @@
-// Light Computing
+// Light Computing
 struct lightingInfo
 {
 	vec3 diffuse;
@@ -32,9 +32,7 @@ lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData,
 #ifdef NDOTL
 	result.ndl = ndl;
 #endif
-
 	result.diffuse = ndl * diffuseColor * attenuation;
-
 #ifdef SPECULARTERM
 	// Specular
 	vec3 angleW = normalize(viewDirectionW + lightVectorW);
@@ -67,7 +65,6 @@ lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightDa
 		result.ndl = ndl;
 #endif
 		result.diffuse = ndl * diffuseColor * attenuation;
-
 #ifdef SPECULARTERM
 		// Specular
 		vec3 angleW = normalize(viewDirectionW + lightVectorW);
@@ -109,6 +106,14 @@ lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4
 
 	result.specular = specComp * specularColor;
 #endif
+		return result;
+}
 
+lightingInfo computeProjectionTexture(lightingInfo origin,sampler2D projectionLightSampler, mat4 textureProjectionMatrix){
+	lightingInfo result = origin;
+	vec4 strq = textureProjectionMatrix * vec4(vPositionW, 1.0);
+	strq /= strq.w;
+	vec4 textureColor = texture2D(projectionLightSampler, strq.xy);
+	result.diffuse *= vec3(textureColor);
 	return result;
-}
+}