Browse Source

Make tech logic impls responsible for light filtering

Kirill Vainer 8 năm trước cách đây
mục cha
commit
f5ad0274b3

+ 19 - 30
jme3-core/src/main/java/com/jme3/material/Material.java

@@ -81,9 +81,9 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
     private AssetKey key;
     private String name;
     private MaterialDef def;
-    private ListMap<String, MatParam> paramValues = new ListMap<String, MatParam>();
+    private ListMap<String, MatParam> paramValues = new ListMap<>();
     private Technique technique;
-    private HashMap<String, Technique> techniques = new HashMap<String, Technique>();
+    private HashMap<String, Technique> techniques = new HashMap<>();
     private RenderState additionalState = null;
     private RenderState mergedRenderState = new RenderState();
     private boolean transparent = false;
@@ -143,10 +143,12 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
         this.name = name;
     }
 
+    @Override
     public void setKey(AssetKey key) {
         this.key = key;
     }
 
+    @Override
     public AssetKey getKey() {
         return key;
     }
@@ -200,9 +202,9 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
                 mat.additionalState = additionalState.clone();
             }
             mat.technique = null;
-            mat.techniques = new HashMap<String, Technique>();
+            mat.techniques = new HashMap<>();
 
-            mat.paramValues = new ListMap<String, MatParam>();
+            mat.paramValues = new ListMap<>();
             for (int i = 0; i < paramValues.size(); i++) {
                 Map.Entry<String, MatParam> entry = paramValues.getEntry(i);
                 mat.paramValues.put(entry.getKey(), entry.getValue().clone());
@@ -933,10 +935,9 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
      * </ul>
      *
      * @param geometry The geometry to render
-     * @param lights Presorted and filtered light list to use for rendering
      * @param renderManager The render manager requesting the rendering
      */
-    public void render(Geometry geometry, LightList lights, RenderManager renderManager) {
+    public void render(Geometry geometry, RenderManager renderManager) {
         if (technique == null) {
             selectTechnique(TechniqueDef.DEFAULT_TECHNIQUE_NAME, renderManager);
         }
@@ -956,7 +957,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
         SafeArrayList<MatParamOverride> overrides = geometry.getWorldMatParamOverrides();
 
         // Select shader to use
-        Shader shader = technique.makeCurrent(renderManager, overrides, renderManager.getForcedMatParams(), lights, rendererCaps);
+        Shader shader = technique.makeCurrent(renderManager, geometry, overrides, renderManager.getForcedMatParams(), rendererCaps);
         
         // Begin tracking which uniforms were changed by material.
         clearUniformsSetByCurrent(shader);
@@ -965,29 +966,24 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
         renderManager.updateUniformBindings(shader);
         
         // Set material parameters
-        int unit = updateShaderMaterialParameters(renderer, shader, overrides, renderManager.getForcedMatParams());
+        int nextTextureUnit = updateShaderMaterialParameters(renderer, shader, overrides, renderManager.getForcedMatParams());
 
         // Clear any uniforms not changed by material.
         resetUniformsNotSetByCurrent(shader);
         
         // Delegate rendering to the technique
-        technique.render(renderManager, shader, geometry, lights, unit);
+        technique.render(renderManager, shader, geometry, nextTextureUnit);
     }
 
-    /**
-     * Called by {@link RenderManager} to render the geometry by
-     * using this material.
-     *
-     * Note that this version of the render method
-     * does not perform light filtering.
-     *
-     * @param geom The geometry to render
-     * @param rm The render manager requesting the rendering
-     */
-    public void render(Geometry geom, RenderManager rm) {
-        render(geom, geom.getWorldLightList(), rm);
+    @Override
+    public String toString() {
+        return "Material[name=" + name + 
+                ", def=" + (def != null ? def.getName() : null) + 
+                ", tech=" + (technique != null && technique.getDef() != null ? technique.getDef().getName() : null) + 
+                "]";
     }
-
+    
+    @Override
     public void write(JmeExporter ex) throws IOException {
         OutputCapsule oc = ex.getCapsule(this);
         oc.write(def.getAssetName(), "material_def", null);
@@ -998,13 +994,6 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
     }
     
     @Override
-    public String toString() {
-        return "Material[name=" + name + 
-                ", def=" + (def != null ? def.getName() : null) + 
-                ", tech=" + (technique != null && technique.getDef() != null ? technique.getDef().getName() : null) + 
-                "]";
-    }
-
     public void read(JmeImporter im) throws IOException {
         InputCapsule ic = im.getCapsule(this);
 
@@ -1054,7 +1043,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
         }
 
         def = (MaterialDef) im.getAssetManager().loadAsset(new AssetKey(defName));
-        paramValues = new ListMap<String, MatParam>();
+        paramValues = new ListMap<>();
 
         // load the textures and update nextTexUnit
         for (Map.Entry<String, MatParam> entry : params.entrySet()) {

+ 6 - 5
jme3-core/src/main/java/com/jme3/material/Technique.java

@@ -133,9 +133,10 @@ public final class Technique {
      * @param rendererCaps The renderer capabilities which the shader should support.
      * @return A compatible shader.
      */
-    Shader makeCurrent(RenderManager renderManager, SafeArrayList<MatParamOverride> worldOverrides,
+    Shader makeCurrent(RenderManager renderManager, Geometry geometry,
+            SafeArrayList<MatParamOverride> worldOverrides,
             SafeArrayList<MatParamOverride> forcedOverrides,
-            LightList lights, EnumSet<Caps> rendererCaps) {
+            EnumSet<Caps> rendererCaps) {
         TechniqueDefLogic logic = def.getLogic();
         AssetManager assetManager = owner.getMaterialDef().getAssetManager();
 
@@ -149,7 +150,7 @@ public final class Technique {
             applyOverrides(dynamicDefines, forcedOverrides);
         }
 
-        return logic.makeCurrent(assetManager, renderManager, rendererCaps, lights, dynamicDefines);
+        return logic.makeCurrent(assetManager, renderManager, rendererCaps, geometry, dynamicDefines);
     }
     
     /**
@@ -161,9 +162,9 @@ public final class Technique {
      * @param geometry The geometry to render
      * @param lights Lights which influence the geometry.
      */
-    void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
+    void render(RenderManager renderManager, Shader shader, Geometry geometry, int lastTextureUnit) {
         TechniqueDefLogic logic = def.getLogic();
-        logic.render(renderManager, shader, geometry, lights, lastTexUnit);
+        logic.render(renderManager, shader, geometry, lastTextureUnit);
     }
     
     /**

+ 15 - 10
jme3-core/src/main/java/com/jme3/material/logic/DefaultTechniqueDefLogic.java

@@ -48,6 +48,7 @@ import java.util.EnumSet;
 public class DefaultTechniqueDefLogic implements TechniqueDefLogic {
 
     protected final TechniqueDef techniqueDef;
+    protected final LightList filteredLightList = new LightList(null);
 
     public DefaultTechniqueDefLogic(TechniqueDef techniqueDef) {
         this.techniqueDef = techniqueDef;
@@ -55,7 +56,7 @@ public class DefaultTechniqueDefLogic implements TechniqueDefLogic {
 
     @Override
     public Shader makeCurrent(AssetManager assetManager, RenderManager renderManager,
-            EnumSet<Caps> rendererCaps, LightList lights, DefineList defines) {
+            EnumSet<Caps> rendererCaps, Geometry geometry, DefineList defines) {
         return techniqueDef.getShader(assetManager, rendererCaps, defines);
     }
 
@@ -70,6 +71,19 @@ public class DefaultTechniqueDefLogic implements TechniqueDefLogic {
             renderer.renderMesh(mesh, lodLevel, 1, null);
         }
     }
+    
+    @Override
+    public void render(RenderManager renderManager, Shader shader, Geometry geometry, int lastTexUnit) {
+        Renderer renderer = renderManager.getRenderer();
+        renderer.setShader(shader);
+        renderMeshFromGeometry(renderer, geometry);
+    }
+    
+    protected LightList getFilteredLightList(RenderManager renderManager, Geometry geom) {
+        filteredLightList.clear();
+        renderManager.getLightFilter().filterLights(geom, filteredLightList);
+        return filteredLightList;
+    }
 
     protected static ColorRGBA getAmbientColor(LightList lightList, boolean removeLights, ColorRGBA ambientLightColor) {
         ambientLightColor.set(0, 0, 0, 1);
@@ -85,13 +99,4 @@ public class DefaultTechniqueDefLogic implements TechniqueDefLogic {
         ambientLightColor.a = 1.0f;
         return ambientLightColor;
     }
-
-
-
-    @Override
-    public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
-        Renderer renderer = renderManager.getRenderer();
-        renderer.setShader(shader);
-        renderMeshFromGeometry(renderer, geometry);
-    }
 }

+ 2 - 6
jme3-core/src/main/java/com/jme3/material/logic/MultiPassLightingLogic.java

@@ -31,7 +31,6 @@
  */
 package com.jme3.material.logic;
 
-import com.jme3.asset.AssetManager;
 import com.jme3.light.AmbientLight;
 import com.jme3.light.DirectionalLight;
 import com.jme3.light.Light;
@@ -41,20 +40,16 @@ import com.jme3.light.SpotLight;
 import com.jme3.material.RenderState;
 import com.jme3.material.TechniqueDef;
 import com.jme3.math.ColorRGBA;
-import com.jme3.math.FastMath;
 import com.jme3.math.Quaternion;
 import com.jme3.math.Vector3f;
 import com.jme3.math.Vector4f;
-import com.jme3.renderer.Caps;
 import com.jme3.renderer.RenderManager;
 import com.jme3.renderer.Renderer;
 import com.jme3.scene.Geometry;
-import com.jme3.shader.DefineList;
 import com.jme3.shader.Shader;
 import com.jme3.shader.Uniform;
 import com.jme3.shader.VarType;
 import com.jme3.util.TempVars;
-import java.util.EnumSet;
 
 public final class MultiPassLightingLogic extends DefaultTechniqueDefLogic {
 
@@ -73,7 +68,7 @@ public final class MultiPassLightingLogic extends DefaultTechniqueDefLogic {
     }
 
     @Override
-    public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
+    public void render(RenderManager renderManager, Shader shader, Geometry geometry, int lastTexUnit) {
         Renderer r = renderManager.getRenderer();
         Uniform lightDir = shader.getUniform("g_LightDirection");
         Uniform lightColor = shader.getUniform("g_LightColor");
@@ -82,6 +77,7 @@ public final class MultiPassLightingLogic extends DefaultTechniqueDefLogic {
         boolean isFirstLight = true;
         boolean isSecondLight = false;
         
+        LightList lights = getFilteredLightList(renderManager, geometry);
         getAmbientColor(lights, false, ambientLightColor);
 
         for (int i = 0; i < lights.size(); i++) {

+ 12 - 9
jme3-core/src/main/java/com/jme3/material/logic/SinglePassAndImageBasedLightingLogic.java

@@ -72,15 +72,18 @@ public final class SinglePassAndImageBasedLightingLogic extends DefaultTechnique
 
     @Override
     public Shader makeCurrent(AssetManager assetManager, RenderManager renderManager,
-            EnumSet<Caps> rendererCaps, LightList lights, DefineList defines) {
+            EnumSet<Caps> rendererCaps, Geometry geometry, DefineList defines) {
         defines.set(nbLightsDefineId, renderManager.getSinglePassLightBatchSize() * 3);
         defines.set(singlePassLightingDefineId, true);
 
-
-        //TODO here we have a problem, this is called once before render, so the define will be set for all passes (in case we have more than NB_LIGHTS lights)
-        //Though the second pass should not render IBL as it is taken care of on first pass like ambient light in phong lighting.
-        //We cannot change the define between passes and the old technique, and for some reason the code fails on mac (renders nothing).
-        if(lights != null) {
+        // TODO: here we have a problem, this is called once before render, 
+        // so the define will be set for all passes (in case we have more than NB_LIGHTS lights)
+        // Though the second pass should not render IBL as it is taken care of on 
+        // first pass like ambient light in phong lighting.
+        // We cannot change the define between passes and the old technique, and 
+        // for some reason the code fails on mac (renders nothing).
+        LightList lights = getFilteredLightList(renderManager, geometry);
+        if (lights != null) {
             lightProbe = extractIndirectLights(lights, false);
             if (lightProbe == null) {
                 defines.set(indirectLightingDefineId, false);
@@ -89,7 +92,7 @@ public final class SinglePassAndImageBasedLightingLogic extends DefaultTechnique
             }
         }
 
-        return super.makeCurrent(assetManager, renderManager, rendererCaps, lights, defines);
+        return super.makeCurrent(assetManager, renderManager, rendererCaps, geometry, defines);
     }
 
     /**
@@ -224,10 +227,11 @@ public final class SinglePassAndImageBasedLightingLogic extends DefaultTechnique
     }
 
     @Override
-    public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
+    public void render(RenderManager renderManager, Shader shader, Geometry geometry, int lastTexUnit) {
         int nbRenderedLights = 0;
         Renderer renderer = renderManager.getRenderer();
         int batchSize = renderManager.getSinglePassLightBatchSize();
+        LightList lights = getFilteredLightList(renderManager, geometry);
         if (lights.size() == 0) {
             updateLightListUniforms(shader, geometry, lights,batchSize, renderManager, 0, lastTexUnit);
             renderer.setShader(shader);
@@ -239,7 +243,6 @@ public final class SinglePassAndImageBasedLightingLogic extends DefaultTechnique
                 renderMeshFromGeometry(renderer, geometry);
             }
         }
-        return;
     }
 
     protected LightProbe extractIndirectLights(LightList lightList, boolean removeLights) {

+ 20 - 13
jme3-core/src/main/java/com/jme3/material/logic/SinglePassLightingLogic.java

@@ -77,25 +77,31 @@ public final class SinglePassLightingLogic extends DefaultTechniqueDefLogic {
     }
 
     @Override
-    public Shader makeCurrent(AssetManager assetManager, RenderManager renderManager,
-            EnumSet<Caps> rendererCaps, LightList lights, DefineList defines) {
+    public Shader makeCurrent(
+            AssetManager assetManager, 
+            RenderManager renderManager,
+            EnumSet<Caps> rendererCaps, 
+            Geometry geometry,
+            DefineList defines) {
         defines.set(nbLightsDefineId, renderManager.getSinglePassLightBatchSize() * 3);
         defines.set(singlePassLightingDefineId, true);
-        return super.makeCurrent(assetManager, renderManager, rendererCaps, lights, defines);
+        return super.makeCurrent(assetManager, renderManager, rendererCaps, geometry, defines);
     }
 
     /**
-     * Uploads the lights in the light list as two uniform arrays.<br/><br/> *
+     * Uploads the lights in the light list as two uniform arrays.<br><br>
+     *
      * <p>
-     * <code>uniform vec4 g_LightColor[numLights];</code><br/> //
-     * g_LightColor.rgb is the diffuse/specular color of the light.<br/> //
-     * g_Lightcolor.a is the type of light, 0 = Directional, 1 = Point, <br/> //
-     * 2 = Spot. <br/> <br/>
-     * <code>uniform vec4 g_LightPosition[numLights];</code><br/> //
-     * g_LightPosition.xyz is the position of the light (for point lights)<br/>
-     * // or the direction of the light (for directional lights).<br/> //
+     * <code>uniform vec4 g_LightColor[numLights];</code><br>
+     * g_LightColor.rgb is the diffuse/specular color of the light.<br>
+     * g_Lightcolor.a is the type of light, 0 = Directional, 1 = Point, <br>
+     * 2 = Spot. <br> <br>
+     * <code>uniform vec4 g_LightPosition[numLights];</code><br>
+     * g_LightPosition.xyz is the position of the light (for point lights)<br>
+     * // or the direction of the light (for directional lights).<br>
      * g_LightPosition.w is the inverse radius (1/r) of the light (for
-     * attenuation) <br/> </p>
+     * attenuation) <br>
+     * </p>
      */
     protected int updateLightListUniforms(Shader shader, Geometry g, LightList lightList, int numLights, RenderManager rm, int startIndex) {
         if (numLights == 0) { // this shader does not do lighting, ignore.
@@ -201,10 +207,11 @@ public final class SinglePassLightingLogic extends DefaultTechniqueDefLogic {
     }
 
     @Override
-    public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) {
+    public void render(RenderManager renderManager, Shader shader, Geometry geometry, int lastTexUnit) {
         int nbRenderedLights = 0;
         Renderer renderer = renderManager.getRenderer();
         int batchSize = renderManager.getSinglePassLightBatchSize();
+        LightList lights = getFilteredLightList(renderManager, geometry);
         if (lights.size() == 0) {
             updateLightListUniforms(shader, geometry, lights, batchSize, renderManager, 0);
             renderer.setShader(shader);

+ 9 - 8
jme3-core/src/main/java/com/jme3/material/logic/TechniqueDefLogic.java

@@ -32,7 +32,9 @@
 package com.jme3.material.logic;
 
 import com.jme3.asset.AssetManager;
-import com.jme3.light.LightList;
+import com.jme3.material.MatParam;
+import com.jme3.material.RenderState;
+import com.jme3.material.TechniqueDef;
 import com.jme3.material.TechniqueDef.LightMode;
 import com.jme3.renderer.Caps;
 import com.jme3.renderer.RenderManager;
@@ -63,19 +65,18 @@ public interface TechniqueDefLogic {
      * 
      * @param assetManager The asset manager to use for loading shader source code,
      * shader nodes, and and lookup textures.
+     * @param geometry The geometry being rendered
      * @param renderManager The render manager for which rendering is to be performed.
      * @param rendererCaps Renderer capabilities. The returned shader must
      * support these capabilities.
-     * @param lights The lights with which the geometry shall be rendered. This
-     * list must not include culled lights.
      * @param defines The define list used by the technique, any 
      * {@link TechniqueDef#addShaderUnmappedDefine(java.lang.String) unmapped defines}
      * should be set here to change shader behavior.
      * 
      * @return The shader to use for rendering.
      */
-    public Shader makeCurrent(AssetManager assetManager, RenderManager renderManager, 
-            EnumSet<Caps> rendererCaps, LightList lights, DefineList defines);
+    public Shader makeCurrent(AssetManager assetManager, RenderManager renderManager,
+            EnumSet<Caps> rendererCaps, Geometry geometry, DefineList defines);
     
     /**
      * Requests that the <code>TechniqueDefLogic</code> renders the given geometry.
@@ -88,10 +89,10 @@ public interface TechniqueDefLogic {
      * can still be overriden.
      * 
      * @param renderManager The render manager to perform the rendering against.
-     * * @param shader The shader that was selected by this logic in 
+     * @param shader The shader that was selected by this logic in 
      * {@link #makeCurrent(com.jme3.asset.AssetManager, com.jme3.renderer.RenderManager, java.util.EnumSet, com.jme3.shader.DefineList)}.
      * @param geometry The geometry to render
-     * @param lights Lights which influence the geometry.
+     * @param lastTextureUnit The last unused texture unit
      */
-    public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit);
+    public void render(RenderManager renderManager, Shader shader, Geometry geometry, int lastTextureUnit);
 }

+ 4 - 14
jme3-core/src/main/java/com/jme3/renderer/RenderManager.java

@@ -84,7 +84,6 @@ public class RenderManager {
     private final SafeArrayList<MatParamOverride> forcedOverrides = new SafeArrayList<>(MatParamOverride.class);
     private int viewX, viewY, viewWidth, viewHeight;
     private final Matrix4f orthoMatrix = new Matrix4f();
-    private final LightList filteredLightList = new LightList(null);
     private boolean handleTranlucentBucket = true;
     private AppProfiler prof;
     private LightFilter lightFilter = new DefaultLightFilter();
@@ -562,15 +561,6 @@ public class RenderManager {
         } else {
             setWorldMatrix(geom.getWorldMatrix());
         }
-        
-        // Perform light filtering if we have a light filter.
-        LightList lightList = geom.getWorldLightList();
-        
-        if (lightFilter != null) {
-            filteredLightList.clear();
-            lightFilter.filterLights(geom, filteredLightList);
-            lightList = filteredLightList;
-        }
 
         Material material = geom.getMaterial();
 
@@ -595,7 +585,7 @@ public class RenderManager {
                     forcedRenderState = geom.getMaterial().getActiveTechnique().getDef().getForcedRenderState();
                 }
                 // use geometry's material
-                material.render(geom, lightList, this);
+                material.render(geom, this);
                 material.selectTechnique(previousTechniqueName, this);
 
                 //restoring forcedRenderState
@@ -605,13 +595,13 @@ public class RenderManager {
                 //If forcedTechnique does not exists, and forcedMaterial is not set, the geom MUST NOT be rendered
             } else if (forcedMaterial != null) {
                 // use forced material
-                forcedMaterial.render(geom, lightList, this);
+                forcedMaterial.render(geom, this);
             }
         } else if (forcedMaterial != null) {
             // use forced material
-            forcedMaterial.render(geom, lightList, this);
+            forcedMaterial.render(geom, this);
         } else {
-            material.render(geom, lightList, this);
+            material.render(geom, this);
         }
     }
 

+ 1 - 2
jme3-core/src/test/java/com/jme3/material/MaterialMatParamTest.java

@@ -430,7 +430,6 @@ public class MaterialMatParamTest {
 
     private final Geometry geometry = new Geometry("Geometry", new Box(1, 1, 1));
     private final Node root = new Node("Root Node");
-    private final LightList lightList = new LightList(geometry);
 
     @Before
     public void setUp() {
@@ -526,7 +525,7 @@ public class MaterialMatParamTest {
     private void evaluateTechniqueDef() {
         Assert.assertFalse(evaluated);
         Material mat = geometry.getMaterial();
-        mat.render(geometry, lightList, renderManager);
+        mat.render(geometry, renderManager);
         Assert.assertTrue(evaluated);
     }