From b88350a069ee0af29373ed6aefcdf5f9db9ff297 Mon Sep 17 00:00:00 2001 From: "rem..om" Date: Sat, 24 Nov 2012 14:46:12 +0000 Subject: [PATCH] All shadow renderers/filters are now properly savables git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10005 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../jme3/shadow/AbstractShadowRenderer.java | 125 ++++++++++++------ .../shadow/DirectionalLightShadowFilter.java | 7 +- .../DirectionalLightShadowRenderer.java | 53 +++++++- .../jme3/shadow/PointLightShadowFilter.java | 13 +- .../jme3/shadow/PointLightShadowRenderer.java | 34 ++++- .../jme3/shadow/SpotLightShadowFilter.java | 26 ++-- .../jme3/shadow/SpotLightShadowRenderer.java | 47 ++++++- 7 files changed, 228 insertions(+), 77 deletions(-) diff --git a/engine/src/core/com/jme3/shadow/AbstractShadowRenderer.java b/engine/src/core/com/jme3/shadow/AbstractShadowRenderer.java index f3d306528..47e6b1fb4 100644 --- a/engine/src/core/com/jme3/shadow/AbstractShadowRenderer.java +++ b/engine/src/core/com/jme3/shadow/AbstractShadowRenderer.java @@ -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); + } } diff --git a/engine/src/core/com/jme3/shadow/DirectionalLightShadowFilter.java b/engine/src/core/com/jme3/shadow/DirectionalLightShadowFilter.java index e5bccf944..460cafa0c 100644 --- a/engine/src/core/com/jme3/shadow/DirectionalLightShadowFilter.java +++ b/engine/src/core/com/jme3/shadow/DirectionalLightShadowFilter.java @@ -57,8 +57,6 @@ import java.io.IOException; */ public class DirectionalLightShadowFilter extends AbstractShadowFilter { - - /** * Creates a DirectionalLightShadowFilter Shadow Filter More info on the * technique at http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html * * @param assetManager the application asset manager - * @param shadowMapSize the size of the rendered shadowmaps (512,1024,2048, etc...) + * @param shadowMapSize the size of the rendered shadowmaps (512,1024,2048, + * etc...) * @param nbSplits the number of shadow maps rendered (the more shadow maps * the more quality, the less fps). */ public DirectionalLightShadowRenderer(AssetManager assetManager, int shadowMapSize, int nbSplits) { super(assetManager, shadowMapSize, nbSplits); + init(nbSplits, shadowMapSize); + } + private void init(int nbSplits, int shadowMapSize) { nbShadowMaps = Math.max(Math.min(nbSplits, 4), 1); + if (nbShadowMaps != nbSplits) { + throw new IllegalArgumentException("Number of splits must be between 1 and 4. Given value : " + nbSplits); + } splits = new ColorRGBA(); splitsArray = new float[nbSplits + 1]; shadowCam = new Camera(shadowMapSize, shadowMapSize); shadowCam.setParallelProjection(true); - for (int i = 0; i < points.length; i++) { points[i] = new Vector3f(); } @@ -154,7 +172,7 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer { return shadowMapOccluders; } - + @Override GeometryList getReceivers(GeometryList sceneReceivers, GeometryList lightReceivers) { return sceneReceivers; @@ -163,7 +181,7 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer { @Override protected Camera getShadowCam(int shadowMapIndex) { return shadowCam; - } + } @Override protected void doDisplayFrustumDebug(int shadowMapIndex) { @@ -258,4 +276,27 @@ public class DirectionalLightShadowRenderer extends AbstractShadowRenderer { } return 0f; } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = (InputCapsule) im.getCapsule(this); + lambda = ic.readFloat("lambda", 0.65f); + zFarOverride = ic.readInt("zFarOverride", 0); + light = (DirectionalLight) ic.readSavable("light", null); + fadeInfo = (Vector2f) ic.readSavable("fadeInfo", null); + fadeLength = ic.readFloat("fadeLength", 0f); + init(nbShadowMaps, (int) shadowMapSize); + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = (OutputCapsule) ex.getCapsule(this); + oc.write(lambda, "lambda", 0.65f); + oc.write(zFarOverride, "zFarOverride", 0); + oc.write(light, "light", null); + oc.write(fadeInfo, "fadeInfo", null); + oc.write(fadeLength, "fadeLength", 0f); + } } diff --git a/engine/src/core/com/jme3/shadow/PointLightShadowFilter.java b/engine/src/core/com/jme3/shadow/PointLightShadowFilter.java index 8c89bbe80..82730860a 100644 --- a/engine/src/core/com/jme3/shadow/PointLightShadowFilter.java +++ b/engine/src/core/com/jme3/shadow/PointLightShadowFilter.java @@ -37,14 +37,6 @@ import com.jme3.export.JmeExporter; import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import com.jme3.light.PointLight; -import com.jme3.material.Material; -import com.jme3.math.Matrix4f; -import com.jme3.math.Vector4f; -import com.jme3.post.Filter; -import com.jme3.renderer.RenderManager; -import com.jme3.renderer.ViewPort; -import com.jme3.renderer.queue.RenderQueue; -import com.jme3.texture.FrameBuffer; import java.io.IOException; /** @@ -72,7 +64,7 @@ public class PointLightShadowFilter extends AbstractShadowFilter { - /** - * Creates a SpotLight Shadow Filter + * Creates a SpotLight Shadow Filter + * * @param assetManager the application asset manager * @param shadowMapSize the size of the rendered shadowmaps (512,1024,2048, - * etc...) - * the more quality, the less fps). + * etc...) the more quality, the less fps). */ public SpotLightShadowFilter(AssetManager assetManager, int shadowMapSize) { - super(assetManager, shadowMapSize, new SpotLightShadowRenderer(assetManager, shadowMapSize)); + super(assetManager, shadowMapSize, new SpotLightShadowRenderer(assetManager, shadowMapSize)); } /** @@ -131,6 +130,7 @@ public class SpotLightShadowFilter extends AbstractShadowFilter