Compare commits
56 Commits
master
...
in-pass-sh
Author | SHA1 | Date |
---|---|---|
|
dd2626c560 | 7 years ago |
|
d444c28183 | 7 years ago |
|
54ef6ec280 | 7 years ago |
|
cbf6ffaad8 | 7 years ago |
|
251511ee00 | 7 years ago |
|
2e9996d498 | 7 years ago |
|
5f66eeacb4 | 7 years ago |
|
5b800952f0 | 7 years ago |
|
caad16626e | 7 years ago |
|
6fb2d029d2 | 7 years ago |
|
5108f52ebf | 7 years ago |
|
42432ed4ea | 7 years ago |
|
6487def9d3 | 7 years ago |
|
e4536808ca | 7 years ago |
|
fe158e7b31 | 7 years ago |
|
628fa23059 | 7 years ago |
|
fca6d4a8b2 | 8 years ago |
|
8d125a30ba | 8 years ago |
|
d50fb09efb | 8 years ago |
|
59c85d58c8 | 8 years ago |
|
4b4bf24127 | 8 years ago |
|
0fae3839d3 | 8 years ago |
|
c3cfab65c6 | 8 years ago |
|
c136a4212e | 8 years ago |
|
ec0fcd24d2 | 8 years ago |
|
47b34c6de5 | 8 years ago |
|
1e861fd2fa | 8 years ago |
|
b52d0e3743 | 8 years ago |
|
3889cb47b7 | 8 years ago |
|
2c385914c6 | 8 years ago |
|
0a4a439745 | 8 years ago |
|
a3145885d9 | 8 years ago |
|
5aa2c722fe | 8 years ago |
|
77e552f551 | 8 years ago |
|
9c4fcac876 | 8 years ago |
|
d159e1746c | 8 years ago |
|
8a747276d7 | 8 years ago |
|
ce28e35393 | 8 years ago |
|
42051b045b | 8 years ago |
|
cfcec44b9a | 8 years ago |
|
55e9fd067a | 8 years ago |
|
f5ad0274b3 | 8 years ago |
|
2ce2995956 | 8 years ago |
|
4d60b2df70 | 8 years ago |
|
16e472678a | 8 years ago |
|
bc50b09bf4 | 8 years ago |
|
134c3651c8 | 8 years ago |
|
7441865307 | 8 years ago |
|
88aaa079e3 | 8 years ago |
|
b0316e419c | 8 years ago |
|
af3a0c70ce | 8 years ago |
|
7a22f8c940 | 8 years ago |
|
23700d5140 | 8 years ago |
|
69139a1e95 | 8 years ago |
|
259694605e | 8 years ago |
|
406c3144d8 | 8 years ago |
@ -1,182 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (c) 2009-2015 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.ColorRGBA; |
|
||||||
import com.jme3.math.Matrix4f; |
|
||||||
import com.jme3.math.Vector3f; |
|
||||||
import com.jme3.renderer.Caps; |
|
||||||
import com.jme3.renderer.RenderManager; |
|
||||||
import com.jme3.renderer.Renderer; |
|
||||||
import com.jme3.scene.Geometry; |
|
||||||
import com.jme3.shader.DefineList; |
|
||||||
import com.jme3.shader.Shader; |
|
||||||
import com.jme3.shader.Uniform; |
|
||||||
import com.jme3.shader.VarType; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.EnumSet; |
|
||||||
|
|
||||||
/** |
|
||||||
* Rendering logic for static pass. |
|
||||||
* |
|
||||||
* @author Kirill Vainer |
|
||||||
*/ |
|
||||||
public final class StaticPassLightingLogic extends DefaultTechniqueDefLogic { |
|
||||||
|
|
||||||
private static final String DEFINE_NUM_DIR_LIGHTS = "NUM_DIR_LIGHTS"; |
|
||||||
private static final String DEFINE_NUM_POINT_LIGHTS = "NUM_POINT_LIGHTS"; |
|
||||||
private static final String DEFINE_NUM_SPOT_LIGHTS = "NUM_SPOT_LIGHTS"; |
|
||||||
|
|
||||||
private final int numDirLightsDefineId; |
|
||||||
private final int numPointLightsDefineId; |
|
||||||
private final int numSpotLightsDefineId; |
|
||||||
|
|
||||||
private final ArrayList<DirectionalLight> tempDirLights = new ArrayList<DirectionalLight>(); |
|
||||||
private final ArrayList<PointLight> tempPointLights = new ArrayList<PointLight>(); |
|
||||||
private final ArrayList<SpotLight> tempSpotLights = new ArrayList<SpotLight>(); |
|
||||||
|
|
||||||
private final ColorRGBA ambientLightColor = new ColorRGBA(0, 0, 0, 1); |
|
||||||
private final Vector3f tempPosition = new Vector3f(); |
|
||||||
private final Vector3f tempDirection = new Vector3f(); |
|
||||||
|
|
||||||
public StaticPassLightingLogic(TechniqueDef techniqueDef) { |
|
||||||
super(techniqueDef); |
|
||||||
|
|
||||||
numDirLightsDefineId = techniqueDef.addShaderUnmappedDefine(DEFINE_NUM_DIR_LIGHTS, VarType.Int); |
|
||||||
numPointLightsDefineId = techniqueDef.addShaderUnmappedDefine(DEFINE_NUM_POINT_LIGHTS, VarType.Int); |
|
||||||
numSpotLightsDefineId = techniqueDef.addShaderUnmappedDefine(DEFINE_NUM_SPOT_LIGHTS, VarType.Int); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public Shader makeCurrent(AssetManager assetManager, RenderManager renderManager, |
|
||||||
EnumSet<Caps> rendererCaps, LightList lights, DefineList defines) { |
|
||||||
|
|
||||||
// TODO: if it ever changes that render isn't called
|
|
||||||
// right away with the same geometry after makeCurrent, it would be
|
|
||||||
// a problem.
|
|
||||||
// Do a radix sort.
|
|
||||||
tempDirLights.clear(); |
|
||||||
tempPointLights.clear(); |
|
||||||
tempSpotLights.clear(); |
|
||||||
for (Light light : lights) { |
|
||||||
switch (light.getType()) { |
|
||||||
case Directional: |
|
||||||
tempDirLights.add((DirectionalLight) light); |
|
||||||
break; |
|
||||||
case Point: |
|
||||||
tempPointLights.add((PointLight) light); |
|
||||||
break; |
|
||||||
case Spot: |
|
||||||
tempSpotLights.add((SpotLight) light); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
defines.set(numDirLightsDefineId, tempDirLights.size()); |
|
||||||
defines.set(numPointLightsDefineId, tempPointLights.size()); |
|
||||||
defines.set(numSpotLightsDefineId, tempSpotLights.size()); |
|
||||||
|
|
||||||
return techniqueDef.getShader(assetManager, rendererCaps, defines); |
|
||||||
} |
|
||||||
|
|
||||||
private void transformDirection(Matrix4f viewMatrix, Vector3f direction) { |
|
||||||
viewMatrix.multNormal(direction, direction); |
|
||||||
} |
|
||||||
|
|
||||||
private void transformPosition(Matrix4f viewMatrix, Vector3f location) { |
|
||||||
viewMatrix.mult(location, location); |
|
||||||
} |
|
||||||
|
|
||||||
private void updateLightListUniforms(Matrix4f viewMatrix, Shader shader, LightList lights) { |
|
||||||
Uniform ambientColor = shader.getUniform("g_AmbientLightColor"); |
|
||||||
ambientColor.setValue(VarType.Vector4, getAmbientColor(lights, true, ambientLightColor)); |
|
||||||
|
|
||||||
Uniform lightData = shader.getUniform("g_LightData"); |
|
||||||
|
|
||||||
int totalSize = tempDirLights.size() * 2 |
|
||||||
+ tempPointLights.size() * 2 |
|
||||||
+ tempSpotLights.size() * 3; |
|
||||||
lightData.setVector4Length(totalSize); |
|
||||||
|
|
||||||
int index = 0; |
|
||||||
for (DirectionalLight light : tempDirLights) { |
|
||||||
ColorRGBA color = light.getColor(); |
|
||||||
tempDirection.set(light.getDirection()); |
|
||||||
transformDirection(viewMatrix, tempDirection); |
|
||||||
lightData.setVector4InArray(color.r, color.g, color.b, 1f, index++); |
|
||||||
lightData.setVector4InArray(tempDirection.x, tempDirection.y, tempDirection.z, 1f, index++); |
|
||||||
} |
|
||||||
|
|
||||||
for (PointLight light : tempPointLights) { |
|
||||||
ColorRGBA color = light.getColor(); |
|
||||||
tempPosition.set(light.getPosition()); |
|
||||||
float invRadius = light.getInvRadius(); |
|
||||||
transformPosition(viewMatrix, tempPosition); |
|
||||||
lightData.setVector4InArray(color.r, color.g, color.b, 1f, index++); |
|
||||||
lightData.setVector4InArray(tempPosition.x, tempPosition.y, tempPosition.z, invRadius, index++); |
|
||||||
} |
|
||||||
|
|
||||||
for (SpotLight light : tempSpotLights) { |
|
||||||
ColorRGBA color = light.getColor(); |
|
||||||
Vector3f pos = light.getPosition(); |
|
||||||
Vector3f dir = light.getDirection(); |
|
||||||
|
|
||||||
tempPosition.set(light.getPosition()); |
|
||||||
tempDirection.set(light.getDirection()); |
|
||||||
transformPosition(viewMatrix, tempPosition); |
|
||||||
transformDirection(viewMatrix, tempDirection); |
|
||||||
|
|
||||||
float invRange = light.getInvSpotRange(); |
|
||||||
float spotAngleCos = light.getPackedAngleCos(); |
|
||||||
lightData.setVector4InArray(color.r, color.g, color.b, 1f, index++); |
|
||||||
lightData.setVector4InArray(tempPosition.x, tempPosition.y, tempPosition.z, invRange, index++); |
|
||||||
lightData.setVector4InArray(tempDirection.x, tempDirection.y, tempDirection.z, spotAngleCos, index++); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void render(RenderManager renderManager, Shader shader, Geometry geometry, LightList lights, int lastTexUnit) { |
|
||||||
Renderer renderer = renderManager.getRenderer(); |
|
||||||
Matrix4f viewMatrix = renderManager.getCurrentCamera().getViewMatrix(); |
|
||||||
updateLightListUniforms(viewMatrix, shader, lights); |
|
||||||
renderer.setShader(shader); |
|
||||||
renderMeshFromGeometry(renderer, geometry); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,275 @@ |
|||||||
|
/* |
||||||
|
* 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.asset.AssetManager; |
||||||
|
import com.jme3.shadow.next.pssm.DirectionalShadowParameters; |
||||||
|
import com.jme3.light.DirectionalLight; |
||||||
|
import com.jme3.light.Light; |
||||||
|
import com.jme3.light.Light.Type; |
||||||
|
import com.jme3.light.PointLight; |
||||||
|
import com.jme3.light.SpotLight; |
||||||
|
import com.jme3.material.MatParamOverride; |
||||||
|
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.scene.Node; |
||||||
|
import com.jme3.shader.VarType; |
||||||
|
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; |
||||||
|
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. |
||||||
|
* <p> |
||||||
|
* This version is primarily focused on rendering in-pass shadows, so pre-pass |
||||||
|
* and subsequent stages are separated. |
||||||
|
* |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public class InPassShadowRenderer 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<Light, ShadowMap> shadowedLights = new ListMap<>(); |
||||||
|
private final RenderState prePassRenderState = RenderState.ADDITIONAL.clone(); |
||||||
|
private final MatParamOverride pointLightOverride = new MatParamOverride(VarType.Boolean, "IsPointLight", true); |
||||||
|
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 InPassShadowRenderer() { |
||||||
|
for (int i = 0; i < points.length; i++) { |
||||||
|
points[i] = new Vector3f(); |
||||||
|
} |
||||||
|
|
||||||
|
prePassRenderState.setFaceCullMode(RenderState.FaceCullMode.Back); |
||||||
|
prePassRenderState.setColorWrite(false); |
||||||
|
prePassRenderState.setDepthWrite(true); |
||||||
|
prePassRenderState.setDepthTest(true); |
||||||
|
prePassRenderState.setPolyOffset(0, 0); |
||||||
|
|
||||||
|
array.setAnisotropicFilter(1); |
||||||
|
array.setShadowCompareMode(ShadowCompareMode.LessOrEqual); |
||||||
|
|
||||||
|
array.setMagFilter(MagFilter.Bilinear); |
||||||
|
array.setMinFilter(MinFilter.BilinearNoMipMaps); |
||||||
|
} |
||||||
|
|
||||||
|
public void displayDebug(AssetManager assetManager, Node guiRoot) { |
||||||
|
guiRoot.addControl(new ShadowDebugControl(assetManager, this)); |
||||||
|
} |
||||||
|
|
||||||
|
@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 TextureArray getShadowMapTexture() { |
||||||
|
return array; |
||||||
|
} |
||||||
|
|
||||||
|
public void addLight(Light light) { |
||||||
|
if (array.getImage() == null) { |
||||||
|
array.setImage(new Image( |
||||||
|
Format.Depth32F, |
||||||
|
textureSize, |
||||||
|
textureSize, |
||||||
|
0, |
||||||
|
new ArrayList<ByteBuffer>(), |
||||||
|
ColorSpace.Linear)); |
||||||
|
} |
||||||
|
|
||||||
|
ShadowMap shadowMap; |
||||||
|
switch (light.getType()) { |
||||||
|
case Directional: |
||||||
|
shadowMap = new DirectionalArrayShadowMap( |
||||||
|
(DirectionalLight) light, |
||||||
|
array, |
||||||
|
nextArraySlice, |
||||||
|
textureSize, |
||||||
|
directionalParams.getNumSplits()); |
||||||
|
break; |
||||||
|
case Point: |
||||||
|
shadowMap = new PointArrayShadowMap( |
||||||
|
(PointLight) light, |
||||||
|
array, |
||||||
|
nextArraySlice, |
||||||
|
textureSize); |
||||||
|
break; |
||||||
|
case Spot: |
||||||
|
shadowMap = new SpotArrayShadowMap( |
||||||
|
(SpotLight) light, |
||||||
|
array, |
||||||
|
nextArraySlice, |
||||||
|
textureSize); |
||||||
|
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); |
||||||
|
renderManager.addForcedMatParam(pointLightOverride); |
||||||
|
|
||||||
|
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(); |
||||||
|
} |
||||||
|
|
||||||
|
pointLightOverride.setEnabled(shadowMap.getLightType() == Type.Point); |
||||||
|
|
||||||
|
switch (shadowMap.getLightType()) { |
||||||
|
case Directional: |
||||||
|
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); |
||||||
|
break; |
||||||
|
default: |
||||||
|
throw new UnsupportedOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
light.setShadowMap(shadowMap); |
||||||
|
} |
||||||
|
|
||||||
|
Renderer renderer = renderManager.getRenderer(); |
||||||
|
renderer.setFrameBuffer(viewPort.getOutputFrameBuffer()); |
||||||
|
renderManager.removeForcedMatParam(pointLightOverride); |
||||||
|
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) { |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,183 @@ |
|||||||
|
/* |
||||||
|
* 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.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.pssm.DirectionalShadowMap; |
||||||
|
import com.jme3.texture.FrameBuffer; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* The 4th generation of shadow mapping in jME3. |
||||||
|
* <p> |
||||||
|
* This version is primarily focused on rendering in-pass shadows, so pre-pass |
||||||
|
* and subsequent stages are separated. |
||||||
|
* |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public class PreShadowRenderer 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 List<ShadowMap> shadowMaps = new ArrayList<>(); |
||||||
|
private final RenderState prePassRenderState = RenderState.ADDITIONAL.clone(); |
||||||
|
|
||||||
|
private int textureSize = 1024; |
||||||
|
|
||||||
|
// parameters for directional lights
|
||||||
|
private final DirectionalShadowParameters directionalParams = new DirectionalShadowParameters(); |
||||||
|
|
||||||
|
public PreShadowRenderer() { |
||||||
|
for (int i = 0; i < points.length; i++) { |
||||||
|
points[i] = new Vector3f(); |
||||||
|
} |
||||||
|
|
||||||
|
prePassRenderState.setFaceCullMode(RenderState.FaceCullMode.Off); |
||||||
|
prePassRenderState.setColorWrite(false); |
||||||
|
prePassRenderState.setDepthWrite(true); |
||||||
|
prePassRenderState.setDepthTest(true); |
||||||
|
prePassRenderState.setPolyOffset(1.2f, 0); |
||||||
|
} |
||||||
|
|
||||||
|
@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) { |
||||||
|
// TODO: might want to set this separately per model
|
||||||
|
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) { |
||||||
|
ShadowMap shadowMap; |
||||||
|
switch (light.getType()) { |
||||||
|
case Directional: |
||||||
|
shadowMap = new DirectionalShadowMap( |
||||||
|
(DirectionalLight) light, |
||||||
|
textureSize, |
||||||
|
directionalParams.getNumSplits(), |
||||||
|
points); |
||||||
|
break; |
||||||
|
default: |
||||||
|
throw new UnsupportedOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
light.setShadowMap(shadowMap); |
||||||
|
shadowMaps.add(shadowMap); |
||||||
|
} |
||||||
|
|
||||||
|
@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() { |
||||||
|
renderManager.setForcedRenderState(prePassRenderState); |
||||||
|
renderManager.setForcedTechnique(PRE_SHADOW_TECHNIQUE_NAME); |
||||||
|
|
||||||
|
for (ShadowMap shadowMap : shadowMaps) { |
||||||
|
switch (shadowMap.getLightType()) { |
||||||
|
case Directional: |
||||||
|
DirectionalShadowMap directionalShadow = (DirectionalShadowMap) shadowMap; |
||||||
|
directionalShadow.renderShadowMap(renderManager, viewPort, directionalParams, shadowCasters); |
||||||
|
break; |
||||||
|
default: |
||||||
|
throw new UnsupportedOperationException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void postFrame(FrameBuffer out) { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void cleanup() { |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setProfiler(AppProfiler profiler) { |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,98 @@ |
|||||||
|
/* |
||||||
|
* 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; |
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.renderer.RenderManager; |
||||||
|
import com.jme3.renderer.ViewPort; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.scene.Spatial; |
||||||
|
import com.jme3.scene.control.AbstractControl; |
||||||
|
import com.jme3.texture.Image; |
||||||
|
import com.jme3.texture.TextureArray; |
||||||
|
import com.jme3.ui.Picture; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Shows the shadow maps on the screen |
||||||
|
* |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
final class ShadowDebugControl extends AbstractControl { |
||||||
|
|
||||||
|
private final List<Picture> pictures = new ArrayList<>(); |
||||||
|
|
||||||
|
public ShadowDebugControl(AssetManager assetManager, InPassShadowRenderer shadowRenderer) { |
||||||
|
TextureArray shadowMapArray = shadowRenderer.getShadowMapTexture(); |
||||||
|
Image shadowMap = shadowMapArray.getImage(); |
||||||
|
for (int i = 0; i < shadowMap.getDepth(); i++) { |
||||||
|
Picture picture = new Picture("Shadow Map " + i); |
||||||
|
picture.setPosition(20, i * 128 + 20); |
||||||
|
picture.setWidth(128); |
||||||
|
picture.setHeight(128); |
||||||
|
|
||||||
|
Material material = new Material(assetManager, "Common/MatDefs/Shadow/ShowShadowArray.j3md"); |
||||||
|
material.setTexture("ShadowMapArray", shadowMapArray); |
||||||
|
material.setFloat("ShadowMapSlice", i); |
||||||
|
picture.setMaterial(material); |
||||||
|
|
||||||
|
pictures.add(picture); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setSpatial(Spatial spatial) { |
||||||
|
if (spatial != null) { |
||||||
|
for (Picture picture : pictures) { |
||||||
|
((Node) spatial).detachChild(picture); |
||||||
|
} |
||||||
|
} |
||||||
|
super.setSpatial(spatial); |
||||||
|
if (spatial != null) { |
||||||
|
for (Picture picture : pictures) { |
||||||
|
((Node) spatial).attachChild(picture); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void controlUpdate(float tpf) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void controlRender(RenderManager rm, ViewPort vp) { |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
/* |
||||||
|
* 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.light.Light; |
||||||
|
import com.jme3.light.Light.Type; |
||||||
|
|
||||||
|
/** |
||||||
|
* Represents shadow information for a light. |
||||||
|
* @param <T> Type of light |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public interface ShadowMap<T extends Light> { |
||||||
|
|
||||||
|
public Type getLightType(); |
||||||
|
|
||||||
|
public int getNumSlices(); |
||||||
|
|
||||||
|
public ShadowMapSlice<T> getSlice(int index); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
/* |
||||||
|
* 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.light.Light; |
||||||
|
import com.jme3.math.Matrix4f; |
||||||
|
import com.jme3.renderer.RenderManager; |
||||||
|
import com.jme3.renderer.ViewPort; |
||||||
|
import com.jme3.renderer.queue.GeometryList; |
||||||
|
|
||||||
|
/** |
||||||
|
* Represents a single slice of a shadow map. |
||||||
|
* |
||||||
|
* @param <T> Type of light |
||||||
|
* |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public interface ShadowMapSlice<T extends Light> { |
||||||
|
|
||||||
|
public static final Matrix4f BIAS_MATRIX = new Matrix4f( |
||||||
|
0.5f, 0.0f, 0.0f, 0.5f, |
||||||
|
0.0f, 0.5f, 0.0f, 0.5f, |
||||||
|
0.0f, 0.0f, 0.5f, 0.5f, |
||||||
|
0.0f, 0.0f, 0.0f, 1.0f); |
||||||
|
|
||||||
|
public Matrix4f getBiasedViewProjectionMatrix(); |
||||||
|
|
||||||
|
public void renderShadowMap(RenderManager renderManager, T light, ViewPort viewPort, GeometryList shadowCasters); |
||||||
|
} |
@ -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(); |
||||||
|
} |
@ -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<T extends Light> extends ShadowMapSlice<T> { |
||||||
|
} |
@ -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<T extends ArrayShadowMapSlice> 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]; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,98 @@ |
|||||||
|
/* |
||||||
|
* 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.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 <T> |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public class BaseArrayShadowMapSlice<T extends Light> implements ArrayShadowMapSlice<T> { |
||||||
|
|
||||||
|
protected final FrameBuffer frameBuffer; |
||||||
|
protected final Camera shadowCamera; |
||||||
|
protected final Matrix4f biasedViewProjectionMatrix = new Matrix4f(); |
||||||
|
|
||||||
|
protected boolean fbNeedClear = true; |
||||||
|
|
||||||
|
public BaseArrayShadowMapSlice(TextureArray array, int layer, int textureSize, boolean useBorder) { |
||||||
|
this.shadowCamera = new Camera(textureSize, textureSize); |
||||||
|
|
||||||
|
if (useBorder) { |
||||||
|
float onePx = 1f / textureSize; |
||||||
|
this.shadowCamera.setViewPort(onePx, 1f - onePx, onePx, 1f - onePx); |
||||||
|
} |
||||||
|
|
||||||
|
this.frameBuffer = new FrameBuffer(textureSize, textureSize, 1); |
||||||
|
|
||||||
|
Image image = array.getImage(); |
||||||
|
image.setDepth(image.getDepth() + 1); |
||||||
|
image.addData(null); |
||||||
|
|
||||||
|
this.frameBuffer.setDepthTexture(array, layer); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Matrix4f getBiasedViewProjectionMatrix() { |
||||||
|
return biasedViewProjectionMatrix; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void renderShadowMap(RenderManager renderManager, Light light, ViewPort viewPort, GeometryList shadowCasters) { |
||||||
|
Renderer renderer = renderManager.getRenderer(); |
||||||
|
|
||||||
|
if (fbNeedClear) { |
||||||
|
renderer.setFrameBuffer(frameBuffer); |
||||||
|
renderer.clearClipRect(); |
||||||
|
renderer.clearBuffers(false, true, false); |
||||||
|
fbNeedClear = false; |
||||||
|
} |
||||||
|
|
||||||
|
if (shadowCasters.size() > 0) { |
||||||
|
renderManager.setCamera(shadowCamera, false); |
||||||
|
viewPort.getQueue().renderShadowQueue(shadowCasters, renderManager, shadowCamera, true); |
||||||
|
fbNeedClear = true; |
||||||
|
} |
||||||
|
|
||||||
|
BIAS_MATRIX.mult(shadowCamera.getViewProjectionMatrix(), biasedViewProjectionMatrix); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
/* |
||||||
|
* 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.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<DirectionalArrayShadowMapSlice> { |
||||||
|
|
||||||
|
private final DirectionalLight light; |
||||||
|
private final Vector3f projectionSplitPositions = new Vector3f(); |
||||||
|
|
||||||
|
public DirectionalArrayShadowMap(DirectionalLight light, TextureArray array, int firstArraySlice, int textureSize, int numSplits) { |
||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void renderShadowMap(RenderManager renderManager, ViewPort viewPort, DirectionalShadowParameters params, GeometryList shadowCasters, Vector3f[] points) { |
||||||
|
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, points); |
||||||
|
slices[i].renderShadowMap(renderManager, light, viewPort, shadowCasters); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Vector3f getProjectionSplitPositions() { |
||||||
|
return projectionSplitPositions; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Light.Type getLightType() { |
||||||
|
return Light.Type.Directional; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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.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<DirectionalLight> { |
||||||
|
|
||||||
|
public DirectionalArrayShadowMapSlice(TextureArray array, int layer, int textureSize) { |
||||||
|
super(array, layer, textureSize, true); |
||||||
|
this.shadowCamera.setParallelProjection(true); |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean isParallelToYUp(Vector3f direction) { |
||||||
|
return direction.x == 0 && direction.z == 0 |
||||||
|
&& (direction.y == -1 || direction.y == 1); |
||||||
|
} |
||||||
|
|
||||||
|
public void updateShadowCamera( |
||||||
|
ViewPort viewPort, |
||||||
|
DirectionalLight light, |
||||||
|
GeometryList shadowCasters, |
||||||
|
float near, |
||||||
|
float far, |
||||||
|
Vector3f[] points) { |
||||||
|
if (isParallelToYUp(light.getDirection())) { |
||||||
|
// direction and up cannot be parallel
|
||||||
|
shadowCamera.lookAtDirection(light.getDirection(), Vector3f.UNIT_Z); |
||||||
|
} else { |
||||||
|
shadowCamera.lookAtDirection(light.getDirection(), Vector3f.UNIT_Y); |
||||||
|
} |
||||||
|
|
||||||
|
int textureSize = frameBuffer.getWidth(); |
||||||
|
ShadowUtil.updateFrustumPoints(viewPort.getCamera(), near, far, points); |
||||||
|
ShadowUtil.updateShadowCamera(viewPort, null, shadowCamera, points, shadowCasters, textureSize); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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<PointArrayShadowMapSlice> { |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -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<PointLight> { |
||||||
|
|
||||||
|
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.5f, light.getRadius()); |
||||||
|
shadowCamera.setLocation(light.getPosition()); |
||||||
|
for (Spatial scene : viewPort.getScenes()) { |
||||||
|
ShadowUtil.getGeometriesInCamFrustum(scene, shadowCamera, ShadowMode.Cast, shadowCasters); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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.Light; |
||||||
|
import com.jme3.light.SpotLight; |
||||||
|
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<SpotArrayShadowMapSlice> { |
||||||
|
|
||||||
|
private final SpotLight light; |
||||||
|
|
||||||
|
public SpotArrayShadowMap(SpotLight light, TextureArray array, int firstArraySlice, int textureSize) { |
||||||
|
super(array, firstArraySlice); |
||||||
|
this.light = light; |
||||||
|
slices = new SpotArrayShadowMapSlice[]{ |
||||||
|
new SpotArrayShadowMapSlice(array, firstArraySlice, textureSize) |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
/* |
||||||
|
* 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.Vector3f; |
||||||
|
import com.jme3.renderer.ViewPort; |
||||||
|
import com.jme3.renderer.queue.GeometryList; |
||||||
|
import com.jme3.renderer.queue.RenderQueue; |
||||||
|
import com.jme3.scene.Spatial; |
||||||
|
import com.jme3.shadow.ShadowUtil; |
||||||
|
import com.jme3.texture.TextureArray; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public class SpotArrayShadowMapSlice extends BaseArrayShadowMapSlice<SpotLight> { |
||||||
|
|
||||||
|
public SpotArrayShadowMapSlice(TextureArray array, int layer, int textureSize) { |
||||||
|
super(array, layer, textureSize, true); |
||||||
|
} |
||||||
|
|
||||||
|
private static boolean isParallelToYUp(Vector3f direction) { |
||||||
|
return direction.x == 0 && direction.z == 0 |
||||||
|
&& (direction.y == -1 || direction.y == 1); |
||||||
|
} |
||||||
|
|
||||||
|
public void updateShadowCamera(ViewPort viewPort, SpotLight light, GeometryList shadowCasters) { |
||||||
|
shadowCamera.setLocation(light.getPosition()); |
||||||
|
if (isParallelToYUp(light.getDirection())) { |
||||||
|
// direction and up cannot be parallel
|
||||||
|
shadowCamera.lookAtDirection(light.getDirection(), Vector3f.UNIT_Z); |
||||||
|
} else { |
||||||
|
shadowCamera.lookAtDirection(light.getDirection(), Vector3f.UNIT_Y); |
||||||
|
} |
||||||
|
shadowCamera.setFrustumPerspective(light.getSpotOuterAngle() * FastMath.RAD_TO_DEG * 2.0f, 1, 1, light.getSpotRange()); |
||||||
|
for (Spatial scene : viewPort.getScenes()) { |
||||||
|
ShadowUtil.getGeometriesInCamFrustum(scene, shadowCamera, RenderQueue.ShadowMode.Cast, shadowCasters); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
/* |
||||||
|
* 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.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.Texture.MagFilter; |
||||||
|
import com.jme3.texture.Texture.MinFilter; |
||||||
|
import com.jme3.texture.Texture.ShadowCompareMode; |
||||||
|
import com.jme3.texture.Texture2D; |
||||||
|
import com.jme3.shadow.next.ShadowMapSlice; |
||||||
|
|
||||||
|
public abstract class BaseShadowMapSlice<T extends Light> implements ShadowMapSlice<T> { |
||||||
|
|
||||||
|
protected final FrameBuffer frameBuffer; |
||||||
|
protected final Texture2D depthTexture; |
||||||
|
protected final Camera shadowCamera; |
||||||
|
protected final Vector3f[] points; |
||||||
|
protected final Matrix4f biasedViewProjectionMatrix = new Matrix4f(); |
||||||
|
|
||||||
|
public BaseShadowMapSlice(int size, Vector3f[] points) { |
||||||
|
this.depthTexture = new Texture2D(size, size, Image.Format.Depth16); |
||||||
|
this.depthTexture.setAnisotropicFilter(1); |
||||||
|
this.depthTexture.setShadowCompareMode(ShadowCompareMode.LessOrEqual); |
||||||
|
this.depthTexture.setMagFilter(MagFilter.Bilinear); |
||||||
|
this.depthTexture.setMinFilter(MinFilter.BilinearNoMipMaps); |
||||||
|
this.shadowCamera = new Camera(size, size); |
||||||
|
this.frameBuffer = new FrameBuffer(size, size, 1); |
||||||
|
this.frameBuffer.setDepthTexture(depthTexture); |
||||||
|
this.points = points; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void renderShadowMap(RenderManager renderManager, T light, ViewPort viewPort, GeometryList shadowCasters) { |
||||||
|
Renderer renderer = renderManager.getRenderer(); |
||||||
|
|
||||||
|
renderer.setFrameBuffer(frameBuffer); |
||||||
|
renderer.clearBuffers(false, true, false); |
||||||
|
|
||||||
|
if (shadowCasters.size() > 0) { |
||||||
|
renderManager.setCamera(shadowCamera, false); |
||||||
|
viewPort.getQueue().renderShadowQueue(shadowCasters, renderManager, shadowCamera, true); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Matrix4f getBiasedViewProjectionMatrix() { |
||||||
|
return BIAS_MATRIX.mult(shadowCamera.getViewProjectionMatrix(), biasedViewProjectionMatrix); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,92 @@ |
|||||||
|
/* |
||||||
|
* 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.light.DirectionalLight; |
||||||
|
import com.jme3.light.Light.Type; |
||||||
|
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.ShadowMapSlice; |
||||||
|
import com.jme3.shadow.next.ShadowMap; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public class DirectionalShadowMap implements ShadowMap<DirectionalLight> { |
||||||
|
|
||||||
|
private final DirectionalLight light; |
||||||
|
private final DirectionalShadowMapSlice[] splits; |
||||||
|
private final Vector3f projectionSplitPositions = new Vector3f(); |
||||||
|
|
||||||
|
public DirectionalShadowMap(DirectionalLight light, int textureSize, int numSplits, Vector3f[] points) { |
||||||
|
this.light = light; |
||||||
|
this.splits = new DirectionalShadowMapSlice[numSplits]; |
||||||
|
for (int i = 0; i < splits.length; i++) { |
||||||
|
this.splits[i] = new DirectionalShadowMapSlice(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 < splits.length; i++) { |
||||||
|
float near = splitPositionsViewSpace[i]; |
||||||
|
float far = splitPositionsViewSpace[i + 1]; |
||||||
|
shadowCasters.clear(); |
||||||
|
splits[i].updateShadowCamera(viewPort, light, shadowCasters, near, far); |
||||||
|
splits[i].renderShadowMap(renderManager, light, viewPort, shadowCasters); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Vector3f getProjectionSplitPositions() { |
||||||
|
return projectionSplitPositions; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getNumSlices() { |
||||||
|
return splits.length; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ShadowMapSlice getSlice(int index) { |
||||||
|
return splits[index]; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Type getLightType() { |
||||||
|
return Type.Directional; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
/* |
||||||
|
* 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.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.Texture2D; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public class DirectionalShadowMapSlice extends BaseShadowMapSlice<DirectionalLight> { |
||||||
|
|
||||||
|
public DirectionalShadowMapSlice(int size, Vector3f[] points) { |
||||||
|
super(size, 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); |
||||||
|
} |
||||||
|
|
||||||
|
public Texture2D getTexture() { |
||||||
|
return depthTexture; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,139 @@ |
|||||||
|
/* |
||||||
|
* 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.Vector3f; |
||||||
|
import com.jme3.renderer.Camera; |
||||||
|
import com.jme3.shadow.PssmShadowUtil; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public final class DirectionalShadowParameters { |
||||||
|
|
||||||
|
private float lambda = 0.65f; |
||||||
|
private int numSplits = 4; |
||||||
|
protected float zFarOverride = 0; |
||||||
|
private float[] splitPositions = new float[numSplits + 1]; |
||||||
|
private final Vector3f projectionSplitPositions = new Vector3f(); |
||||||
|
|
||||||
|
public float getLambda() { |
||||||
|
return lambda; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLambda(float lambda) { |
||||||
|
this.lambda = lambda; |
||||||
|
} |
||||||
|
|
||||||
|
public int getNumSplits() { |
||||||
|
return numSplits; |
||||||
|
} |
||||||
|
|
||||||
|
public void setNumSplits(int numSplits) { |
||||||
|
if (numSplits < 1 || numSplits > 4) { |
||||||
|
throw new IllegalArgumentException("Number of splits must be between 1 and 4"); |
||||||
|
} |
||||||
|
this.numSplits = numSplits; |
||||||
|
this.splitPositions = new float[numSplits + 1]; |
||||||
|
} |
||||||
|
|
||||||
|
public float[] getSplitPositions() { |
||||||
|
return splitPositions; |
||||||
|
} |
||||||
|
|
||||||
|
public Vector3f 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;
|
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
#import "Common/ShaderLib/GLSLCompat.glsllib" |
||||||
|
|
||||||
|
uniform float m_ShadowMapSlice; |
||||||
|
uniform sampler2DArray m_ShadowMapArray; |
||||||
|
varying vec2 texCoord1; |
||||||
|
|
||||||
|
void main() { |
||||||
|
float shadow = texture2D(m_ShadowMapArray, vec3(texCoord1, m_ShadowMapSlice)).r; |
||||||
|
|
||||||
|
shadow = sqrt(shadow); |
||||||
|
|
||||||
|
// TODO: make it betterer |
||||||
|
gl_FragColor.rgb = vec3(shadow); |
||||||
|
gl_FragColor.a = 1.0; |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
MaterialDef Pre Shadow { |
||||||
|
|
||||||
|
MaterialParameters { |
||||||
|
TextureArray ShadowMapArray |
||||||
|
Float ShadowMapSlice |
||||||
|
} |
||||||
|
|
||||||
|
Technique { |
||||||
|
VertexShader GLSL150 : Common/MatDefs/Misc/Unshaded.vert |
||||||
|
FragmentShader GLSL150 : Common/MatDefs/Shadow/ShowShadowArray.frag |
||||||
|
|
||||||
|
WorldParameters { |
||||||
|
WorldViewProjectionMatrix |
||||||
|
ViewProjectionMatrix |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,165 @@ |
|||||||
|
#import "Common/ShaderLib/GLSLCompat.glsllib" |
||||||
|
|
||||||
|
#extension GL_EXT_texture_array : enable |
||||||
|
|
||||||
|
#ifndef NUM_PSSM_SPLITS |
||||||
|
#define NUM_PSSM_SPLITS 0 |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef IN_PASS_SHADOWS |
||||||
|
|
||||||
|
uniform mat4 g_ShadowMatrices[(NB_LIGHTS/3) + NUM_PSSM_SPLITS]; |
||||||
|
|
||||||
|
#if NUM_PSSM_SPLITS > 0 |
||||||
|
varying vec3 dirProjCoord[NUM_PSSM_SPLITS]; |
||||||
|
#else |
||||||
|
varying vec3 dirProjCoord[1]; |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef VERTEX_SHADER |
||||||
|
void Shadow_ProcessProjCoord(vec3 worldPos) { |
||||||
|
#if NUM_PSSM_SPLITS > 0 |
||||||
|
for (int i = 0; i < NUM_PSSM_SPLITS; i++) { |
||||||
|
#if __VERSION__ >= 150 |
||||||
|
dirProjCoord[i] = mat4x3(g_ShadowMatrices[i]) * vec4(worldPos, 1.0); |
||||||
|
#else |
||||||
|
dirProjCoord[i] = (g_ShadowMatrices[i] * vec4(worldPos, 1.0)).xyz; |
||||||
|
#endif |
||||||
|
} |
||||||
|
#endif |
||||||
|
} |
||||||
|
#else |
||||||
|
uniform sampler2DArrayShadow g_ShadowMapArray; |
||||||
|
uniform vec3 g_PssmSplits; |
||||||
|
|
||||||
|
float pssmSliceOffset; |
||||||
|
|
||||||
|
void Shadow_ProcessPssmSlice() { |
||||||
|
#if NUM_PSSM_SPLITS > 1 |
||||||
|
pssmSliceOffset = dot(step(g_PssmSplits.xyz, gl_FragCoord.zzz), vec3(1.0)); |
||||||
|
#else |
||||||
|
pssmSliceOffset = 0.0; |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
vec3 Shadow_GetCubeMapTC(in vec3 direction) { |
||||||
|
vec3 axis = abs(direction); |
||||||
|
float largest = max(axis.x, max(axis.y, axis.z)); |
||||||
|
vec3 tc; |
||||||
|
if (largest == axis.x) { |
||||||
|
if (direction.x > 0.0) { |
||||||
|
tc = vec3( direction.z, -direction.y, 0.0); |
||||||
|
} else { |
||||||
|
tc = vec3(-direction.z, -direction.y, 1.0); |
||||||
|
} |
||||||
|
} else if (largest == axis.y) { |
||||||
|
if (direction.y > 0.0) { |
||||||
|
tc = vec3(-direction.x, direction.z, 2.0); |
||||||
|
} else { |
||||||
|
tc = vec3(-direction.x, -direction.z, 3.0); |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (direction.z > 0.0) { |
||||||
|
tc = vec3(-direction.x, -direction.y, 4.0); |
||||||
|
} else { |
||||||
|
tc = vec3(direction.x, -direction.y, 5.0); |
||||||
|
} |
||||||
|
} |
||||||
|
largest = 1.0 / largest; |
||||||
|
tc.xy = 0.5 * (tc.xy * vec2(largest) + 1.0); |
||||||
|
return tc; |
||||||
|
} |
||||||
|
|
||||||
|
float Shadow_Process(int lightIndex, float lightType, float shadowMapIndex, |
||||||
|
vec3 lightVec, vec3 lightDir, |
||||||
|
vec3 worldPos, float invRadius) { |
||||||
|
vec4 tc; |
||||||
|
|
||||||
|
if (lightType <= 0.2) { |
||||||
|
vec3 projCoord = dirProjCoord[int(pssmSliceOffset)]; |
||||||
|
tc = vec4(projCoord.xy, shadowMapIndex + pssmSliceOffset, projCoord.z); |
||||||
|
} else if (lightType <= 0.3) { |
||||||
|
vec3 projCoord = Shadow_GetCubeMapTC(lightVec.xyz); |
||||||
|
float dist = sqrt(length(lightVec) * invRadius); |
||||||
|
tc = vec4(projCoord.xy, shadowMapIndex + projCoord.z, dist); |
||||||
|
} else { |
||||||
|
tc = g_ShadowMatrices[NUM_PSSM_SPLITS + lightIndex] * vec4(worldPos, 1.0); |
||||||
|
tc.xyz /= tc.w; |
||||||
|
tc = vec4(tc.xy, shadowMapIndex, tc.z); |
||||||
|
} |
||||||
|
|
||||||
|
#if __VERSION__ >= 150 |
||||||
|
return texture(g_ShadowMapArray, tc); |
||||||
|
#else |
||||||
|
return shadow2DArray(g_ShadowMapArray, tc).x; |
||||||
|
#endif |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
#elif NUM_PSSM_SPLITS > 0 |
||||||
|
|
||||||
|
// A lightweight version of in-pass lighting that only handles directional lights |
||||||
|
// Control flow and loop iteration count are static |
||||||
|
|
||||||
|
varying vec4 vProjCoord[NUM_PSSM_SPLITS]; |
||||||
|
|
||||||
|
#ifdef VERTEX_SHADER |
||||||
|
uniform mat4 g_DirectionalShadowMatrix[NUM_PSSM_SPLITS]; |
||||||
|
void Shadow_ProcessProjCoord(vec3 worldPos) { |
||||||
|
for (int i = 0; i < NUM_PSSM_SPLITS; i++) { |
||||||
|
vProjCoord[i] = g_DirectionalShadowMatrix[i] * vec4(worldPos, 1.0); |
||||||
|
} |
||||||
|
} |
||||||
|
#else |
||||||
|
uniform sampler2DShadow g_DirectionalShadowMap[NUM_PSSM_SPLITS]; |
||||||
|
uniform vec4 g_PssmSplits; |
||||||
|
|
||||||
|
const vec2 invTexSize = vec2(1.0 / 1024.0); |
||||||
|
|
||||||
|
float Shadow_SampleOffset(sampler2DShadow shadowMap, vec4 projCoord, vec2 offset) { |
||||||
|
return shadow2D(shadowMap, vec3(projCoord.xy + offset * invTexSize, projCoord.z)).r; |
||||||
|
} |
||||||
|
|
||||||
|
float Shadow_Sample(sampler2DShadow shadowMap, vec4 projCoord) { |
||||||
|
return shadow2D(shadowMap, projCoord.xyz).r; |
||||||
|
} |
||||||
|
|
||||||
|
#define GET_SHADOW(i) if (z < g_PssmSplits[i]) return Shadow_Sample(g_DirectionalShadowMap[i], vProjCoord[i]); |
||||||
|
|
||||||
|
void Shadow_ProcessPssmSlice() { |
||||||
|
} |
||||||
|
|
||||||
|
float Shadow_ProcessDirectional() { |
||||||
|
float z = gl_FragCoord.z; |
||||||
|
|
||||||
|
GET_SHADOW(0); |
||||||
|
#if NUM_PSSM_SPLITS > 1 |
||||||
|
GET_SHADOW(1) |
||||||
|
#if NUM_PSSM_SPLITS > 2 |
||||||
|
GET_SHADOW(2) |
||||||
|
#if NUM_PSSM_SPLITS > 3 |
||||||
|
GET_SHADOW(3) |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
|
||||||
|
return 1.0; |
||||||
|
} |
||||||
|
#endif |
||||||
|
#else |
||||||
|
#define NUM_PSSM_SPLITS 0 |
||||||
|
|
||||||
|
const int pssmSliceOffset = 0; |
||||||
|
|
||||||
|
void Shadow_ProcessProjCoord(vec3 worldPos) { |
||||||
|
} |
||||||
|
|
||||||
|
void Shadow_ProcessPssmSlice() { |
||||||
|
} |
||||||
|
|
||||||
|
float Shadow_Process(int lightIndex, float lightType, float shadowMapIndex, |
||||||
|
vec3 lightVec, vec3 lightDir, |
||||||
|
vec3 worldPos, float invRadius) { |
||||||
|
return 1.0; |
||||||
|
} |
||||||
|
#endif |
@ -0,0 +1,206 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2018 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 jme3test.light; |
||||||
|
|
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.input.KeyInput; |
||||||
|
import com.jme3.input.controls.ActionListener; |
||||||
|
import com.jme3.input.controls.AnalogListener; |
||||||
|
import com.jme3.input.controls.KeyTrigger; |
||||||
|
import com.jme3.light.AmbientLight; |
||||||
|
import com.jme3.light.DirectionalLight; |
||||||
|
import com.jme3.light.PointLight; |
||||||
|
import com.jme3.light.SpotLight; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.material.TechniqueDef.LightMode; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.FastMath; |
||||||
|
import com.jme3.math.Quaternion; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.post.FilterPostProcessor; |
||||||
|
import com.jme3.post.filters.ToneMapFilter; |
||||||
|
import com.jme3.renderer.queue.RenderQueue.ShadowMode; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.shape.Box; |
||||||
|
import com.jme3.scene.shape.Quad; |
||||||
|
import com.jme3.shadow.next.InPassShadowRenderer; |
||||||
|
import com.jme3.system.AppSettings; |
||||||
|
|
||||||
|
public class TestInPassShadows extends SimpleApplication { |
||||||
|
|
||||||
|
private DirectionalLight dl; |
||||||
|
private SpotLight sl; |
||||||
|
private PointLight pl; |
||||||
|
private InPassShadowRenderer ipsr; |
||||||
|
private ToneMapFilter tmf; |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
TestInPassShadows app = new TestInPassShadows(); |
||||||
|
AppSettings settings = new AppSettings(true); |
||||||
|
settings.setGammaCorrection(true); |
||||||
|
app.setSettings(settings); |
||||||
|
app.start(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleInitApp() { |
||||||
|
renderManager.setPreferredLightMode(LightMode.SinglePassAndImageBased); |
||||||
|
renderManager.setSinglePassLightBatchSize(3); |
||||||
|
|
||||||
|
cam.setLocation(new Vector3f(8.079489f, 10.792628f, -6.714233f)); |
||||||
|
cam.setRotation(new Quaternion(0.38442945f, -0.35025623f, 0.16050051f, 0.8389125f)); |
||||||
|
flyCam.setMoveSpeed(5); |
||||||
|
|
||||||
|
tmf = new ToneMapFilter(new Vector3f(50, 50, 50)); |
||||||
|
FilterPostProcessor fpp = new FilterPostProcessor(assetManager); |
||||||
|
fpp.addFilter(tmf); |
||||||
|
viewPort.addProcessor(fpp); |
||||||
|
|
||||||
|
loadLights(); |
||||||
|
loadScene(); |
||||||
|
loadInputs(); |
||||||
|
} |
||||||
|
|
||||||
|
private void loadLights() { |
||||||
|
AmbientLight al = new AmbientLight(new ColorRGBA(0.2f, 0.2f, 0.3f, 1.0f).mult(2f)); |
||||||
|
rootNode.addLight(al); |
||||||
|
|
||||||
|
dl = new DirectionalLight(); |
||||||
|
dl.setDirection(new Vector3f(-1, -0.5f, -1).normalizeLocal()); |
||||||
|
dl.setColor(new ColorRGBA(1, 0.9f, 0.8f, 1).mult(2.5f)); |
||||||
|
rootNode.addLight(dl); |
||||||
|
|
||||||
|
sl = new SpotLight(); |
||||||
|
sl.setSpotRange(15); |
||||||
|
sl.setSpotInnerAngle(20 * FastMath.DEG_TO_RAD); |
||||||
|
sl.setSpotOuterAngle(25 * FastMath.DEG_TO_RAD); |
||||||
|
sl.setPosition(new Vector3f(-5.2193f, -0.5851393f, 4.831882f)); |
||||||
|
sl.setDirection(new Vector3f(0.8429418f, -0.42458484f, -0.33041906f)); |
||||||
|
sl.setColor(new ColorRGBA(0.5f, 0.7f, 1.0f, 1.0f).mult(50)); |
||||||
|
rootNode.addLight(sl); |
||||||
|
|
||||||
|
pl = new PointLight( |
||||||
|
new Vector3f(-0.10135013f, 1.9986207f, -2.0745828f), |
||||||
|
new ColorRGBA(0.5f, 0.3f, 0.1f, 1f).mult(20), |
||||||
|
30); |
||||||
|
rootNode.addLight(pl); |
||||||
|
|
||||||
|
ipsr = new InPassShadowRenderer(); |
||||||
|
ipsr.setTextureSize(512); |
||||||
|
ipsr.setPolyOffset(5, 0); |
||||||
|
ipsr.directional().setNumSplits(1); |
||||||
|
ipsr.addLight(dl); |
||||||
|
ipsr.addLight(sl); |
||||||
|
ipsr.addLight(pl); |
||||||
|
viewPort.addProcessor(ipsr); |
||||||
|
} |
||||||
|
|
||||||
|
private void loadScene() { |
||||||
|
Geometry box = new Geometry("Box", new Box(1, 1, 1)); |
||||||
|
box.setShadowMode(ShadowMode.CastAndReceive); |
||||||
|
Material boxMat = new Material(assetManager, "Common/MatDefs/Light/PBRLighting.j3md"); |
||||||
|
boxMat.setFloat("Roughness", 0.5f); |
||||||
|
boxMat.setFloat("Metallic", 0f); |
||||||
|
box.setMaterial(boxMat); |
||||||
|
rootNode.attachChild(box); |
||||||
|
|
||||||
|
Geometry box2 = box.clone(true); |
||||||
|
box2.move(3, 0, 0); |
||||||
|
rootNode.attachChild(box2); |
||||||
|
|
||||||
|
Geometry box3 = box.clone(true); |
||||||
|
box3.move(-3, 0, 0); |
||||||
|
rootNode.attachChild(box3); |
||||||
|
|
||||||
|
Geometry floor = new Geometry("floor", new Quad(100, 100)); |
||||||
|
floor.rotate(-FastMath.HALF_PI, 0, 0); |
||||||
|
floor.center(); |
||||||
|
floor.move(0, -1, 0); |
||||||
|
floor.setShadowMode(ShadowMode.Receive); |
||||||
|
Material floorMat = new Material(assetManager, "Common/MatDefs/Light/PBRLighting.j3md"); |
||||||
|
floorMat.setFloat("Roughness", 0.5f); |
||||||
|
floorMat.setFloat("Metallic", 0f); |
||||||
|
floor.setMaterial(floorMat); |
||||||
|
rootNode.attachChild(floor); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean moveLight = false; |
||||||
|
|
||||||
|
private void loadInputs() { |
||||||
|
inputManager.addMapping("MoveLight", new KeyTrigger(KeyInput.KEY_SPACE)); |
||||||
|
inputManager.addListener(new ActionListener() { |
||||||
|
@Override |
||||||
|
public void onAction(String name, boolean isPressed, float tpf) { |
||||||
|
moveLight = isPressed; |
||||||
|
} |
||||||
|
}, "MoveLight"); |
||||||
|
|
||||||
|
inputManager.addMapping("OffsetFactorUp", new KeyTrigger(KeyInput.KEY_U)); |
||||||
|
inputManager.addMapping("OffsetFactorDown", new KeyTrigger(KeyInput.KEY_J)); |
||||||
|
inputManager.addMapping("OffsetUnitsUp", new KeyTrigger(KeyInput.KEY_I)); |
||||||
|
inputManager.addMapping("OffsetUnitsDown", new KeyTrigger(KeyInput.KEY_K)); |
||||||
|
inputManager.addListener(new AnalogListener() { |
||||||
|
private float factor, units; |
||||||
|
@Override |
||||||
|
public void onAnalog(String name, float value, float tpf) { |
||||||
|
switch (name) { |
||||||
|
case "OffsetFactorUp": |
||||||
|
factor += tpf * 5f; |
||||||
|
break; |
||||||
|
case "OffsetFactorDown": |
||||||
|
factor -= tpf * 5f; |
||||||
|
break; |
||||||
|
case "OffsetUnitsUp": |
||||||
|
units += tpf * 50f; |
||||||
|
break; |
||||||
|
case "OffsetUnitsDown": |
||||||
|
units -= tpf * 50f; |
||||||
|
break; |
||||||
|
} |
||||||
|
ipsr.setPolyOffset(factor, units); |
||||||
|
System.out.println("PolyOffset(" + factor + ", " + units + ")"); |
||||||
|
} |
||||||
|
|
||||||
|
}, "OffsetFactorUp", "OffsetFactorDown", "OffsetUnitsUp", "OffsetUnitsDown"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleUpdate(float tpf) { |
||||||
|
if (moveLight) { |
||||||
|
sl.setPosition(cam.getLocation()); |
||||||
|
sl.setDirection(cam.getDirection()); |
||||||
|
System.out.println(sl.getPosition()); |
||||||
|
System.out.println(sl.getDirection()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue