Changed the way post shadow pass is done. It's now a technique of the lighting material definition.

This allow to have shadows that fully works with partially transparent objects (like trees).
If a material does not have the postShadow technique, the renderer uses the fallback material (like before).

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9279 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 13 years ago
parent 7445565df3
commit bf55974bf4
  1. 67
      engine/src/core-data/Common/MatDefs/Light/Lighting.j3md
  2. 44
      engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM.frag
  3. 9
      engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM.vert
  4. 22
      engine/src/core-data/Common/MatDefs/Shadow/PostShadowPSSM15.frag
  5. 20
      engine/src/core-data/Common/MatDefs/Shadow/PreShadow.frag
  6. 77
      engine/src/core/com/jme3/shadow/PssmShadowRenderer.java
  7. 57
      engine/src/test/jme3test/light/TestTransparentShadow.java

@ -99,6 +99,25 @@ MaterialDef Phong Lighting {
// the env map is a spheremap and not a cube map // the env map is a spheremap and not a cube map
Boolean EnvMapAsSphereMap Boolean EnvMapAsSphereMap
//shadows
Int FilterMode
Boolean HardwareShadows
Texture2D ShadowMap0
Texture2D ShadowMap1
Texture2D ShadowMap2
Texture2D ShadowMap3
Float ShadowIntensity
Vector4 Splits
Matrix4 LightViewProjectionMatrix0
Matrix4 LightViewProjectionMatrix1
Matrix4 LightViewProjectionMatrix2
Matrix4 LightViewProjectionMatrix3
Float PCFEdge
} }
Technique { Technique {
@ -156,7 +175,8 @@ MaterialDef Phong Lighting {
} }
Defines { Defines {
DIFFUSEMAP_ALPHA : DiffuseMap COLOR_MAP : ColorMap
DISCARD_ALPHA : AlphaDiscardThreshold
} }
RenderState { RenderState {
@ -169,6 +189,51 @@ MaterialDef Phong Lighting {
} }
Technique PostShadow15{
VertexShader GLSL150: Common/MatDefs/Shadow/PostShadowPSSM.vert
FragmentShader GLSL150: Common/MatDefs/Shadow/PostShadowPSSM15.frag
WorldParameters {
WorldViewProjectionMatrix
WorldMatrix
}
Defines {
HARDWARE_SHADOWS : HardwareShadows
FILTER_MODE : FilterMode
PCFEDGE : PCFEdge
DISCARD_ALPHA : AlphaDiscardThreshold
COLOR_MAP : ColorMap
}
RenderState {
Blend Modulate
}
}
Technique PostShadow{
VertexShader GLSL100: Common/MatDefs/Shadow/PostShadowPSSM.vert
FragmentShader GLSL100: Common/MatDefs/Shadow/PostShadowPSSM.frag
WorldParameters {
WorldViewProjectionMatrix
WorldMatrix
}
Defines {
HARDWARE_SHADOWS : HardwareShadows
FILTER_MODE : FilterMode
PCFEDGE : PCFEdge
DISCARD_ALPHA : AlphaDiscardThreshold
COLOR_MAP : ColorMap
}
RenderState {
Blend Modulate
}
}
Technique PreNormalPass { Technique PreNormalPass {
VertexShader GLSL100 : Common/MatDefs/SSAO/normal.vert VertexShader GLSL100 : Common/MatDefs/SSAO/normal.vert

@ -27,6 +27,7 @@
#define KERNEL 8.0 #define KERNEL 8.0
#endif #endif
uniform SHADOWMAP m_ShadowMap0; uniform SHADOWMAP m_ShadowMap0;
uniform SHADOWMAP m_ShadowMap1; uniform SHADOWMAP m_ShadowMap1;
uniform SHADOWMAP m_ShadowMap2; uniform SHADOWMAP m_ShadowMap2;
@ -43,7 +44,7 @@ varying vec4 projCoord3;
varying float shadowPosition; varying float shadowPosition;
const float texSize = 1024.0; float texSize = 1024.0;
const float pixSize = 1.0 / texSize; const float pixSize = 1.0 / texSize;
const vec2 pixSize2 = vec2(pixSize); const vec2 pixSize2 = vec2(pixSize);
@ -64,6 +65,11 @@ float Shadow_BorderCheck(in vec2 coord){
} }
float Shadow_DoDither_2x2(in SHADOWMAP tex, in vec4 projCoord){ float Shadow_DoDither_2x2(in SHADOWMAP tex, in vec4 projCoord){
float border = Shadow_BorderCheck(projCoord.xy);
if (border > 0.0)
return 1.0;
float shadow = 0.0; float shadow = 0.0;
vec2 o = mod(floor(gl_FragCoord.xy), 2.0); vec2 o = mod(floor(gl_FragCoord.xy), 2.0);
shadow += Shadow_DoShadowCompareOffset(tex,projCoord,vec2(-1.5, 1.5) + o); shadow += Shadow_DoShadowCompareOffset(tex,projCoord,vec2(-1.5, 1.5) + o);
@ -75,6 +81,9 @@ float Shadow_DoDither_2x2(in SHADOWMAP tex, in vec4 projCoord){
} }
float Shadow_DoBilinear_2x2(in SHADOWMAP tex, in vec4 projCoord){ float Shadow_DoBilinear_2x2(in SHADOWMAP tex, in vec4 projCoord){
float border = Shadow_BorderCheck(projCoord.xy);
if (border > 0.0)
return 1.0;
vec4 gather = vec4(0.0); vec4 gather = vec4(0.0);
gather.x = Shadow_DoShadowCompareOffset(tex, projCoord, vec2(0.0, 0.0)); gather.x = Shadow_DoShadowCompareOffset(tex, projCoord, vec2(0.0, 0.0));
gather.y = Shadow_DoShadowCompareOffset(tex, projCoord, vec2(1.0, 0.0)); gather.y = Shadow_DoShadowCompareOffset(tex, projCoord, vec2(1.0, 0.0));
@ -88,12 +97,15 @@ float Shadow_DoBilinear_2x2(in SHADOWMAP tex, in vec4 projCoord){
float Shadow_DoPCF(in SHADOWMAP tex, in vec4 projCoord){ float Shadow_DoPCF(in SHADOWMAP tex, in vec4 projCoord){
float shadow = 0.0; float shadow = 0.0;
float border = Shadow_BorderCheck(projCoord.xy);
if (border > 0.0)
return 1.0;
float bound = KERNEL * 0.5 - 0.5; float bound = KERNEL * 0.5 - 0.5;
bound *= PCFEDGE; bound *= PCFEDGE;
for (float y = -bound; y <= bound; y += PCFEDGE){ for (float y = -bound; y <= bound; y += PCFEDGE){
for (float x = -bound; x <= bound; x += PCFEDGE){ for (float x = -bound; x <= bound; x += PCFEDGE){
shadow += clamp(Shadow_DoShadowCompareOffset(tex,projCoord,vec2(x,y)) + shadow += clamp(Shadow_DoShadowCompareOffset(tex,projCoord,vec2(x,y)) +
Shadow_BorderCheck(projCoord.xy), border,
0.0, 1.0); 0.0, 1.0);
} }
} }
@ -102,18 +114,46 @@ float Shadow_DoPCF(in SHADOWMAP tex, in vec4 projCoord){
return shadow; return shadow;
} }
#ifdef DISCARD_ALPHA
#ifdef COLOR_MAP
uniform sampler2D m_ColorMap;
#else
uniform sampler2D m_DiffuseMap;
#endif
uniform float m_AlphaDiscardThreshold;
varying vec2 texCoord;
#endif
void main(){ void main(){
#ifdef DISCARD_ALPHA
#ifdef COLOR_MAP
float alpha = texture2D(m_ColorMap,texCoord).a;
#else
float alpha = texture2D(m_DiffuseMap,texCoord).a;
#endif
if(alpha<=m_AlphaDiscardThreshold){
discard;
}
#endif
vec4 shadowPerSplit = vec4(0.0); vec4 shadowPerSplit = vec4(0.0);
shadowPerSplit.x = GETSHADOW(m_ShadowMap0, projCoord0); shadowPerSplit.x = GETSHADOW(m_ShadowMap0, projCoord0);
shadowPerSplit.y = GETSHADOW(m_ShadowMap1, projCoord1); shadowPerSplit.y = GETSHADOW(m_ShadowMap1, projCoord1);
shadowPerSplit.z = GETSHADOW(m_ShadowMap2, projCoord2); shadowPerSplit.z = GETSHADOW(m_ShadowMap2, projCoord2);
shadowPerSplit.w = GETSHADOW(m_ShadowMap3, projCoord3); shadowPerSplit.w = GETSHADOW(m_ShadowMap3, projCoord3);
vec4 less = step( shadowPosition, m_Splits ); vec4 less = step( shadowPosition, m_Splits );
vec4 more = vec4(1.0) - step( shadowPosition, vec4(0.0, m_Splits.xyz) ); vec4 more = vec4(1.0) - step( shadowPosition, vec4(0.0, m_Splits.xyz) );
float shadow = dot(shadowPerSplit, less * more ); float shadow = dot(shadowPerSplit, less * more );
shadow = shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity); shadow = shadow * m_ShadowIntensity + (1.0 - m_ShadowIntensity);
gl_FragColor = vec4(shadow, shadow, shadow, 1.0); gl_FragColor = vec4(shadow, shadow, shadow, 1.0);
//gl_FragColor = vec4(alpha, alpha, alpha, 1.0);
} }

@ -13,7 +13,12 @@ varying vec4 projCoord3;
varying float shadowPosition; varying float shadowPosition;
varying vec2 texCoord;
attribute vec3 inPosition; attribute vec3 inPosition;
#ifdef DISCARD_ALPHA
attribute vec2 inTexCoord;
#endif
const mat4 biasMat = mat4(0.5, 0.0, 0.0, 0.0, const mat4 biasMat = mat4(0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0,
@ -28,7 +33,9 @@ void main(){
// get the vertex in world space // get the vertex in world space
vec4 worldPos = g_WorldMatrix * vec4(inPosition, 1.0); vec4 worldPos = g_WorldMatrix * vec4(inPosition, 1.0);
#ifdef DISCARD_ALPHA
texCoord = inTexCoord;
#endif
// populate the light view matrices array and convert vertex to light viewProj space // populate the light view matrices array and convert vertex to light viewProj space
projCoord0 = biasMat * m_LightViewProjectionMatrix0 * worldPos; projCoord0 = biasMat * m_LightViewProjectionMatrix0 * worldPos;
projCoord1 = biasMat * m_LightViewProjectionMatrix1 * worldPos; projCoord1 = biasMat * m_LightViewProjectionMatrix1 * worldPos;

@ -120,9 +120,31 @@ float Shadow_DoPCF(in SHADOWMAP tex, in vec4 projCoord){
return shadow; return shadow;
} }
#ifdef DISCARD_ALPHA
#ifdef COLOR_MAP
uniform sampler2D m_ColorMap;
#else
uniform sampler2D m_DiffuseMap;
#endif
uniform float m_AlphaDiscardThreshold;
varying vec2 texCoord;
#endif
void main(){ void main(){
float shadow = 0.0; float shadow = 0.0;
#ifdef DISCARD_ALPHA
#ifdef COLOR_MAP
float alpha = texture2D(m_ColorMap,texCoord).a;
#else
float alpha = texture2D(m_DiffuseMap,texCoord).a;
#endif
if(alpha < m_AlphaDiscardThreshold){
discard;
}
#endif
if(shadowPosition < m_Splits.x){ if(shadowPosition < m_Splits.x){
shadow = GETSHADOW(m_ShadowMap0, projCoord0); shadow = GETSHADOW(m_ShadowMap0, projCoord0);
}else if( shadowPosition < m_Splits.y){ }else if( shadowPosition < m_Splits.y){

@ -1,14 +1,26 @@
varying vec2 texCoord; varying vec2 texCoord;
#ifdef DIFFUSEMAP_ALPHA #ifdef DISCARD_ALPHA
uniform sampler2D m_DiffuseMap; #ifdef COLOR_MAP
uniform sampler2D m_ColorMap;
#else
uniform sampler2D m_DiffuseMap;
#endif
uniform float m_AlphaDiscardThreshold;
#endif #endif
void main(){ void main(){
#ifdef DIFFUSEMAP_ALPHA #ifdef DISCARD_ALPHA
if (texture2D(m_DiffuseMap, texCoord).a <= 0.50) #ifdef COLOR_MAP
if (texture2D(m_ColorMap, texCoord).a <= m_AlphaDiscardThreshold){
discard;
}
#else
if (texture2D(m_DiffuseMap, texCoord).a <= m_AlphaDiscardThreshold){
discard; discard;
}
#endif
#endif #endif
gl_FragColor = vec4(1.0); gl_FragColor = vec4(1.0);

@ -31,11 +31,13 @@ package com.jme3.shadow;
import com.jme3.asset.AssetManager; import com.jme3.asset.AssetManager;
import com.jme3.material.Material; import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.post.SceneProcessor; import com.jme3.post.SceneProcessor;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.renderer.Caps;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.renderer.Renderer; import com.jme3.renderer.Renderer;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
@ -140,6 +142,12 @@ public class PssmShadowRenderer implements SceneProcessor {
private Picture[] dispPic; private Picture[] dispPic;
private Vector3f[] points = new Vector3f[8]; private Vector3f[] points = new Vector3f[8];
private boolean flushQueues = true; private boolean flushQueues = true;
//render state for post shadow pass
private RenderState state = new RenderState();
// define if the fallback material should be used.
private boolean needsfallBackMaterial = false;
//Name of the post material technique
private String postTechniqueName = "PostShadow";
/** /**
* Create a PSSM Shadow Renderer * Create a PSSM Shadow Renderer
@ -208,13 +216,17 @@ public class PssmShadowRenderer implements SceneProcessor {
for (int i = 0; i < points.length; i++) { for (int i = 0; i < points.length; i++) {
points[i] = new Vector3f(); points[i] = new Vector3f();
} }
//initializing render state for post shadow pass (modulade blending and cullmode of for back faces )
state.setBlendMode(RenderState.BlendMode.Modulate);
state.setFaceCullMode(RenderState.FaceCullMode.Off);
} }
/** /**
* Sets the filtering mode for shadow edges see {@link FilterMode} for more info * Sets the filtering mode for shadow edges see {@link FilterMode} for more info
* @param filterMode * @param filterMode
*/ */
public void setFilterMode(FilterMode filterMode) { final public void setFilterMode(FilterMode filterMode) {
if (filterMode == null) { if (filterMode == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
@ -243,7 +255,7 @@ public class PssmShadowRenderer implements SceneProcessor {
* sets the shadow compare mode see {@link CompareMode} for more info * sets the shadow compare mode see {@link CompareMode} for more info
* @param compareMode * @param compareMode
*/ */
public void setCompareMode(CompareMode compareMode) { final public void setCompareMode(CompareMode compareMode) {
if (compareMode == null) { if (compareMode == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
@ -306,6 +318,12 @@ public class PssmShadowRenderer implements SceneProcessor {
public void initialize(RenderManager rm, ViewPort vp) { public void initialize(RenderManager rm, ViewPort vp) {
renderManager = rm; renderManager = rm;
viewPort = vp; viewPort = vp;
//checking for caps to chosse the appropriate post material technique
if (renderManager.getRenderer().getCaps().contains(Caps.GLSL150)) {
postTechniqueName = "PostShadow15";
}else{
postTechniqueName = "PostShadow";
}
} }
public boolean isInitialized() { public boolean isInitialized() {
@ -430,15 +448,24 @@ public class PssmShadowRenderer implements SceneProcessor {
public void postFrame(FrameBuffer out) { public void postFrame(FrameBuffer out) {
Camera cam = viewPort.getCamera(); Camera cam = viewPort.getCamera();
if (!noOccluders) { if (!noOccluders) {
postshadowMat.setColor("Splits", splits); //setting params to recieving geometry list
for (int i = 0; i < nbSplits; i++) { setMatParams();
postshadowMat.setMatrix4("LightViewProjectionMatrix" + i, lightViewProjectionsMatrices[i]); //some materials in the scene does not have a post shadow technique so we're using the fall back material
} if (needsfallBackMaterial) {
renderManager.setForcedMaterial(postshadowMat); renderManager.setForcedMaterial(postshadowMat);
}
//forcing the post shadow technique and render state
renderManager.setForcedTechnique(postTechniqueName);
renderManager.setForcedRenderState(state);
//rendering the post shadow pass
viewPort.getQueue().renderShadowQueue(ShadowMode.Receive, renderManager, cam, flushQueues); viewPort.getQueue().renderShadowQueue(ShadowMode.Receive, renderManager, cam, flushQueues);
//resetting renderManager settings
renderManager.setForcedTechnique(null);
renderManager.setForcedMaterial(null); renderManager.setForcedMaterial(null);
renderManager.setForcedRenderState(null);
renderManager.setCamera(cam, false); renderManager.setCamera(cam, false);
} }
@ -447,6 +474,42 @@ public class PssmShadowRenderer implements SceneProcessor {
} }
} }
private void setMatParams() {
GeometryList l = viewPort.getQueue().getShadowQueueContent(ShadowMode.Receive);
//iteratin throught all the geometries of the list to set the material params
for (int i = 0; i < l.size(); i++) {
Material mat = l.get(i).getMaterial();
//checking if the material has the post technique and setting the params.
if (mat.getMaterialDef().getTechniqueDef(postTechniqueName) != null) {
mat.setColor("Splits", splits);
postshadowMat.setColor("Splits", splits);
for (int j = 0; j < nbSplits; j++) {
mat.setMatrix4("LightViewProjectionMatrix" + j, lightViewProjectionsMatrices[j]);
mat.setTexture("ShadowMap" + j, shadowMaps[j]);
}
mat.setBoolean("HardwareShadows", compareMode == CompareMode.Hardware);
mat.setInt("FilterMode", filterMode.ordinal());
mat.setFloat("PCFEdge", edgesThickness);
mat.setFloat("ShadowIntensity", shadowIntensity);
} else {
needsfallBackMaterial = true;
}
}
//At least one material of the receiving geoms does not support the post shadow techniques
//so we fall back to the forced material solution (transparent shadows won't be supported for these objects)
if (needsfallBackMaterial) {
postshadowMat.setColor("Splits", splits);
for (int j = 0; j < nbSplits; j++) {
postshadowMat.setMatrix4("LightViewProjectionMatrix" + j, lightViewProjectionsMatrices[j]);
}
}
}
public void preFrame(float tpf) { public void preFrame(float tpf) {
} }
@ -511,7 +574,7 @@ public class PssmShadowRenderer implements SceneProcessor {
* default is 0.7 * default is 0.7
* @param shadowIntensity the darkness of the shadow * @param shadowIntensity the darkness of the shadow
*/ */
public void setShadowIntensity(float shadowIntensity) { final public void setShadowIntensity(float shadowIntensity) {
this.shadowIntensity = shadowIntensity; this.shadowIntensity = shadowIntensity;
postshadowMat.setFloat("ShadowIntensity", shadowIntensity); postshadowMat.setFloat("ShadowIntensity", shadowIntensity);
} }

@ -42,10 +42,9 @@ import com.jme3.math.*;
import com.jme3.renderer.queue.RenderQueue.Bucket; import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.renderer.queue.RenderQueue.ShadowMode; import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry; import com.jme3.scene.Geometry;
import com.jme3.scene.SceneGraphVisitorAdapter;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.control.LodControl;
import com.jme3.scene.shape.Quad; import com.jme3.scene.shape.Quad;
import com.jme3.scene.shape.Sphere;
import com.jme3.shadow.PssmShadowRenderer; import com.jme3.shadow.PssmShadowRenderer;
import com.jme3.shadow.PssmShadowRenderer.CompareMode; import com.jme3.shadow.PssmShadowRenderer.CompareMode;
import com.jme3.shadow.PssmShadowRenderer.FilterMode; import com.jme3.shadow.PssmShadowRenderer.FilterMode;
@ -59,15 +58,16 @@ public class TestTransparentShadow extends SimpleApplication {
public void simpleInitApp() { public void simpleInitApp() {
cam.setLocation(new Vector3f(2.0606942f, 3.20342f, 6.7860126f)); cam.setLocation(new Vector3f(5.700248f, 6.161693f, 5.1404157f));
cam.setRotation(new Quaternion(-0.017481906f, 0.98241085f, -0.12393151f, -0.13857932f)); cam.setRotation(new Quaternion(-0.09441641f, 0.8993388f, -0.24089815f, -0.35248178f));
viewPort.setBackgroundColor(ColorRGBA.DarkGray); viewPort.setBackgroundColor(ColorRGBA.DarkGray);
Quad q = new Quad(20, 20); Quad q = new Quad(20, 20);
q.scaleTextureCoordinates(Vector2f.UNIT_XY.mult(5)); q.scaleTextureCoordinates(Vector2f.UNIT_XY.mult(10));
Geometry geom = new Geometry("floor", q); Geometry geom = new Geometry("floor", q);
Material mat = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m"); Material mat = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m");
mat.setFloat("Shininess", 0);
geom.setMaterial(mat); geom.setMaterial(mat);
geom.rotate(-FastMath.HALF_PI, 0, 0); geom.rotate(-FastMath.HALF_PI, 0, 0);
@ -76,34 +76,21 @@ public class TestTransparentShadow extends SimpleApplication {
rootNode.attachChild(geom); rootNode.attachChild(geom);
// create the geometry and attach it // create the geometry and attach it
Spatial teaGeom = assetManager.loadModel("Models/Tree/Tree.mesh.j3o"); Spatial tree = assetManager.loadModel("Models/Tree/Tree.mesh.j3o");
teaGeom.setQueueBucket(Bucket.Transparent); tree.setQueueBucket(Bucket.Transparent);
teaGeom.setShadowMode(ShadowMode.Cast); tree.setShadowMode(ShadowMode.CastAndReceive);
teaGeom.depthFirstTraversal(new SceneGraphVisitorAdapter(){
@Override
public void visit(Geometry geom) {
LodControl lodCtrl = new LodControl();
lodCtrl.setTrisPerPixel(0.25f);
geom.addControl(lodCtrl);
}
});
AmbientLight al = new AmbientLight(); AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(2)); al.setColor(ColorRGBA.White.mult(0.7f));
rootNode.addLight(al); rootNode.addLight(al);
DirectionalLight dl1 = new DirectionalLight(); DirectionalLight dl1 = new DirectionalLight();
dl1.setDirection(new Vector3f(1, -1, 1).normalizeLocal()); dl1.setDirection(new Vector3f(0, -1, 0.5f).normalizeLocal());
dl1.setColor(new ColorRGBA(0.965f, 0.949f, 0.772f, 1f).mult(0.7f)); dl1.setColor(ColorRGBA.White.mult(1.5f));
rootNode.addLight(dl1); rootNode.addLight(dl1);
DirectionalLight dl = new DirectionalLight(); rootNode.attachChild(tree);
dl.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
dl.setColor(new ColorRGBA(0.965f, 0.949f, 0.772f, 1f).mult(0.7f));
rootNode.addLight(dl);
rootNode.attachChild(teaGeom);
/** Uses Texture from jme3-test-data library! */ /** Uses Texture from jme3-test-data library! */
ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30); ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);
@ -125,16 +112,26 @@ public class TestTransparentShadow extends SimpleApplication {
fire.setLocalTranslation(1.0f, 0, 1.0f); fire.setLocalTranslation(1.0f, 0, 1.0f);
fire.setLocalScale(0.3f); fire.setLocalScale(0.3f);
fire.setQueueBucket(Bucket.Translucent); fire.setQueueBucket(Bucket.Translucent);
rootNode.attachChild(fire); // rootNode.attachChild(fire);
Material mat2 = assetManager.loadMaterial("Common/Materials/RedColor.j3m");
Geometry ball = new Geometry("sphere", new Sphere(16, 16, 0.5f));
ball.setMaterial(mat2);
ball.setShadowMode(ShadowMode.CastAndReceive);
rootNode.attachChild(ball);
ball.setLocalTranslation(-1.0f, 1.5f, 1.0f);
PssmShadowRenderer pssmRenderer = new PssmShadowRenderer(assetManager, 1024, 1); PssmShadowRenderer pssmRenderer = new PssmShadowRenderer(assetManager, 1024, 1);
pssmRenderer.setDirection(new Vector3f(0.01f, -1f, 0.01f).normalizeLocal()); pssmRenderer.setDirection(dl1.getDirection());
pssmRenderer.setLambda(0.55f); pssmRenderer.setLambda(0.55f);
pssmRenderer.setShadowIntensity(0.6f); pssmRenderer.setShadowIntensity(0.8f);
pssmRenderer.setCompareMode(CompareMode.Software); pssmRenderer.setCompareMode(CompareMode.Software);
pssmRenderer.setFilterMode(FilterMode.PCF4); pssmRenderer.setFilterMode(FilterMode.PCF4);
pssmRenderer.displayDebug(); //pssmRenderer.displayDebug();
viewPort.addProcessor(pssmRenderer); viewPort.addProcessor(pssmRenderer);
} }
} }

Loading…
Cancel
Save