|
@@ -32,6 +32,11 @@
|
|
|
package com.jme3.shadow;
|
|
|
|
|
|
import com.jme3.asset.AssetManager;
|
|
|
+import com.jme3.export.InputCapsule;
|
|
|
+import com.jme3.export.JmeExporter;
|
|
|
+import com.jme3.export.JmeImporter;
|
|
|
+import com.jme3.export.OutputCapsule;
|
|
|
+import com.jme3.export.Savable;
|
|
|
import com.jme3.material.Material;
|
|
|
import com.jme3.math.ColorRGBA;
|
|
|
import com.jme3.math.Matrix4f;
|
|
@@ -49,7 +54,6 @@ import com.jme3.renderer.queue.RenderQueue.ShadowMode;
|
|
|
import com.jme3.scene.Geometry;
|
|
|
import com.jme3.scene.Spatial;
|
|
|
import com.jme3.scene.debug.WireFrustum;
|
|
|
-import com.jme3.shadow.PssmShadowRenderer.FilterMode;
|
|
|
import com.jme3.texture.FrameBuffer;
|
|
|
import com.jme3.texture.Image.Format;
|
|
|
import com.jme3.texture.Texture.MagFilter;
|
|
@@ -57,14 +61,17 @@ import com.jme3.texture.Texture.MinFilter;
|
|
|
import com.jme3.texture.Texture.ShadowCompareMode;
|
|
|
import com.jme3.texture.Texture2D;
|
|
|
import com.jme3.ui.Picture;
|
|
|
+import java.io.IOException;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
|
|
|
/**
|
|
|
- * abstract shadow renderer that holds commons feature to have for a shadow renderer
|
|
|
+ * abstract shadow renderer that holds commons feature to have for a shadow
|
|
|
+ * renderer
|
|
|
+ *
|
|
|
* @author Rémy Bouquet aka Nehon
|
|
|
*/
|
|
|
-public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
+public abstract class AbstractShadowRenderer implements SceneProcessor, Savable {
|
|
|
|
|
|
protected int nbShadowMaps = 1;
|
|
|
protected float shadowMapSize;
|
|
@@ -76,12 +83,12 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
protected Texture2D dummyTex;
|
|
|
protected Material preshadowMat;
|
|
|
protected Material postshadowMat;
|
|
|
- protected Matrix4f[] lightViewProjectionsMatrices;
|
|
|
+ protected Matrix4f[] lightViewProjectionsMatrices;
|
|
|
protected AssetManager assetManager;
|
|
|
protected boolean debug = false;
|
|
|
protected float edgesThickness = 1.0f;
|
|
|
- protected EdgeFilteringMode edgeFilteringMode;
|
|
|
- protected CompareMode shadowCompareMode;
|
|
|
+ protected EdgeFilteringMode edgeFilteringMode = EdgeFilteringMode.Bilinear;
|
|
|
+ protected CompareMode shadowCompareMode = CompareMode.Hardware;
|
|
|
protected Picture[] dispPic;
|
|
|
protected boolean flushQueues = true;
|
|
|
// define if the fallback material should be used.
|
|
@@ -95,8 +102,17 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
protected GeometryList lightReceivers = new GeometryList(new OpaqueComparator());
|
|
|
protected GeometryList shadowMapOccluders = new GeometryList(new OpaqueComparator());
|
|
|
|
|
|
+
|
|
|
+ /**
|
|
|
+ * used for serialization
|
|
|
+ */
|
|
|
+ protected AbstractShadowRenderer(){
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
- * Create an abstract shadow renderer, this is to be called in extending classes
|
|
|
+ * Create an abstract shadow renderer, this is to be called in extending
|
|
|
+ * classes
|
|
|
+ *
|
|
|
* @param assetManager the application asset manager
|
|
|
* @param shadowMapSize the size of the rendered shadowmaps (512,1024,2048,
|
|
|
* etc...)
|
|
@@ -106,9 +122,14 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
protected AbstractShadowRenderer(AssetManager assetManager, int shadowMapSize, int nbShadowMaps) {
|
|
|
|
|
|
this.assetManager = assetManager;
|
|
|
- this.postshadowMat = new Material(assetManager, "Common/MatDefs/Shadow/PostShadow.j3md");
|
|
|
this.nbShadowMaps = nbShadowMaps;
|
|
|
this.shadowMapSize = shadowMapSize;
|
|
|
+ init(assetManager, nbShadowMaps, shadowMapSize);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void init(AssetManager assetManager, int nbShadowMaps, int shadowMapSize) {
|
|
|
+ this.postshadowMat = new Material(assetManager, "Common/MatDefs/Shadow/PostShadow.j3md");
|
|
|
shadowFB = new FrameBuffer[nbShadowMaps];
|
|
|
shadowMaps = new Texture2D[nbShadowMaps];
|
|
|
dispPic = new Picture[nbShadowMaps];
|
|
@@ -137,15 +158,15 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
dispPic[i].setTexture(assetManager, shadowMaps[i], false);
|
|
|
}
|
|
|
|
|
|
- setShadowCompareMode(CompareMode.Hardware);
|
|
|
- setEdgeFilteringMode(EdgeFilteringMode.Bilinear);
|
|
|
- setShadowIntensity(0.7f);
|
|
|
-
|
|
|
+ setShadowCompareMode(shadowCompareMode);
|
|
|
+ setEdgeFilteringMode(edgeFilteringMode);
|
|
|
+ setShadowIntensity(shadowIntensity);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* set the post shadow material for this renderer
|
|
|
- * @param postShadowMat
|
|
|
+ *
|
|
|
+ * @param postShadowMat
|
|
|
*/
|
|
|
protected final void setPostShadowMaterial(Material postShadowMat) {
|
|
|
this.postshadowMat = postShadowMat;
|
|
@@ -159,10 +180,10 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Sets the filtering mode for shadow edges see {@link FilterMode} for more
|
|
|
- * info
|
|
|
+ * Sets the filtering mode for shadow edges see {@link EdgeFilteringMode}
|
|
|
+ * for more info
|
|
|
*
|
|
|
- * @param filterMode
|
|
|
+ * @param EdgeFilteringMode
|
|
|
*/
|
|
|
final public void setEdgeFilteringMode(EdgeFilteringMode filterMode) {
|
|
|
if (filterMode == null) {
|
|
@@ -206,11 +227,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
*/
|
|
|
final public void setShadowCompareMode(CompareMode compareMode) {
|
|
|
if (compareMode == null) {
|
|
|
- throw new NullPointerException();
|
|
|
- }
|
|
|
-
|
|
|
- if (this.shadowCompareMode == compareMode) {
|
|
|
- return;
|
|
|
+ throw new IllegalArgumentException("Shadow compare mode cannot be null");
|
|
|
}
|
|
|
|
|
|
this.shadowCompareMode = compareMode;
|
|
@@ -290,31 +307,38 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * This mehtod is called once per frame.
|
|
|
- * it is responsible for updating the shadow cams according to the light view.
|
|
|
+ * This mehtod is called once per frame. it is responsible for updating the
|
|
|
+ * shadow cams according to the light view.
|
|
|
+ *
|
|
|
* @param viewCam the scene cam
|
|
|
*/
|
|
|
protected abstract void updateShadowCams(Camera viewCam);
|
|
|
|
|
|
/**
|
|
|
- * this method must return the geomtryList that contains the oclluders to be rendered in the shadow map
|
|
|
+ * this method must return the geomtryList that contains the oclluders to be
|
|
|
+ * rendered in the shadow map
|
|
|
+ *
|
|
|
* @param shadowMapIndex the index of the shadow map being rendered
|
|
|
* @param sceneOccluders the occluders of the whole scene
|
|
|
* @param sceneReceivers the recievers of the whole scene
|
|
|
- * @return
|
|
|
+ * @return
|
|
|
*/
|
|
|
- protected abstract GeometryList getOccludersToRender(int shadowMapIndex, GeometryList sceneOccluders, GeometryList sceneReceivers,GeometryList shadowMapOccluders);
|
|
|
+ protected abstract GeometryList getOccludersToRender(int shadowMapIndex, GeometryList sceneOccluders, GeometryList sceneReceivers, GeometryList shadowMapOccluders);
|
|
|
|
|
|
/**
|
|
|
- * return the shadow camera to use for rendering the shadow map according the given index
|
|
|
+ * return the shadow camera to use for rendering the shadow map according
|
|
|
+ * the given index
|
|
|
+ *
|
|
|
* @param shadowMapIndex the index of the shadow map being rendered
|
|
|
* @return the shadowCam
|
|
|
*/
|
|
|
protected abstract Camera getShadowCam(int shadowMapIndex);
|
|
|
|
|
|
/**
|
|
|
- * responsible for displaying the frustum of the shadow cam for debug purpose
|
|
|
- * @param shadowMapIndex
|
|
|
+ * responsible for displaying the frustum of the shadow cam for debug
|
|
|
+ * purpose
|
|
|
+ *
|
|
|
+ * @param shadowMapIndex
|
|
|
*/
|
|
|
protected void doDisplayFrustumDebug(int shadowMapIndex) {
|
|
|
}
|
|
@@ -355,7 +379,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
}
|
|
|
|
|
|
protected void renderShadowMap(int shadowMapIndex, GeometryList occluders, GeometryList receivers) {
|
|
|
- shadowMapOccluders = getOccludersToRender(shadowMapIndex, occluders, receivers,shadowMapOccluders);
|
|
|
+ shadowMapOccluders = getOccludersToRender(shadowMapIndex, occluders, receivers, shadowMapOccluders);
|
|
|
Camera shadowCam = getShadowCam(shadowMapIndex);
|
|
|
|
|
|
//saving light view projection matrix for this split
|
|
@@ -396,7 +420,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
public void displayDebug() {
|
|
|
debug = true;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
abstract GeometryList getReceivers(GeometryList sceneReceivers, GeometryList lightReceivers);
|
|
|
|
|
|
public void postFrame(FrameBuffer out) {
|
|
@@ -404,10 +428,10 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
if (debug) {
|
|
|
displayShadowMap(renderManager.getRenderer());
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
lightReceivers = getReceivers(sceneReceivers, lightReceivers);
|
|
|
-
|
|
|
- if (lightReceivers.size()!=0) {
|
|
|
+
|
|
|
+ if (lightReceivers.size() != 0) {
|
|
|
//setting params to recieving geometry list
|
|
|
setMatParams();
|
|
|
|
|
@@ -422,7 +446,7 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
|
|
|
//rendering the post shadow pass
|
|
|
viewPort.getQueue().renderShadowQueue(lightReceivers, renderManager, cam, true);
|
|
|
- if(flushQueues){
|
|
|
+ if (flushQueues) {
|
|
|
sceneReceivers.clear();
|
|
|
}
|
|
|
|
|
@@ -436,8 +460,9 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * This method is called once per frame and is responsible of setting the material
|
|
|
- * parameters than sub class may need to set on the post material
|
|
|
+ * This method is called once per frame and is responsible of setting the
|
|
|
+ * material parameters than sub class may need to set on the post material
|
|
|
+ *
|
|
|
* @param material the materail to use for the post shadow pass
|
|
|
*/
|
|
|
protected abstract void setMaterialParameters(Material material);
|
|
@@ -571,4 +596,30 @@ public abstract class AbstractShadowRenderer implements SceneProcessor {
|
|
|
public void setFlushQueues(boolean flushQueues) {
|
|
|
this.flushQueues = flushQueues;
|
|
|
}
|
|
|
+
|
|
|
+ public void read(JmeImporter im) throws IOException {
|
|
|
+ InputCapsule ic = (InputCapsule) im.getCapsule(this);
|
|
|
+ assetManager = im.getAssetManager();
|
|
|
+ nbShadowMaps = ic.readInt("nbShadowMaps", 1);
|
|
|
+ shadowMapSize = ic.readInt("shadowMapSize", 0);
|
|
|
+ shadowIntensity = ic.readFloat("shadowIntensity", 0.7f);
|
|
|
+ edgeFilteringMode = ic.readEnum("edgeFilteringMode", EdgeFilteringMode.class, EdgeFilteringMode.Bilinear);
|
|
|
+ shadowCompareMode = ic.readEnum("shadowCompareMode", CompareMode.class, CompareMode.Hardware);
|
|
|
+ flushQueues = ic.readBoolean("flushQueues", false);
|
|
|
+ init(assetManager, nbShadowMaps, (int) shadowMapSize);
|
|
|
+ edgesThickness = ic.readFloat("edgesThickness", 1.0f);
|
|
|
+ postshadowMat.setFloat("PCFEdge", edgesThickness);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public void write(JmeExporter ex) throws IOException {
|
|
|
+ OutputCapsule oc = (OutputCapsule) ex.getCapsule(this);
|
|
|
+ oc.write(nbShadowMaps, "nbShadowMaps", 1);
|
|
|
+ oc.write(shadowMapSize, "shadowMapSize", 0);
|
|
|
+ oc.write(shadowIntensity, "shadowIntensity", 0.7f);
|
|
|
+ oc.write(edgeFilteringMode, "edgeFilteringMode", EdgeFilteringMode.Bilinear);
|
|
|
+ oc.write(shadowCompareMode, "shadowCompareMode", CompareMode.Hardware);
|
|
|
+ oc.write(flushQueues, "flushQueues", false);
|
|
|
+ oc.write(edgesThickness, "edgesThickness", 1.0f);
|
|
|
+ }
|
|
|
}
|