/* * Copyright (c) 2009-2012 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'jMonkeyEngine' nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 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.material.Material; import com.jme3.math.Matrix4f; import com.jme3.math.Vector3f; 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.shadow.PssmShadowRenderer.CompareMode; import com.jme3.shadow.PssmShadowRenderer.FilterMode; import com.jme3.texture.FrameBuffer; import java.io.IOException; /** * * This Filter does basically the same as a PssmShadowRenderer except it renders * the post shadow pass as a fulscreen quad pass instead of a geometry pass. * It's mostly faster than PssmShadowRenderer as long as you have more than a about ten shadow recieving objects. * The expense is the draw back that the shadow Recieve mode set on spatial is ignored. * So basically all and only objects that render depth in the scene receive shadows. * See this post for more details http://jmonkeyengine.org/groups/general-2/forum/topic/silly-question-about-shadow-rendering/#post-191599 * * API is basically the same as the PssmShadowRenderer; * * @author Rémy Bouquet aka Nehon * @deprecated use {@link DirectionalLightShadowFilter} */ @Deprecated public class PssmShadowFilter extends Filter { private PssmShadowRenderer pssmRenderer; private ViewPort viewPort; /** * Creates a PSSM Shadow Filter * More info on the technique at <a href="http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html">http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html</a> * @param manager the application asset manager * @param size 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 PssmShadowFilter(AssetManager manager, int size, int nbSplits) { super("Post Shadow"); material = new Material(manager, "Common/MatDefs/Shadow/PostShadowFilter.j3md"); pssmRenderer = new PssmShadowRenderer(manager, size, nbSplits, material); pssmRenderer.needsfallBackMaterial = true; } @Override protected Material getMaterial() { return material; } @Override protected boolean isRequiresDepthTexture() { return true; } public Material getShadowMaterial() { return material; } Vector4f tmpv = new Vector4f(); @Override protected void preFrame(float tpf) { pssmRenderer.preFrame(tpf); material.setMatrix4("ViewProjectionMatrixInverse", viewPort.getCamera().getViewProjectionMatrix().invert()); Matrix4f m = viewPort.getCamera().getViewProjectionMatrix(); material.setVector4("ViewProjectionMatrixRow2", tmpv.set(m.m20, m.m21, m.m22, m.m23)); } @Override protected void postQueue(RenderQueue queue) { pssmRenderer.postQueue(queue); } @Override protected void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBuffer prevFilterBuffer, FrameBuffer sceneBuffer) { pssmRenderer.setPostShadowParams(); } @Override protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { pssmRenderer.initialize(renderManager, vp); this.viewPort = vp; } /** * returns the light direction used by the processor * @return */ public Vector3f getDirection() { return pssmRenderer.getDirection(); } /** * Sets the light direction to use to compute shadows * @param direction */ public void setDirection(Vector3f direction) { pssmRenderer.setDirection(direction); } /** * returns the lambda parameter * @see #setLambda(float lambda) * @return lambda */ public float getLambda() { return pssmRenderer.getLambda(); } /** * Adjust the repartition of the different shadow maps in the shadow extend * usualy goes from 0.0 to 1.0 * a low value give a more linear repartition resulting in a constant quality in the shadow over the extends, but near shadows could look very jagged * a high value give a more logarithmic repartition resulting in a high quality for near shadows, but the quality quickly decrease over the extend. * the default value is set to 0.65f (theoric optimal value). * @param lambda the lambda value. */ public void setLambda(float lambda) { pssmRenderer.setLambda(lambda); } /** * How far the shadows are rendered in the view * @see setShadowZExtend(float zFar) * @return shadowZExtend */ public float getShadowZExtend() { return pssmRenderer.getShadowZExtend(); } /** * Set the distance from the eye where the shadows will be rendered * default value is dynamically computed to the shadow casters/receivers union bound zFar, capped to view frustum far value. * @param zFar the zFar values that override the computed one */ public void setShadowZExtend(float zFar) { pssmRenderer.setShadowZExtend(zFar); } /** * returns the shadow intensity * @see #setShadowIntensity(float shadowIntensity) * @return shadowIntensity */ public float getShadowIntensity() { return pssmRenderer.getShadowIntensity(); } /** * Set the shadowIntensity, the value should be between 0 and 1, * a 0 value gives a bright and invisible shadow, * a 1 value gives a pitch black shadow, * default is 0.7 * @param shadowIntensity the darkness of the shadow */ final public void setShadowIntensity(float shadowIntensity) { pssmRenderer.setShadowIntensity(shadowIntensity); } /** * returns the edges thickness <br> * @see #setEdgesThickness(int edgesThickness) * @return edgesThickness */ public int getEdgesThickness() { return pssmRenderer.getEdgesThickness(); } /** * Sets the shadow edges thickness. default is 1, setting it to lower values can help to reduce the jagged effect of the shadow edges * @param edgesThickness */ public void setEdgesThickness(int edgesThickness) { pssmRenderer.setEdgesThickness(edgesThickness); } /** * returns true if the PssmRenderer flushed the shadow queues * @return flushQueues */ public boolean isFlushQueues() { return pssmRenderer.isFlushQueues(); } /** * Set this to false if you want to use several PssmRederers to have multiple shadows cast by multiple light sources. * Make sure the last PssmRenderer in the stack DO flush the queues, but not the others * @param flushQueues */ public void setFlushQueues(boolean flushQueues) { pssmRenderer.setFlushQueues(flushQueues); } /** * sets the shadow compare mode see {@link CompareMode} for more info * @param compareMode */ final public void setCompareMode(CompareMode compareMode) { pssmRenderer.setCompareMode(compareMode); } /** * Sets the filtering mode for shadow edges see {@link FilterMode} for more info * @param filterMode */ final public void setFilterMode(FilterMode filterMode) { pssmRenderer.setFilterMode(filterMode); } /** * Define the length over which the shadow will fade out when using a shadowZextend * @param length the fade length in world units */ public void setShadowZFadeLength(float length){ pssmRenderer.setShadowZFadeLength(length); } /** * get the length over which the shadow will fade out when using a shadowZextend * @return the fade length in world units */ public float getShadowZFadeLength(){ return pssmRenderer.getShadowZFadeLength(); } @Override public void write(JmeExporter ex) throws IOException { super.write(ex); OutputCapsule oc = ex.getCapsule(this); } @Override public void read(JmeImporter im) throws IOException { super.read(im); InputCapsule ic = im.getCapsule(this); } }