From 9c4fcac8769d7d02f0ec116d5a0422397c341505 Mon Sep 17 00:00:00 2001 From: Kirill Vainer Date: Sat, 9 Sep 2017 16:31:39 -0400 Subject: [PATCH] Add PreShadowArrayRenderer --- .../logic/ShadowStaticPassLightingLogic.java | 191 ++++++++++++++ .../shadow/next/PreShadowArrayRenderer.java | 248 ++++++++++++++++++ .../jme3/shadow/next/ShadowParameters.java | 38 +++ .../shadow/next/array/ArrayShadowMap.java | 47 ++++ .../next/array/ArrayShadowMapSlice.java | 41 +++ .../shadow/next/array/BaseArrayShadowMap.java | 75 ++++++ .../next/array/BaseArrayShadowMapSlice.java | 85 ++++++ .../next/array/DirectionalArrayShadowMap.java | 82 ++++++ .../array/DirectionalArrayShadowMapSlice.java | 66 +++++ .../shadow/next/array/SpotArrayShadowMap.java | 68 +++++ .../next/array/SpotArrayShadowMapSlice.java | 72 +++++ .../pssm/DirectionalShadowParameters.java | 138 ++++++++++ 12 files changed, 1151 insertions(+) create mode 100755 jme3-core/src/main/java/com/jme3/material/logic/ShadowStaticPassLightingLogic.java create mode 100755 jme3-core/src/main/java/com/jme3/shadow/next/PreShadowArrayRenderer.java create mode 100755 jme3-core/src/main/java/com/jme3/shadow/next/ShadowParameters.java create mode 100755 jme3-core/src/main/java/com/jme3/shadow/next/array/ArrayShadowMap.java create mode 100755 jme3-core/src/main/java/com/jme3/shadow/next/array/ArrayShadowMapSlice.java create mode 100755 jme3-core/src/main/java/com/jme3/shadow/next/array/BaseArrayShadowMap.java create mode 100755 jme3-core/src/main/java/com/jme3/shadow/next/array/BaseArrayShadowMapSlice.java create mode 100755 jme3-core/src/main/java/com/jme3/shadow/next/array/DirectionalArrayShadowMap.java create mode 100755 jme3-core/src/main/java/com/jme3/shadow/next/array/DirectionalArrayShadowMapSlice.java create mode 100755 jme3-core/src/main/java/com/jme3/shadow/next/array/SpotArrayShadowMap.java create mode 100755 jme3-core/src/main/java/com/jme3/shadow/next/array/SpotArrayShadowMapSlice.java create mode 100755 jme3-core/src/main/java/com/jme3/shadow/next/pssm/DirectionalShadowParameters.java diff --git a/jme3-core/src/main/java/com/jme3/material/logic/ShadowStaticPassLightingLogic.java b/jme3-core/src/main/java/com/jme3/material/logic/ShadowStaticPassLightingLogic.java new file mode 100755 index 000000000..54fad0f0f --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/material/logic/ShadowStaticPassLightingLogic.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2009-2016 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.material.logic; + +import com.jme3.asset.AssetManager; +import com.jme3.light.DirectionalLight; +import com.jme3.light.Light; +import com.jme3.light.LightList; +import com.jme3.light.PointLight; +import com.jme3.light.SpotLight; +import com.jme3.material.TechniqueDef; +import com.jme3.math.Matrix4f; +import com.jme3.math.Vector4f; +import com.jme3.renderer.Caps; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.Renderer; +import com.jme3.shader.DefineList; +import com.jme3.shader.Shader; +import com.jme3.shader.Uniform; +import com.jme3.shader.VarType; +import com.jme3.shadow.next.array.ArrayShadowMap; +import com.jme3.shadow.next.array.ArrayShadowMapSlice; +import com.jme3.shadow.next.array.DirectionalArrayShadowMap; +import com.jme3.shadow.next.array.SpotArrayShadowMap; +import com.jme3.shadow.next.array.SpotArrayShadowMapSlice; +import com.jme3.texture.TextureArray; +import java.util.EnumSet; + +public class ShadowStaticPassLightingLogic extends StaticPassLightingLogic { + + private static final String DEFINE_NUM_PSSM_SPLITS = "NUM_PSSM_SPLITS"; + private static final String DEFINE_NUM_SHADOW_DIR_LIGHTS = "NUM_SHADOW_DIR_LIGHTS"; + private static final String DEFINE_NUM_SHADOW_POINT_LIGHTS = "NUM_SHADOW_POINT_LIGHTS"; + private static final String DEFINE_NUM_SHADOW_SPOT_LIGHTS = "NUM_SHADOW_SPOT_LIGHTS"; + + private final int numPssmSplitsDefineId; + private final int numShadowDirLightsDefineId; + private final int numShadowPointLightsDefineId; + private final int numShadowSpotLightsDefineId; + private int numShadowDirLights = 0; + private int numShadowPointLights = 0; + private int numShadowSpotLights = 0; + private final Matrix4f[] shadowMatrices = new Matrix4f[5]; + + public ShadowStaticPassLightingLogic(TechniqueDef techniqueDef) { + super(techniqueDef); + numPssmSplitsDefineId = techniqueDef.addShaderUnmappedDefine(DEFINE_NUM_PSSM_SPLITS, VarType.Int); + numShadowDirLightsDefineId = techniqueDef.addShaderUnmappedDefine(DEFINE_NUM_SHADOW_DIR_LIGHTS, VarType.Int); + numShadowPointLightsDefineId = techniqueDef.addShaderUnmappedDefine(DEFINE_NUM_SHADOW_POINT_LIGHTS, VarType.Int); + numShadowSpotLightsDefineId = techniqueDef.addShaderUnmappedDefine(DEFINE_NUM_SHADOW_SPOT_LIGHTS, VarType.Int); + + for (int i = 0; i < shadowMatrices.length; i++) { + shadowMatrices[i] = new Matrix4f(); + } + } + + @Override + protected void makeCurrentBase(AssetManager assetManager, RenderManager renderManager, + EnumSet rendererCaps, LightList lights, DefineList defines) { + + tempDirLights.clear(); + tempPointLights.clear(); + tempSpotLights.clear(); + ambientLightColor.set(0, 0, 0, 1); + numShadowDirLights = 0; + numShadowPointLights = 0; + numShadowSpotLights = 0; + + int pssmSplits = 0; + + for (Light light : lights) { + switch (light.getType()) { + case Directional: + if (light.getShadowMap() != null) { + pssmSplits = light.getShadowMap().getNumSlices(); + tempDirLights.add(numShadowDirLights, (DirectionalLight) light); + numShadowDirLights++; + } else { + tempDirLights.add((DirectionalLight) light); + } + break; + case Point: + if (light.getShadowMap() != null) { + tempPointLights.add(numShadowPointLights, (PointLight) light); + numShadowPointLights++; + } else { + tempPointLights.add((PointLight) light); + } + break; + case Spot: + if (light.getShadowMap() != null) { + tempSpotLights.add(numShadowSpotLights, (SpotLight) light); + numShadowSpotLights++; + } else { + tempSpotLights.add((SpotLight) light); + } + break; + case Ambient: + ambientLightColor.addLocal(light.getColor()); + break; + } + } + ambientLightColor.a = 1.0f; + + defines.set(numDirLightsDefineId, tempDirLights.size()); + defines.set(numPointLightsDefineId, tempPointLights.size()); + defines.set(numSpotLightsDefineId, tempSpotLights.size()); + + defines.set(numShadowDirLightsDefineId, numShadowDirLights); + defines.set(numShadowPointLightsDefineId, numShadowPointLights); + defines.set(numShadowSpotLightsDefineId, numShadowSpotLights); + + defines.set(numPssmSplitsDefineId, pssmSplits); + } + + @Override + protected float getShadowMapIndex(Light light) { + if (light.getShadowMap() == null) { + return -1.0f; + } + ArrayShadowMap map = (ArrayShadowMap) light.getShadowMap(); + return (float) map.getFirstArraySlice(); + } + + @Override + protected void updateShadowUniforms(Renderer renderer, Shader shader, int nextTextureUnit) { + TextureArray array = null; + Vector4f pssmSplits = null; + + Uniform shadowMatricesUniform = shader.getUniform("g_ShadowMatrices"); + int shadowMatrixIndex = 0; + for (int i = 0; i < numShadowDirLights; i++) { + DirectionalArrayShadowMap map = (DirectionalArrayShadowMap) tempDirLights.get(i).getShadowMap(); + array = map.getArray(); + pssmSplits = map.getProjectionSplitPositions(); + for (int j = 0; j < map.getNumSlices(); j++) { + ArrayShadowMapSlice slice = (ArrayShadowMapSlice) map.getSlice(j); + BIAS_MATRIX.mult(slice.getViewProjectionMatrix(), shadowMatrices[shadowMatrixIndex]); + shadowMatrixIndex++; + } + } + + for (int i = 0; i < numShadowSpotLights; i++) { + SpotArrayShadowMap map = (SpotArrayShadowMap) tempSpotLights.get(i).getShadowMap(); + array = map.getArray(); + SpotArrayShadowMapSlice slice = map.getSlice(0); + BIAS_MATRIX.mult(slice.getViewProjectionMatrix(), shadowMatrices[shadowMatrixIndex]); + shadowMatrixIndex++; + } + + shadowMatricesUniform.setValue(VarType.Matrix4Array, shadowMatrices); + if (array != null) { + renderer.setTexture(nextTextureUnit, array); + Uniform shadowMapArrayUniform = shader.getUniform("g_ShadowMapArray"); + shadowMapArrayUniform.setValue(VarType.Int, nextTextureUnit); + } + if (pssmSplits != null) { + Uniform pssmSplitsUniform = shader.getUniform("g_PssmSplits"); + pssmSplitsUniform.setValue(VarType.Vector4, pssmSplits); + } + } +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/PreShadowArrayRenderer.java b/jme3-core/src/main/java/com/jme3/shadow/next/PreShadowArrayRenderer.java new file mode 100755 index 000000000..fd9bd6e58 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/PreShadowArrayRenderer.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2009-2016 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.next; + +import com.jme3.shadow.next.pssm.DirectionalShadowParameters; +import com.jme3.light.DirectionalLight; +import com.jme3.light.Light; +import com.jme3.light.SpotLight; +import com.jme3.material.RenderState; +import com.jme3.math.Vector3f; +import com.jme3.post.SceneProcessor; +import com.jme3.profile.AppProfiler; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.Renderer; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.GeometryList; +import com.jme3.renderer.queue.OpaqueComparator; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.shadow.next.array.DirectionalArrayShadowMap; +import com.jme3.shadow.next.array.SpotArrayShadowMap; +import com.jme3.texture.FrameBuffer; +import com.jme3.texture.Image; +import com.jme3.texture.Image.Format; +import com.jme3.texture.Texture.MagFilter; +import com.jme3.texture.Texture.MinFilter; +import com.jme3.texture.Texture.ShadowCompareMode; +import com.jme3.texture.TextureArray; +import com.jme3.texture.image.ColorSpace; +import com.jme3.util.ListMap; +import com.jme3.util.TempVars; +import java.nio.ByteBuffer; +import java.util.ArrayList; + +/** + * The 4th generation of shadow mapping in jME3. + *

+ * This version is primarily focused on rendering in-pass shadows, so pre-pass + * and subsequent stages are separated. + * + * @author Kirill Vainer + */ +public class PreShadowArrayRenderer implements SceneProcessor { + + private static final String PRE_SHADOW_TECHNIQUE_NAME = "PreShadow"; + + private RenderManager renderManager; + private ViewPort viewPort; + private final Vector3f[] points = new Vector3f[8]; + private final GeometryList shadowCasters = new GeometryList(new OpaqueComparator()); + private final ListMap shadowedLights = new ListMap<>(); + private final RenderState prePassRenderState = RenderState.ADDITIONAL.clone(); + private final TextureArray array = new TextureArray(); + + private int textureSize = 1024; + private int nextArraySlice = 0; + + // parameters for directional lights + private final DirectionalShadowParameters directionalParams = new DirectionalShadowParameters(); + + public PreShadowArrayRenderer() { + for (int i = 0; i < points.length; i++) { + points[i] = new Vector3f(); + } + + prePassRenderState.setFaceCullMode(RenderState.FaceCullMode.Front); + prePassRenderState.setColorWrite(false); + prePassRenderState.setDepthWrite(true); + prePassRenderState.setDepthTest(true); + prePassRenderState.setPolyOffset(0, 0); + + array.setAnisotropicFilter(1); + array.setShadowCompareMode(ShadowCompareMode.LessOrEqual); + array.setMagFilter(MagFilter.Nearest); + array.setMinFilter(MinFilter.NearestNoMipMaps); + + array.setMagFilter(MagFilter.Bilinear); + array.setMinFilter(MinFilter.BilinearNoMipMaps); + } + + @Override + public void initialize(RenderManager rm, ViewPort vp) { + this.renderManager = rm; + this.viewPort = vp; + } + + public DirectionalShadowParameters directional() { + return directionalParams; + } + + public void setPolyOffset(float factor, float units) { + prePassRenderState.setPolyOffset(factor, units); + } + + public int getTextureSize() { + return textureSize; + } + + public void setTextureSize(int textureSize) { + // TODO: support changing texture size after shadow maps are created + this.textureSize = textureSize; + } + + public void addLight(Light light) { + if (array.getImage() == null) { + array.setImage(new Image( + Format.Depth32F, + textureSize, + textureSize, + 0, + new ArrayList(), + ColorSpace.Linear)); + } + + ShadowMap shadowMap; + switch (light.getType()) { + case Directional: + shadowMap = new DirectionalArrayShadowMap( + (DirectionalLight) light, + array, + nextArraySlice, + textureSize, + directionalParams.getNumSplits(), + points); + break; + case Spot: + shadowMap = new SpotArrayShadowMap( + (SpotLight) light, + array, + nextArraySlice, + textureSize, + points); + break; + default: + throw new UnsupportedOperationException(); + } + + shadowedLights.put(light, shadowMap); + nextArraySlice += shadowMap.getNumSlices(); + } + + @Override + public void reshape(ViewPort vp, int w, int h) { + } + + @Override + public boolean isInitialized() { + return this.viewPort != null; + } + + @Override + public void preFrame(float tpf) { + } + + private void renderShadowMaps(ViewPort viewPort) { + renderManager.setForcedRenderState(prePassRenderState); + renderManager.setForcedTechnique(PRE_SHADOW_TECHNIQUE_NAME); + + for (int i = 0; i < shadowedLights.size(); i++) { + Light light = shadowedLights.getKey(i); + ShadowMap shadowMap = shadowedLights.getValue(i); + + TempVars vars = TempVars.get(); + try { + light.setFrustumCheckNeeded(false); + light.setIntersectsFrustum(light.intersectsFrustum(viewPort.getCamera(), vars)); + if (!light.isIntersectsFrustum()) { + continue; + } + } finally { + vars.release(); + } + + switch (shadowMap.getLightType()) { + case Directional: + DirectionalArrayShadowMap directionalShadow = (DirectionalArrayShadowMap) shadowMap; + directionalShadow.renderShadowMap(renderManager, viewPort, directionalParams, shadowCasters); + break; + case Spot: + SpotArrayShadowMap spotShadow = (SpotArrayShadowMap) shadowMap; + spotShadow.renderShadowMap(renderManager, viewPort, shadowCasters); + break; + default: + throw new UnsupportedOperationException(); + } + + light.setShadowMap(shadowMap); + } + + Renderer renderer = renderManager.getRenderer(); + renderer.setFrameBuffer(viewPort.getOutputFrameBuffer()); + renderManager.setForcedRenderState(null); + renderManager.setForcedTechnique(null); + renderManager.setCamera(viewPort.getCamera(), false); + } + + @Override + public void postQueue(RenderQueue rq) { + directionalParams.updateSplitPositions(viewPort.getCamera()); + renderShadowMaps(viewPort); + } + + @Override + public void postFrame(FrameBuffer out) { + // TODO: call discard contents on all the framebuffers. + for (int i = 0; i < shadowedLights.size(); i++) { + Light light = shadowedLights.getKey(i); + light.setShadowMap(null); + } + } + + @Override + public void cleanup() { + } + + @Override + public void setProfiler(AppProfiler profiler) { + } + +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/ShadowParameters.java b/jme3-core/src/main/java/com/jme3/shadow/next/ShadowParameters.java new file mode 100755 index 000000000..37df980ab --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/ShadowParameters.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2009-2016 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.next; + +/** + * @author Kirill Vainer + */ +public interface ShadowParameters { +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/array/ArrayShadowMap.java b/jme3-core/src/main/java/com/jme3/shadow/next/array/ArrayShadowMap.java new file mode 100755 index 000000000..fe5fdcc83 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/array/ArrayShadowMap.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2009-2016 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.next.array; + +import com.jme3.shadow.next.ShadowMap; +import com.jme3.texture.TextureArray; + +/** + * Represents shadow information for a light, uses texture arrays. + * + * @author Kirill Vainer + */ +public interface ArrayShadowMap extends ShadowMap { + + public TextureArray getArray(); + + public int getFirstArraySlice(); +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/array/ArrayShadowMapSlice.java b/jme3-core/src/main/java/com/jme3/shadow/next/array/ArrayShadowMapSlice.java new file mode 100755 index 000000000..6d3897db2 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/array/ArrayShadowMapSlice.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2009-2016 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.next.array; + +import com.jme3.light.Light; +import com.jme3.shadow.next.ShadowMapSlice; + +/** + * @author Kirill Vainer + */ +public interface ArrayShadowMapSlice extends ShadowMapSlice { +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/array/BaseArrayShadowMap.java b/jme3-core/src/main/java/com/jme3/shadow/next/array/BaseArrayShadowMap.java new file mode 100755 index 000000000..bb7e8024c --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/array/BaseArrayShadowMap.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2009-2016 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.next.array; + +import com.jme3.light.Light; +import com.jme3.texture.TextureArray; + +/** + * + * @author Kirill Vainer + */ +public abstract class BaseArrayShadowMap implements ArrayShadowMap { + + protected final TextureArray array; + protected final int firstArraySlice; + protected T[] slices; + + public BaseArrayShadowMap(TextureArray array, int firstArraySlice) { + this.array = array; + this.firstArraySlice = firstArraySlice; + } + + @Override + public TextureArray getArray() { + return array; + } + + @Override + public int getFirstArraySlice() { + return firstArraySlice; + } + + @Override + public abstract Light.Type getLightType(); + + @Override + public int getNumSlices() { + return slices.length; + } + + @Override + public T getSlice(int index) { + return slices[index]; + } + +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/array/BaseArrayShadowMapSlice.java b/jme3-core/src/main/java/com/jme3/shadow/next/array/BaseArrayShadowMapSlice.java new file mode 100755 index 000000000..b554fb92f --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/array/BaseArrayShadowMapSlice.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2009-2016 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.next.array; + +import com.jme3.light.Light; +import com.jme3.math.Matrix4f; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.Renderer; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.GeometryList; +import com.jme3.texture.FrameBuffer; +import com.jme3.texture.Image; +import com.jme3.texture.TextureArray; + +/** + * @param + * @author Kirill Vainer + */ +public class BaseArrayShadowMapSlice implements ArrayShadowMapSlice { + + protected final FrameBuffer frameBuffer; + protected final Camera shadowCamera; + protected final Vector3f[] points; + + public BaseArrayShadowMapSlice(TextureArray array, int layer, int textureSize, Vector3f[] points) { + this.shadowCamera = new Camera(textureSize, textureSize); + this.shadowCamera.setParallelProjection(true); + this.frameBuffer = new FrameBuffer(textureSize, textureSize, 1); + + Image image = array.getImage(); + image.setDepth(image.getDepth() + 1); + image.addData(null); + + this.frameBuffer.setDepthTexture(array, layer); + this.points = points; + } + + @Override + public Matrix4f getViewProjectionMatrix() { + return shadowCamera.getViewProjectionMatrix(); + } + + @Override + public void renderShadowMap(RenderManager renderManager, Light light, ViewPort viewPort, GeometryList shadowCasters) { + Renderer renderer = renderManager.getRenderer(); + + renderer.setFrameBuffer(frameBuffer); + renderManager.setCamera(shadowCamera, false); + renderer.clearBuffers(false, true, false); + + viewPort.getQueue().renderShadowQueue(shadowCasters, renderManager, shadowCamera, true); + } + +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/array/DirectionalArrayShadowMap.java b/jme3-core/src/main/java/com/jme3/shadow/next/array/DirectionalArrayShadowMap.java new file mode 100755 index 000000000..32151e42a --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/array/DirectionalArrayShadowMap.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2009-2016 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.next.array; + +import com.jme3.light.DirectionalLight; +import com.jme3.light.Light; +import com.jme3.math.Vector3f; +import com.jme3.math.Vector4f; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.GeometryList; +import com.jme3.shadow.next.pssm.DirectionalShadowParameters; +import com.jme3.texture.TextureArray; + +/** + * @author Kirill Vainer + */ +public class DirectionalArrayShadowMap extends BaseArrayShadowMap { + + private final DirectionalLight light; + private final Vector4f projectionSplitPositions = new Vector4f(); + + public DirectionalArrayShadowMap(DirectionalLight light, TextureArray array, int firstArraySlice, int textureSize, int numSplits, Vector3f[] points) { + super(array, firstArraySlice); + this.light = light; + this.slices = new DirectionalArrayShadowMapSlice[numSplits]; + for (int i = 0; i < numSplits; i++) { + this.slices[i] = new DirectionalArrayShadowMapSlice(array, firstArraySlice + i, textureSize, points); + } + } + + public void renderShadowMap(RenderManager renderManager, ViewPort viewPort, DirectionalShadowParameters params, GeometryList shadowCasters) { + projectionSplitPositions.set(params.getProjectionSplitPositions()); + float[] splitPositionsViewSpace = params.getSplitPositions(); + for (int i = 0; i < slices.length; i++) { + float near = splitPositionsViewSpace[i]; + float far = splitPositionsViewSpace[i + 1]; + shadowCasters.clear(); + slices[i].updateShadowCamera(viewPort, light, shadowCasters, near, far); + slices[i].renderShadowMap(renderManager, light, viewPort, shadowCasters); + } + } + + public Vector4f getProjectionSplitPositions() { + return projectionSplitPositions; + } + + @Override + public Light.Type getLightType() { + return Light.Type.Directional; + } + +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/array/DirectionalArrayShadowMapSlice.java b/jme3-core/src/main/java/com/jme3/shadow/next/array/DirectionalArrayShadowMapSlice.java new file mode 100755 index 000000000..580023005 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/array/DirectionalArrayShadowMapSlice.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2009-2016 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.next.array; + +import com.jme3.light.DirectionalLight; +import com.jme3.math.Vector3f; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.GeometryList; +import com.jme3.shadow.ShadowUtil; +import com.jme3.texture.TextureArray; + +/** + * + * @author Kirill Vainer + */ +public class DirectionalArrayShadowMapSlice extends BaseArrayShadowMapSlice { + + public DirectionalArrayShadowMapSlice(TextureArray array, int layer, int textureSize, Vector3f[] points) { + super(array, layer, textureSize, points); + this.shadowCamera.setParallelProjection(true); + } + + public void updateShadowCamera( + ViewPort viewPort, + DirectionalLight light, + GeometryList shadowCasters, + float near, + float far) { + + ShadowUtil.updateFrustumPoints(viewPort.getCamera(), near, far, points); + shadowCamera.lookAtDirection(light.getDirection(), shadowCamera.getUp()); + + int textureSize = frameBuffer.getWidth(); + ShadowUtil.updateShadowCamera(viewPort, null, shadowCamera, points, shadowCasters, textureSize); + } + +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/array/SpotArrayShadowMap.java b/jme3-core/src/main/java/com/jme3/shadow/next/array/SpotArrayShadowMap.java new file mode 100755 index 000000000..5046bc976 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/array/SpotArrayShadowMap.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2009-2016 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.next.array; + +import com.jme3.light.Light; +import com.jme3.light.SpotLight; +import com.jme3.math.Vector3f; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.GeometryList; +import com.jme3.texture.TextureArray; + +/** + * @author Kirill Vainer + */ +public class SpotArrayShadowMap extends BaseArrayShadowMap { + + private final SpotLight light; + + public SpotArrayShadowMap(SpotLight light, TextureArray array, int firstArraySlice, int textureSize, Vector3f[] points) { + super(array, firstArraySlice); + this.light = light; + slices = new SpotArrayShadowMapSlice[]{ + new SpotArrayShadowMapSlice(array, firstArraySlice, textureSize, points) + }; + } + + public void renderShadowMap(RenderManager renderManager, ViewPort viewPort, GeometryList shadowCasters) { + shadowCasters.clear(); + slices[0].updateShadowCamera(viewPort, light, shadowCasters); + slices[0].renderShadowMap(renderManager, light, viewPort, shadowCasters); + } + + @Override + public Light.Type getLightType() { + return Light.Type.Spot; + } + +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/array/SpotArrayShadowMapSlice.java b/jme3-core/src/main/java/com/jme3/shadow/next/array/SpotArrayShadowMapSlice.java new file mode 100755 index 000000000..874da428b --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/array/SpotArrayShadowMapSlice.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2009-2016 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.next.array; + +import com.jme3.light.SpotLight; +import com.jme3.math.FastMath; +import com.jme3.math.Matrix4f; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.GeometryList; +import com.jme3.shadow.ShadowUtil; +import com.jme3.texture.TextureArray; + +/** + * + * @author Kirill Vainer + */ +public class SpotArrayShadowMapSlice extends BaseArrayShadowMapSlice { + + public SpotArrayShadowMapSlice(TextureArray array, int layer, int textureSize, Vector3f[] points) { + super(array, layer, textureSize, points); + } + + public void updateShadowCamera( + ViewPort viewPort, + SpotLight light, + GeometryList shadowCasters) { + + Camera viewCamera = viewPort.getCamera(); + float near = viewCamera.getFrustumNear(); + float far = viewCamera.getFrustumFar(); + + ShadowUtil.updateFrustumPoints(viewCamera, near, far, points); + + shadowCamera.setFrustumPerspective(light.getSpotOuterAngle() * FastMath.RAD_TO_DEG * 2.0f, 1, 1, light.getSpotRange()); + shadowCamera.lookAtDirection(light.getDirection(), shadowCamera.getUp()); + shadowCamera.setLocation(light.getPosition()); + + int textureSize = frameBuffer.getWidth(); + ShadowUtil.updateShadowCamera(viewPort, null, shadowCamera, points, shadowCasters, textureSize); + } +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/pssm/DirectionalShadowParameters.java b/jme3-core/src/main/java/com/jme3/shadow/next/pssm/DirectionalShadowParameters.java new file mode 100755 index 000000000..57f5646be --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/pssm/DirectionalShadowParameters.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2009-2016 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.next.pssm; + +import com.jme3.math.Vector4f; +import com.jme3.renderer.Camera; +import com.jme3.shadow.PssmShadowUtil; +import com.jme3.shadow.next.ShadowParameters; + +/** + * @author Kirill Vainer + */ +public final class DirectionalShadowParameters implements ShadowParameters { + + private float lambda = 0.65f; + private int numSplits = 4; + protected float zFarOverride = 0; + private float[] splitPositions = new float[numSplits + 1]; + private final Vector4f projectionSplitPositions = new Vector4f(); + + public float getLambda() { + return lambda; + } + + public void setLambda(float lambda) { + this.lambda = lambda; + } + + public int getNumSplits() { + return numSplits; + } + + public void setNumSplits(int numSplits) { + // TODO: ensure it is 1 to 4 + this.numSplits = numSplits; + this.splitPositions = new float[numSplits + 1]; + } + + public float[] getSplitPositions() { + return splitPositions; + } + + public Vector4f getProjectionSplitPositions() { + return projectionSplitPositions; + } + + /** + * How far the shadows are rendered in the view + * + * @see #setShadowZExtend(float zFar) + * @return shadowZExtend + */ + public float getShadowZExtend() { + return zFarOverride; + } + + /** + * Set the distance from the eye where the shadows will be rendered. + * + * The default value is dynamically computed based on 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) { + this.zFarOverride = zFar; + + // TODO: Fade length not supported yet +// if (zFarOverride == 0) { +// fadeInfo = null; +// frustumCam = null; +// } else { +// if (fadeInfo != null) { +// fadeInfo.set(zFarOverride - fadeLength, 1f / fadeLength); +// } +// if (frustumCam == null && viewPort != null) { +// initFrustumCam(); +// } +// } + } + + public void updateSplitPositions(Camera viewCamera) { + float near = viewCamera.getFrustumNear(); + float far = zFarOverride == 0f ? viewCamera.getFrustumFar() : zFarOverride; + + PssmShadowUtil.updateFrustumSplits(splitPositions, near, far, lambda); + + // TODO: Parallel projection can have negative near value, so split + // positions must be adjusted. +// if (viewCamera.isParallelProjection()) { +// for (int i = 0; i < splitPositions.length; i++) { +// splitPositions[i] = splitPositions[i] / (far - near); +// } +// } + + switch (splitPositions.length) { + case 5: + projectionSplitPositions.w = 1.0f; // = viewCamera.getViewToProjectionZ(splitPositions[4]); + case 4: + projectionSplitPositions.z = viewCamera.getViewToProjectionZ(splitPositions[3]); + case 3: + projectionSplitPositions.y = viewCamera.getViewToProjectionZ(splitPositions[2]); + case 2: + case 1: + projectionSplitPositions.x = viewCamera.getViewToProjectionZ(splitPositions[1]); + break; + } + } +}