From ec0fcd24d2c92b17cbbc7845f9420d138fa244f5 Mon Sep 17 00:00:00 2001 From: Kirill Vainer Date: Sun, 17 Sep 2017 22:23:51 -0400 Subject: [PATCH] support point light shadows --- .../logic/ShadowStaticPassLightingLogic.java | 13 +++ .../shadow/next/PreShadowArrayRenderer.java | 13 +++ .../next/array/PointArrayShadowMap.java | 99 +++++++++++++++++++ .../next/array/PointArrayShadowMapSlice.java | 60 +++++++++++ 4 files changed, 185 insertions(+) create mode 100644 jme3-core/src/main/java/com/jme3/shadow/next/array/PointArrayShadowMap.java create mode 100644 jme3-core/src/main/java/com/jme3/shadow/next/array/PointArrayShadowMapSlice.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 index dfeec2c2b..c5c11c32d 100755 --- a/jme3-core/src/main/java/com/jme3/material/logic/ShadowStaticPassLightingLogic.java +++ b/jme3-core/src/main/java/com/jme3/material/logic/ShadowStaticPassLightingLogic.java @@ -50,6 +50,7 @@ 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.PointArrayShadowMap; import com.jme3.shadow.next.array.SpotArrayShadowMap; import com.jme3.shadow.next.array.SpotArrayShadowMapSlice; import com.jme3.texture.TextureArray; @@ -171,6 +172,18 @@ public class ShadowStaticPassLightingLogic extends StaticPassLightingLogic { shadowMatrixIndex++; } } + + for (int i = 0; i < numShadowPointLights; i++) { + PointArrayShadowMap map = (PointArrayShadowMap) tempPointLights.get(i).getShadowMap(); + array = map.getArray(); + for (int j = 0; j < map.getNumSlices(); j++) { + ArrayShadowMapSlice slice = (ArrayShadowMapSlice) map.getSlice(j); + shadowMatricesUniform.setMatrix4InArray( + slice.getBiasedViewProjectionMatrix(), + shadowMatrixIndex); + shadowMatrixIndex++; + } + } for (int i = 0; i < numShadowSpotLights; i++) { SpotArrayShadowMap map = (SpotArrayShadowMap) tempSpotLights.get(i).getShadowMap(); 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 index e3e00b636..78b9507fe 100755 --- a/jme3-core/src/main/java/com/jme3/shadow/next/PreShadowArrayRenderer.java +++ b/jme3-core/src/main/java/com/jme3/shadow/next/PreShadowArrayRenderer.java @@ -34,6 +34,7 @@ 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.PointLight; import com.jme3.light.SpotLight; import com.jme3.material.RenderState; import com.jme3.math.Vector3f; @@ -46,6 +47,7 @@ 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.PointArrayShadowMap; import com.jme3.shadow.next.array.SpotArrayShadowMap; import com.jme3.texture.FrameBuffer; import com.jme3.texture.Image; @@ -150,6 +152,13 @@ public class PreShadowArrayRenderer implements SceneProcessor { textureSize, directionalParams.getNumSplits()); break; + case Point: + shadowMap = new PointArrayShadowMap( + (PointLight) light, + array, + nextArraySlice, + textureSize); + break; case Spot: shadowMap = new SpotArrayShadowMap( (SpotLight) light, @@ -202,6 +211,10 @@ public class PreShadowArrayRenderer implements SceneProcessor { DirectionalArrayShadowMap directionalShadow = (DirectionalArrayShadowMap) shadowMap; directionalShadow.renderShadowMap(renderManager, viewPort, directionalParams, shadowCasters, points); break; + case Point: + PointArrayShadowMap pointShadow = (PointArrayShadowMap) shadowMap; + pointShadow.renderShadowMap(renderManager, viewPort, shadowCasters); + break; case Spot: SpotArrayShadowMap spotShadow = (SpotArrayShadowMap) shadowMap; spotShadow.renderShadowMap(renderManager, viewPort, shadowCasters); diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/array/PointArrayShadowMap.java b/jme3-core/src/main/java/com/jme3/shadow/next/array/PointArrayShadowMap.java new file mode 100644 index 000000000..67e2bd35d --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/array/PointArrayShadowMap.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2009-2017 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.Light.Type; +import com.jme3.light.PointLight; +import com.jme3.math.Quaternion; +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 PointArrayShadowMap extends BaseArrayShadowMap { + + private final PointLight light; + + private static final Quaternion[] ROTATIONS = new Quaternion[6]; + + static { + for (int i = 0; i < ROTATIONS.length; i++) { + ROTATIONS[i] = new Quaternion(); + } + + // left + ROTATIONS[0].fromAxes(Vector3f.UNIT_Z, Vector3f.UNIT_Y, Vector3f.UNIT_X.mult(-1f)); + + // right + ROTATIONS[1].fromAxes(Vector3f.UNIT_Z.mult(-1f), Vector3f.UNIT_Y, Vector3f.UNIT_X); + + // bottom + ROTATIONS[2].fromAxes(Vector3f.UNIT_X.mult(-1f), Vector3f.UNIT_Z.mult(-1f), Vector3f.UNIT_Y.mult(-1f)); + + // top + ROTATIONS[3].fromAxes(Vector3f.UNIT_X.mult(-1f), Vector3f.UNIT_Z, Vector3f.UNIT_Y); + + // forward + ROTATIONS[4].fromAxes(Vector3f.UNIT_X.mult(-1f), Vector3f.UNIT_Y, Vector3f.UNIT_Z.mult(-1f)); + + // backward + ROTATIONS[5].fromAxes(Vector3f.UNIT_X, Vector3f.UNIT_Y, Vector3f.UNIT_Z); + } + + public PointArrayShadowMap(PointLight light, TextureArray array, int firstArraySlice, int textureSize) { + super(array, firstArraySlice); + this.light = light; + this.slices = new PointArrayShadowMapSlice[6]; + for (int i = 0; i < slices.length; i++) { + this.slices[i] = new PointArrayShadowMapSlice(array, firstArraySlice + i, textureSize, ROTATIONS[i]); + } + } + + public void renderShadowMap(RenderManager renderManager, ViewPort viewPort, GeometryList shadowCasters) { + for (int i = 0; i < slices.length; i++) { + shadowCasters.clear(); + slices[i].updateShadowCamera(viewPort, light, shadowCasters); + slices[i].renderShadowMap(renderManager, light, viewPort, shadowCasters); + } + } + + @Override + public Light.Type getLightType() { + return Type.Point; + } + +} diff --git a/jme3-core/src/main/java/com/jme3/shadow/next/array/PointArrayShadowMapSlice.java b/jme3-core/src/main/java/com/jme3/shadow/next/array/PointArrayShadowMapSlice.java new file mode 100644 index 000000000..06b8f0a68 --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/shadow/next/array/PointArrayShadowMapSlice.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009-2017 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.PointLight; +import com.jme3.math.Quaternion; +import com.jme3.renderer.ViewPort; +import com.jme3.renderer.queue.GeometryList; +import com.jme3.renderer.queue.RenderQueue.ShadowMode; +import com.jme3.scene.Spatial; +import com.jme3.shadow.ShadowUtil; +import com.jme3.texture.TextureArray; + +/** + * @author Kirill Vainer + */ +public class PointArrayShadowMapSlice extends BaseArrayShadowMapSlice { + + public PointArrayShadowMapSlice(TextureArray array, int layer, int textureSize, Quaternion axes) { + super(array, layer, textureSize, false); + shadowCamera.setAxes(axes); + } + + public void updateShadowCamera(ViewPort viewPort, PointLight light, GeometryList shadowCasters) { + shadowCamera.setFrustumPerspective(90f, 1f, 0.1f, light.getRadius()); + shadowCamera.setLocation(light.getPosition()); + for (Spatial scene : viewPort.getScenes()) { + ShadowUtil.getGeometriesInCamFrustum(scene, shadowCamera, ShadowMode.Cast, shadowCasters); + } + } +}