소스 검색

Introduced a LightSpace attribute in the TechniqueDef to define in what space LightData should be sent to the shader. Used it for the multipass lighting

Nehon 10 년 전
부모
커밋
01ed6db77c
2개의 변경된 파일62개의 추가작업 그리고 9개의 파일을 삭제
  1. 25 8
      jme3-core/src/main/java/com/jme3/material/Material.java
  2. 37 1
      jme3-core/src/main/java/com/jme3/material/TechniqueDef.java

+ 25 - 8
jme3-core/src/main/java/com/jme3/material/Material.java

@@ -874,7 +874,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
 
             TempVars vars = TempVars.get();
             Quaternion tmpLightDirection = vars.quat1;
-            Quaternion tmpLightPosition = vars.quat2;
+            Vector4f tmpLightPosition = vars.vect4f2;
             ColorRGBA tmpLightColor = vars.color;
             Vector4f tmpVec = vars.vect4f1;
 
@@ -892,7 +892,8 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
                     //The directional light direction is passed in the 
                     //LightPosition uniform. The lighting shader needs to be 
                     //reworked though in order to fix this.
-                    tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1);
+                    tmpLightPosition.set(dir.getX(), dir.getY(), dir.getZ(), -1);      
+                    transposeLightDataToSpace(technique.getDef().getLightSpace(), rm, tmpLightPosition);
                     lightPos.setValue(VarType.Vector4, tmpLightPosition);
                     tmpLightDirection.set(0, 0, 0, 0);
                     lightDir.setValue(VarType.Vector4, tmpLightDirection);
@@ -903,6 +904,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
                     float invRadius = pl.getInvRadius();
 
                     tmpLightPosition.set(pos.getX(), pos.getY(), pos.getZ(), invRadius);
+                    transposeLightDataToSpace(technique.getDef().getLightSpace(), rm, tmpLightPosition);
                     lightPos.setValue(VarType.Vector4, tmpLightPosition);
                     tmpLightDirection.set(0, 0, 0, 0);
                     lightDir.setValue(VarType.Vector4, tmpLightDirection);
@@ -913,15 +915,21 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
                     Vector3f dir2 = sl.getDirection();
                     float invRange = sl.getInvSpotRange();
                     float spotAngleCos = sl.getPackedAngleCos();
-
+                
                     tmpLightPosition.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange);
+                    transposeLightDataToSpace(technique.getDef().getLightSpace(), rm, tmpLightPosition);
                     lightPos.setValue(VarType.Vector4, tmpLightPosition);
 
-                    //We transform the spot direction 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 happens now in the frag shader.
                     tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0);
-                    rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
+                    if (technique.getDef().getLightSpace() == TechniqueDef.LightSpace.Legacy) {
+                        //Legacy kept for backward compatibility.
+                        //We transform the spot direction 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 happens now in the frag shader.
+                        transposeLightDataToSpace(TechniqueDef.LightSpace.View, rm, tmpVec);
+                    } else {
+                        transposeLightDataToSpace(technique.getDef().getLightSpace(), rm, tmpVec);
+                    }
                     tmpLightDirection.set(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos);
 
                     lightDir.setValue(VarType.Vector4, tmpLightDirection);
@@ -945,6 +953,12 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
             renderMeshFromGeometry(r, g);
         }
     }
+    
+    private void transposeLightDataToSpace(TechniqueDef.LightSpace space, RenderManager rm, Vector4f store){
+        if(space == TechniqueDef.LightSpace.View){          
+            rm.getCurrentCamera().getViewMatrix().mult(store, store);            
+        }
+    };
 
     /**
      * Select the technique to use for rendering this material.
@@ -1179,15 +1193,17 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
 
         Shader shader = technique.getShader();
 
+        
         // send lighting information, if needed
         switch (techDef.getLightMode()) {
             case Disable:
                 break;
             case SinglePass:
+                assert technique.getDef().getLightSpace()!= null;
                 int nbRenderedLights = 0;
                 resetUniformsNotSetByCurrent(shader);
                 if (lights.size() == 0) {
-                    nbRenderedLights = updateLightListUniforms(shader, geom, lights, rm.getSinglePassLightBatchSize(), rm, 0);
+                    updateLightListUniforms(shader, geom, lights, rm.getSinglePassLightBatchSize(), rm, 0);
                     r.setShader(shader);
                     renderMeshFromGeometry(r, geom);
                 } else {
@@ -1201,6 +1217,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
             case FixedPipeline:
                 throw new IllegalArgumentException("OpenGL1 is not supported");
             case MultiPass:
+                assert technique.getDef().getLightSpace()!= null;
                 // NOTE: Special case!
                 resetUniformsNotSetByCurrent(shader);
                 renderMultipassLighting(shader, geom, lights, rm);

+ 37 - 1
jme3-core/src/main/java/com/jme3/material/TechniqueDef.java

@@ -90,6 +90,15 @@ public class TechniqueDef implements Savable {
         InPass,
         PostPass,
     }
+    
+    /**
+     * Define in what space the light data should be sent to the shader.
+     */
+    public enum LightSpace {
+        World,
+        View,
+        Legacy
+    }
 
     private EnumSet<Caps> requiredCaps = EnumSet.noneOf(Caps.class);
     private String name;
@@ -111,6 +120,8 @@ public class TechniqueDef implements Savable {
 
     private HashMap<String, String> defineParams;
     private ArrayList<UniformBinding> worldBinds;
+    //The space in which the light should be transposed before sending to the shader.
+    private LightSpace lightSpace;
 
     /**
      * Creates a new technique definition.
@@ -161,6 +172,14 @@ public class TechniqueDef implements Savable {
      */
     public void setLightMode(LightMode lightMode) {
         this.lightMode = lightMode;
+        //if light space is not specified we set it to Legacy
+        if(lightSpace == null){
+            if(lightMode== LightMode.MultiPass){
+                lightSpace = LightSpace.Legacy;
+            }else if(lightMode== LightMode.SinglePass){
+                lightSpace = LightSpace.View;
+            }
+        }
     }
 
     /**
@@ -530,5 +549,22 @@ public class TechniqueDef implements Savable {
     @Override
     public String toString() {
         return "TechniqueDef{" + "requiredCaps=" + requiredCaps + ", name=" + name /*+ ", vertName=" + vertName + ", fragName=" + fragName + ", vertLanguage=" + vertLanguage + ", fragLanguage=" + fragLanguage */+ ", presetDefines=" + presetDefines + ", usesShaders=" + usesShaders + ", usesNodes=" + usesNodes + ", shaderNodes=" + shaderNodes + ", shaderGenerationInfo=" + shaderGenerationInfo + ", renderState=" + renderState + ", forcedRenderState=" + forcedRenderState + ", lightMode=" + lightMode + ", shadowMode=" + shadowMode + ", defineParams=" + defineParams + ", worldBinds=" + worldBinds + '}';
-    }    
+    }   
+
+    /**
+     * Returns the space in which the light data should be passed to the shader.
+     * @return the light space
+     */
+    public LightSpace getLightSpace() {
+        return lightSpace;
+    }
+
+    /**
+     * Sets the space in which the light data should be passed to the shader.
+     * @param lightSpace the light space
+     */
+    public void setLightSpace(LightSpace lightSpace) {
+        this.lightSpace = lightSpace;
+    }
+ 
 }