Hello all,
I’m testing the Shadow renderer, and I can get okay results with the Modulative lighting method, but the contrast is a bit too high. However, when I switch to Additive lighting, the light becomes so faint that no shadows are produced. I have experimented with many variations on the diffuse and ambient lighting, the global ambient light, and even the attenuation settings in the hopes of brightening the light enough to cast a shadow in Additive mode, to no avail. (And I would prefer to continue to use a PointLight, rather than DirectionLight, to cast shadows.) I’ve searched through the forums, but I am at a loss; thus I turn to you, my fellow jMonkeyEngineers… any ideas on fixing the code below to cast nice shadows with Additive lighting?
Thanks!
/**
- Shadow example.
-
@author Stemkoski
*/
public class ShadowDemo extends SimpleGame
{
// a geometric shape that will be rendered
Sphere mySphere;
PointLight pl;
Sphere lightBulb;
private ShadowedRenderPass shadowPass = new ShadowedRenderPass();
private BasicPassManager pManager;
public static void main(String[] args)
{
ShadowDemo app = new ShadowDemo();
app.setConfigShowMode(ConfigShowMode.AlwaysShow);
app.start();
}
protected void simpleInitGame()
{
stencilBits = 4;
// make the standard cursor visible.
org.lwjgl.input.Mouse.setGrabbed(false);
// SimpleGame class defaults mouse behavior to rotate view; here we disable this.
((FirstPersonHandler)input).getMouseLookHandler().setEnabled(false);
// reposition camera
cam.setLocation( new Vector3f(1,1,12) );
// create a material to apply to geometric objects, use objects' default color,
// apply to front and back, and assign rendering to root node
MaterialState customMaterial = display.getRenderer().createMaterialState();
customMaterial.setColorMaterial(MaterialState.ColorMaterial.AmbientAndDiffuse);
customMaterial.setMaterialFace(MaterialState.MaterialFace.FrontAndBack);
rootNode.setRenderState(customMaterial);
mySphere = new Sphere("s", new Vector3f(0,0,0), 50, 50, 1 );
mySphere.setSolidColor( ColorRGBA.blue );
lightBulb = new Sphere("s", new Vector3f(0,0,0), 6, 6, 0.25f );
lightBulb.setSolidColor( ColorRGBA.white );
rootNode.attachChild(lightBulb);
// create a floor structure
Box floor = new Box("b", new Vector3f(-20,-2,-20), new Vector3f(20,-9.9f,20));
floor.setSolidColor( ColorRGBA.gray );
rootNode.attachChild( floor );
// Another light so there is no full darkness.
pl = new PointLight();
pl.setEnabled(true);
pl.setDiffuse( new ColorRGBA(0.9f, 0.9f, 0.9f, 0.0f) );
pl.setAmbient( new ColorRGBA(0.2f, 0.2f, 0.2f, 0.6f) );
pl.setLocation(new Vector3f(1, 5, 1));
pl.setShadowCaster(true);
lightState.detachAll();
lightState.attach(pl);
lightState.setGlobalAmbient(new ColorRGBA(0.3f, 0.3f, 0.3f, 0.1f));
Node occluders = new Node("Occluders");
rootNode.attachChild(occluders);
occluders.attachChild( mySphere );
// pass renderer setup
pManager = new BasicPassManager();
shadowPass.add(rootNode);
shadowPass.addOccluder(occluders);
shadowPass.setRenderShadows(true);
// Modulative: contrast is too high.
// Additive: results are too dark, resulting in no shadows
// What to do?
shadowPass.setLightingMethod(LightingMethod.Modulative);
pManager.add(shadowPass);
// remove all pre-existing key assignments
KeyBindingManager.getKeyBindingManager().removeAll();
KeyBindingManager.getKeyBindingManager().set( "exit", KeyInput.KEY_ESCAPE );
KeyBindingManager.getKeyBindingManager().set( "toggle_wire", KeyInput.KEY_F1 );
KeyBindingManager.getKeyBindingManager().set( "toggle_bounds", KeyInput.KEY_F2 );
KeyBindingManager.getKeyBindingManager().set( "sphereRed", KeyInput.KEY_1 );
KeyBindingManager.getKeyBindingManager().set( "sphereMulti", KeyInput.KEY_2 );
KeyBindingManager.getKeyBindingManager().set( "+", KeyInput.KEY_4 );
KeyBindingManager.getKeyBindingManager().set( "-", KeyInput.KEY_5 );
// light translation
KeyBindingManager.getKeyBindingManager().set( "lightTranslateUp", KeyInput.KEY_I );
KeyBindingManager.getKeyBindingManager().set( "lightTranslateDown", KeyInput.KEY_K );
KeyBindingManager.getKeyBindingManager().set( "lightTranslateLeft", KeyInput.KEY_J );
KeyBindingManager.getKeyBindingManager().set( "lightTranslateRight", KeyInput.KEY_L );
KeyBindingManager.getKeyBindingManager().set( "lightTranslateForward", KeyInput.KEY_U );
KeyBindingManager.getKeyBindingManager().set( "lightTranslateBackward", KeyInput.KEY_M );
// node translation relative to camera
KeyBindingManager.getKeyBindingManager().set( "nodeTranslateUp", KeyInput.KEY_W );
KeyBindingManager.getKeyBindingManager().set( "nodeTranslateDown", KeyInput.KEY_S );
KeyBindingManager.getKeyBindingManager().set( "nodeTranslateLeft", KeyInput.KEY_A );
KeyBindingManager.getKeyBindingManager().set( "nodeTranslateRight", KeyInput.KEY_D );
KeyBindingManager.getKeyBindingManager().set( "nodeTranslateForward", KeyInput.KEY_Q );
KeyBindingManager.getKeyBindingManager().set( "nodeTranslateBackward", KeyInput.KEY_Z );
}
protected void simpleUpdate()
{
if (KeyBindingManager.getKeyBindingManager().isValidCommand("sphereRed", false))
mySphere.setSolidColor( ColorRGBA.red );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("sphereMulti"))
mySphere.setRandomColors();
float speed = 2*tpf;
if (KeyBindingManager.getKeyBindingManager().isValidCommand("nodeTranslateUp"))
mySphere.getLocalTranslation().addLocal( cam.getUp().clone().mult(speed) );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("nodeTranslateDown"))
mySphere.getLocalTranslation().addLocal( cam.getUp().clone().mult(-speed) );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("nodeTranslateLeft"))
mySphere.getLocalTranslation().addLocal( cam.getLeft().clone().mult(speed) );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("nodeTranslateRight"))
mySphere.getLocalTranslation().addLocal( cam.getLeft().clone().mult(-speed) );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("nodeTranslateForward"))
mySphere.getLocalTranslation().addLocal( cam.getDirection().clone().mult(speed) );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("nodeTranslateBackward"))
mySphere.getLocalTranslation().addLocal( cam.getDirection().clone().mult(-speed) );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("lightTranslateUp"))
pl.getLocation().addLocal( cam.getUp().clone().mult(speed) );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("lightTranslateDown"))
pl.getLocation().addLocal( cam.getUp().clone().mult(-speed) );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("lightTranslateLeft"))
pl.getLocation().addLocal( cam.getLeft().clone().mult(speed) );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("lightTranslateRight"))
pl.getLocation().addLocal( cam.getLeft().clone().mult(-speed) );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("lightTranslateForward"))
pl.getLocation().addLocal( cam.getDirection().clone().mult(speed) );
if (KeyBindingManager.getKeyBindingManager().isValidCommand("lightTranslateBackward"))
pl.getLocation().addLocal( cam.getDirection().clone().mult(-speed) );
lightBulb.setLocalTranslation( pl.getLocation() );
pManager.updatePasses(tpf);
}
protected void simpleRender()
{
/** Have the PassManager render. */
pManager.renderPasses( display.getRenderer() );
}
}