OSDN Git Service

SpotLight : reduced the number of float varying by 5 in the shaders :
authorremy.bouquet@gmail.com <remy.bouquet@gmail.com@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Fri, 5 Aug 2011 17:03:46 +0000 (17:03 +0000)
committerremy.bouquet@gmail.com <remy.bouquet@gmail.com@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Fri, 5 Aug 2011 17:03:46 +0000 (17:03 +0000)
- computed the spotDirection in view space on the java side in Material and pass it as a uniform -> vec4 spotVec disapear
- this implies to decode the cos values for falloff in the frag shader instead of the vert shader, but allows to reduce light vec from vec4 to vec3

All in all it shouldn't be that much of a performance hit, since the matrix multiplication of spotVec occur once per geometry instead of once per vertex, we could go further and compute it once per frame.
On the other hand decoding of the cos values happens once for each pixel instead of once for each vertex ( a floor a mult and a fract). I guess this should be balanced in a rich scene.

git-svn-id: http://jmonkeyengine.googlecode.com/svn/trunk@7978 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

engine/src/core-data/Common/MatDefs/Light/Lighting.frag
engine/src/core-data/Common/MatDefs/Light/Lighting.vert
engine/src/core/com/jme3/material/Material.java
engine/src/core/com/jme3/util/TempVars.java

index 1dfe0e0..0c50b07 100644 (file)
@@ -2,6 +2,7 @@
 #define ATTENUATION\r
 //#define HQ_ATTENUATION\r
 \r
+uniform vec4 g_LightDirection;\r
 varying vec2 texCoord;\r
 #ifdef SEPARATE_TEXCOORD\r
   varying vec2 texCoord2;\r
@@ -50,8 +51,7 @@ varying vec3 SpecularSum;
 #endif\r
 uniform float m_AlphaDiscardThreshold;\r
 \r
-varying vec4 lightVec;\r
-varying vec4 spotVec;\r
+varying vec3 lightVec;\r
 \r
 #ifndef VERTEX_LIGHTING\r
 uniform float m_Shininess;\r
@@ -162,12 +162,12 @@ void main(){
 \r
     #ifndef VERTEX_LIGHTING\r
         float spotFallOff = 1.0;\r
-        if(spotVec.w != 0.0){\r
+        if(g_LightDirection.w != 0.0){\r
               vec3 L       = normalize(lightVec.xyz);\r
-              vec3 spotdir = normalize(spotVec.xyz);\r
+              vec3 spotdir = normalize(g_LightDirection.xyz);\r
               float curAngleCos = dot(-L, spotdir);             \r
-              float innerAngleCos = spotVec.w;\r
-              float outerAngleCos = lightVec.w;\r
+              float innerAngleCos = floor(g_LightDirection.w) * 0.001;\r
+              float outerAngleCos = fract(g_LightDirection.w);\r
               float innerMinusOuter = innerAngleCos - outerAngleCos;\r
               spotFallOff = clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0);\r
               if(spotFallOff <= 0.0){\r
index 7f880c1..031633e 100644 (file)
@@ -13,7 +13,7 @@ uniform float m_Shininess;
 \r
 uniform vec4 g_LightColor;\r
 uniform vec4 g_LightPosition;\r
-uniform vec4 g_LightDirection;\r
+//uniform vec4 g_LightDirection;\r
 uniform vec4 g_AmbientLightColor;\r
 \r
 varying vec2 texCoord;\r
@@ -30,8 +30,8 @@ attribute vec3 inPosition;
 attribute vec2 inTexCoord;\r
 attribute vec3 inNormal;\r
 \r
-varying vec4 lightVec;\r
-varying vec4 spotVec;\r
+varying vec3 lightVec;\r
+//varying vec4 spotVec;\r
 \r
 #ifdef VERTEX_COLOR\r
   attribute vec4 inColor;\r
@@ -83,7 +83,7 @@ varying vec4 spotVec;
 void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){\r
     float posLight = step(0.5, color.w);\r
     vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);\r
-    lightVec.xyz = tempVec;  \r
+    lightVec = tempVec;  \r
     #ifdef ATTENUATION\r
      float dist = length(tempVec);\r
      lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);\r
@@ -176,9 +176,9 @@ void main(){
    #endif\r
 \r
    //computing spot direction in view space and unpacking spotlight cos\r
-   spotVec = (g_ViewMatrix * vec4(g_LightDirection.xyz, 0.0) );\r
-   spotVec.w  = floor(g_LightDirection.w) * 0.001;\r
-   lightVec.w = fract(g_LightDirection.w);\r
+//   spotVec = (g_ViewMatrix * vec4(g_LightDirection.xyz, 0.0) );\r
+//   spotVec.w  = floor(g_LightDirection.w) * 0.001;\r
+//   lightVec.w = fract(g_LightDirection.w);\r
 \r
    lightColor.w = 1.0;\r
    #ifdef MATERIAL_COLORS\r
index 369b646..fa14f0d 100644 (file)
@@ -47,7 +47,6 @@ import com.jme3.light.LightList;
 import com.jme3.light.PointLight;
 import com.jme3.light.SpotLight;
 import com.jme3.material.TechniqueDef.LightMode;
-import com.jme3.math.FastMath;
 import com.jme3.math.Quaternion;
 import com.jme3.math.Vector3f;
 import com.jme3.math.Vector4f;
@@ -98,7 +97,6 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
         additiveLight.setBlendMode(RenderState.BlendMode.AlphaAdditive);
         additiveLight.setDepthWrite(false);
     }
-    
     private AssetKey key;
     private MaterialDef def;
     private ListMap<String, MatParam> paramValues = new ListMap<String, MatParam>();
@@ -141,14 +139,14 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
         return key != null ? key.getName() : null;
     }
 
-    public void setKey(AssetKey key){
+    public void setKey(AssetKey key) {
         this.key = key;
     }
-    
-    public AssetKey getKey(){
+
+    public AssetKey getKey() {
         return key;
     }
-    
+
     /**
      * Returns the sorting ID or sorting index for this material. 
      * 
@@ -698,7 +696,9 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
         }
     }
 
-    protected void renderMultipassLighting(Shader shader, Geometry g, Renderer r) {
+    protected void renderMultipassLighting(Shader shader, Geometry g, RenderManager rm) {
+
+        Renderer r = rm.getRenderer();
         LightList lightList = g.getWorldLightList();
         Uniform lightDir = shader.getUniform("g_LightDirection");
         Uniform lightColor = shader.getUniform("g_LightColor");
@@ -729,6 +729,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
             Quaternion tmpLightDirection = vars.quat1;
             Quaternion tmpLightPosition = vars.quat2;
             ColorRGBA tmpLightColor = vars.color;
+            Vector4f tmpVec = vars.vect4f;
 
             ColorRGBA color = l.getColor();
             tmpLightColor.set(color);
@@ -742,7 +743,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
 
                     tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1);
                     lightPos.setValue(VarType.Vector4, tmpLightPosition);
-                    tmpLightDirection.set(0,0,0,0);
+                    tmpLightDirection.set(0, 0, 0, 0);
                     lightDir.setValue(VarType.Vector4, tmpLightDirection);
                     break;
                 case Point:
@@ -752,7 +753,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
 
                     tmpLightPosition.set(pos.getX(), pos.getY(), pos.getZ(), invRadius);
                     lightPos.setValue(VarType.Vector4, tmpLightPosition);
-                    tmpLightDirection.set(0,0,0,0);
+                    tmpLightDirection.set(0, 0, 0, 0);
                     lightDir.setValue(VarType.Vector4, tmpLightDirection);
                     break;
                 case Spot:
@@ -765,7 +766,13 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
                     tmpLightPosition.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange);
                     lightPos.setValue(VarType.Vector4, tmpLightPosition);
 
-                    tmpLightDirection.set(dir2.getX(), dir2.getY(), dir2.getZ(), spotAngleCos);
+                    //We transform the spot directoin in view space here to save 5 varying later in the lighting shader
+                    //one vec4 less and a vec4 that becomes a vec3
+                    //the downside is that spotAngleCos decoding happen now in the frag shader.
+                    tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(),0);
+                    rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
+                    tmpLightDirection.set(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos);
+
                     lightDir.setValue(VarType.Vector4, tmpLightDirection);
 
                     break;
@@ -951,6 +958,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
         autoSelectTechnique(rm);
 
         Renderer r = rm.getRenderer();
+
         TechniqueDef techDef = technique.getDef();
 
         if (techDef.getLightMode() == LightMode.MultiPass
@@ -999,7 +1007,7 @@ public class Material implements Asset, Cloneable, Savable, Comparable<Material>
             case MultiPass:
                 // NOTE: Special case!
                 resetUniformsNotSetByCurrent(shader);
-                renderMultipassLighting(shader, geom, r);
+                renderMultipassLighting(shader, geom, rm);
                 // very important, notice the return statement!
                 return;
         }
index f51ab83..5b361e9 100644 (file)
@@ -41,6 +41,7 @@ import com.jme3.math.Quaternion;
 import com.jme3.math.Triangle;\r
 import com.jme3.math.Vector2f;\r
 import com.jme3.math.Vector3f;\r
+import com.jme3.math.Vector4f;\r
 import com.jme3.scene.Spatial;\r
 import java.nio.FloatBuffer;\r
 import java.nio.IntBuffer;\r
@@ -53,13 +54,13 @@ import java.util.ArrayList;
  * This returns an available instance of the TempVar class ensuring this \r
  * particular instance is never used elsewhere in the mean time.\r
  */\r
-public class TempVars {    \r
+public class TempVars {\r
 \r
     /**\r
      * Allow X instances of TempVars in a single thread.\r
      */\r
     private static final int STACK_SIZE = 5;\r
-    \r
+\r
     /**\r
      * <code>TempVarsStack</code> contains a stack of TempVars.\r
      * Every time TempVars.get() is called, a new entry is added to the stack,\r
@@ -68,30 +69,30 @@ public class TempVars {
      * the current instance and  then the index is decremented.\r
      */\r
     private static class TempVarsStack {\r
+\r
         int index = 0;\r
         TempVars[] tempVars = new TempVars[STACK_SIZE];\r
     }\r
-    \r
     /**\r
      * ThreadLocal to store a TempVarsStack for each thread.\r
      * This ensures each thread has a single TempVarsStack that is\r
      * used only in method calls in that thread.\r
      */\r
     private static final ThreadLocal<TempVarsStack> varsLocal = new ThreadLocal<TempVarsStack>() {\r
+\r
         @Override\r
         public TempVarsStack initialValue() {\r
             return new TempVarsStack();\r
         }\r
     };\r
-   \r
     /**\r
      * This instance of TempVars has been retrieved but not released yet.\r
      */\r
     private boolean isUsed = false;\r
-    \r
+\r
     private TempVars() {\r
     }\r
-    \r
+\r
     /**\r
      * Acquire an instance of the TempVar class.\r
      * You have to release the instance after use by calling the \r
@@ -103,21 +104,21 @@ public class TempVars {
      */\r
     public static TempVars get() {\r
         TempVarsStack stack = varsLocal.get();\r
-        \r
+\r
         TempVars instance = stack.tempVars[stack.index];\r
-        \r
-        if (instance == null){\r
+\r
+        if (instance == null) {\r
             // Create new\r
             instance = new TempVars();\r
-            \r
+\r
             // Put it in there\r
             stack.tempVars[stack.index] = instance;\r
         }\r
-        \r
+\r
         stack.index++;\r
-        \r
+\r
         instance.isUsed = true;\r
-        \r
+\r
         return instance;\r
     }\r
 \r
@@ -129,23 +130,22 @@ public class TempVars {
      * first otherwise an exception will be thrown.\r
      */\r
     public void release() {\r
-        if (!isUsed){\r
+        if (!isUsed) {\r
             throw new IllegalStateException("This instance of TempVars was already released!");\r
         }\r
-        \r
+\r
         isUsed = false;\r
-        \r
+\r
         TempVarsStack stack = varsLocal.get();\r
-        \r
+\r
         // Return it to the stack\r
         stack.index--;\r
-        \r
+\r
         // Check if it is actually there\r
-        if (stack.tempVars[stack.index] != this){\r
+        if (stack.tempVars[stack.index] != this) {\r
             throw new IllegalStateException("An instance of TempVars has not been released in a called method!");\r
         }\r
     }\r
-    \r
     /**\r
      * For interfacing with OpenGL in Renderer.\r
      */\r
@@ -161,7 +161,6 @@ public class TempVars {
      * Fetching triangle from mesh\r
      */\r
     public final Triangle triangle = new Triangle();\r
-    \r
     /**\r
      * Color\r
      */\r
@@ -180,6 +179,7 @@ public class TempVars {
     public final Vector3f vect8 = new Vector3f();\r
     public final Vector3f vect9 = new Vector3f();\r
     public final Vector3f vect10 = new Vector3f();\r
+    public final Vector4f vect4f = new Vector4f();\r
     public final Vector3f[] tri = {new Vector3f(),\r
         new Vector3f(),\r
         new Vector3f()};\r