Hi everyone. I’m newbie in jMonkey and I’m trying to build a 3d environment for my game.
I’ve just implemented a DirectionalLight and enabled shadows. But weird thing happens when camera passes through the shadows.
This is before camera is passing through the shadow. Everything is normal and shadows are OK.
This is while camera is passing through the shadow. I think because the object that is owner of the is culled the shadow is culled too. If the problem is this, why the object is culled so early?
I really don’t understand what is happening, I played with culling settings but i couldn’t manage to correct this…
And I have a second problem. As I said before I’m using DirectionalLight. But the brightness of the light is too low, so it cannot manage to provide a shiny and sunny day environment… I’ve used more than one lights with only one of them casting shadows. Is there any chance to play with the brightness of the light or am I doing something wrong? I mostly used codes from examples and I’m really stuk in here any help please?
package com.game;
import java.util.HashMap;
import jmetest.flagrushtut.lesson9.Lesson9;
import com.jme.app.BaseGame;
import com.jme.image.Texture;
import com.jme.input.ChaseCamera;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.thirdperson.ThirdPersonMouseLook;
import com.jme.light.DirectionalLight;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.BasicPassManager;
import com.jme.renderer.pass.RenderPass;
import com.jme.renderer.pass.ShadowedRenderPass;
import com.jme.scene.Node;
import com.jme.scene.SceneElement;
import com.jme.scene.Skybox;
import com.jme.scene.Text;
import com.jme.scene.state.CullState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.RenderState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.TextureManager;
import com.jme.util.Timer;
import com.game.extensions.jme.ModelFileLoader;
import com.game.test.objects.TestCar;
import com.game.test.objects.TestInputHandler;
import com.game.test.objects.TestLevel;
/**
* @author randomhero
*/
public class LightTestMain extends BaseGame {
protected InputHandler input;
protected Timer timer;
private Camera cam;
private ChaseCamera chaser;
// display attributes for the window. We will keep these values
// to allow the user to change them
private int width, height, depth, freq;
private boolean fullscreen;
private static ShadowedRenderPass shadowPass = new ShadowedRenderPass();
private BasicPassManager passManager;
// the root node of the scene graph
private Node scene;
private TestCar playerCar;
private TestLevel testLevel;
private Skybox skybox;
protected Text fps;
protected Node fpsNode;
protected float tpf;
protected StringBuffer updateStringBuffer = new StringBuffer(30);
protected StringBuffer tempBuffer = new StringBuffer();
public static void main(String[] args) {
LightTestMain app = new LightTestMain();
app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG, Lesson9.class
.getClassLoader().getResource("images/yogurt.jpg"));
// new ShadowTweaker(shadowPass).setVisible(true);
app.start();
}
protected void cleanup() {
}
protected void initGame() {
display.setTitle("Yogurt Test Game Window");
scene = new Node("Scene graph node");
// Create a ZBuffer to display pixels closest to the camera above
// farther ones.
ZBufferState buf = display.getRenderer().createZBufferState();
buf.setEnabled(true);
buf.setFunction(ZBufferState.CF_LEQUAL);
scene.setRenderState(buf);
// Time for a little optimization. We don't need to render back face
// triangles, so lets
// not. This will give us a performance boost for very little effort.
CullState cs = display.getRenderer().createCullState();
cs.setCullMode(CullState.CS_NONE);
scene.setRenderState(cs);
// BUILD THINGS....
buildSkyBox();
buildPlayerCar();
buildLevel();
buildChaseCamera();
buildInput();
buildLighting();
buildPassManager();
// Then our font Text object.
// This is what will actually have the text at the bottom.
fps = Text.createDefaultTextLabel("FPS label");
fps.setCullMode(SceneElement.CULL_NEVER);
fps.setTextureCombineMode(TextureState.REPLACE);
// Finally, a stand alone node (not attached to root on purpose)
fpsNode = new Node("FPS node");
fpsNode.setRenderState(fps.getRenderState(RenderState.RS_ALPHA));
fpsNode.setRenderState(fps.getRenderState(RenderState.RS_TEXTURE));
fpsNode.attachChild(fps);
fpsNode.setCullMode(SceneElement.CULL_NEVER);
// update the scene graph for rendering
scene.updateGeometricState(0.0f, true);
scene.updateRenderState();
fpsNode.updateGeometricState(0.0f, true);
fpsNode.updateRenderState();
}
protected void initSystem() {
// store the properties information
width = properties.getWidth();
height = properties.getHeight();
depth = properties.getDepth();
freq = properties.getFreq();
fullscreen = properties.getFullscreen();
// get display system
try {
display = DisplaySystem.getDisplaySystem(properties.getRenderer());
display.setMinStencilBits(8);
display.createWindow(width, height, depth, freq, fullscreen);
cam = display.getRenderer().createCamera(width, height);
} catch (JmeException e) {
e.printStackTrace();
System.exit(1);
}
// paint background black
display.getRenderer().setBackgroundColor(ColorRGBA.black);
// initialize the camera
cam.setFrustumPerspective(45.0f, (float) width / (float) height, 1,
5000);
cam.setParallelProjection( false );
Vector3f loc = new Vector3f( 0.0f, 0.0f, 25.0f );
Vector3f left = new Vector3f( -1.0f, 0.0f, 0.0f );
Vector3f up = new Vector3f( 0.0f, 1.0f, 0.0f );
Vector3f dir = new Vector3f( 0.0f, 0f, -1.0f );
cam.setFrame( loc, left, up, dir );
//cam.setLocation(new Vector3f(200, 1000, 200));
// Signal that we've changed our camera's location/frustum.
cam.update();
// get timer
timer = Timer.getTimer();
// set the camera
display.getRenderer().setCamera(cam);
// set key ESC as exit key
KeyBindingManager.getKeyBindingManager().set("exit",
KeyInput.KEY_ESCAPE);
}
protected void reinit() {
display.recreateWindow(width, height, depth, freq, fullscreen);
}
/**
* draws the scene graph
*
* @see com.jme.app.SimpleGame#render()
*/
protected void render(float interpolation) {
// Clear the screen
display.getRenderer().clearBuffers();
display.getRenderer().draw(fpsNode);
// display.getRenderer().draw(scene);
/** Have the PassManager render. */
passManager.renderPasses(display.getRenderer());
}
protected void update(float interpolation) {
// update the time to get the framerate
timer.update();
interpolation = timer.getTimePerFrame();
// update the keyboard input (move the player around)
input.update(interpolation);
// update the chase camera to handle the player moving around.
chaser.update(interpolation);
skybox.setLocalTranslation(chaser.getCamera().getLocation());
updateStringBuffer.setLength(0);
updateStringBuffer.append("FPS: ").append((int) timer.getFrameRate());
updateStringBuffer.append(display.getRenderer().getStatistics(
tempBuffer));
fps.print(updateStringBuffer);
// if escape was pressed, we exit
if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit")) {
finished = true;
}
scene.updateGeometricState(interpolation, true);
scene.updateRenderState();
scene.updateWorldData(interpolation);
}
/**
* close the window and also exit the program.
*/
protected void quit() {
super.quit();
System.exit(0);
}
private void buildPlayerCar() {
Node playerCarModel = ModelFileLoader.loadObjModel(
"models/car_no_tire.obj", "car1", 0.165f);
playerCar = new TestCar("Player Node", playerCarModel);
playerCar.setAcceleration(15);
playerCar.setBraking(15);
playerCar.setTurnSpeed(2.5f);
playerCar.setWeight(25);
playerCar.setMaxSpeed(25);
playerCar.setMinSpeed(15);
playerCar.setLocalTranslation(new Vector3f(0, 0, 0));
scene.attachChild(playerCar);
scene.updateGeometricState(0, true);
playerCar.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
}
private void buildLevel() {
Node levelModel = null;
levelModel = ModelFileLoader.loadObjModel("models/level_cartoon.obj", "level_01",
0.50f);
testLevel = new TestLevel("pist_01", levelModel);
// testLevel.setNormalsMode(SceneElement.NM_USE_PROVIDED);
// testLevel.setCullMode(SceneElement.CULL_DYNAMIC);
// testLevel.setLastFrustumIntersection(Camera.INSIDE_FRUSTUM);
testLevel.updateModelBound();
testLevel.updateRenderState();
scene.attachChild(testLevel);
testLevel.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
testLevel.updateRenderState();
}
private void buildInput() {
input = new TestInputHandler(playerCar, properties.getRenderer());
}
private void buildChaseCamera() {
HashMap<String, Object> props = new HashMap<String, Object>();
props.put(ThirdPersonMouseLook.PROP_MAXROLLOUT, "6");
props.put(ThirdPersonMouseLook.PROP_MINROLLOUT, "3");
props.put(ThirdPersonMouseLook.PROP_MAXASCENT, "" + 45
* FastMath.DEG_TO_RAD);
props.put(ChaseCamera.PROP_INITIALSPHERECOORDS, new Vector3f(5, 0,
30 * FastMath.DEG_TO_RAD));
props.put(ChaseCamera.PROP_DAMPINGK, "4");
props.put(ChaseCamera.PROP_SPRINGK, "9");
chaser = new ChaseCamera(cam, playerCar, props);
chaser.setMaxDistance(2.0f);
chaser.setMinDistance(1.0f);
}
private void buildLighting() {
/** Set up a basic, default light. */
DirectionalLight light = new DirectionalLight();
light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, .5f));
light.setDirection(new Vector3f(1, -1, 0));
light.setShadowCaster(true);
light.setEnabled(true);
/** Set up a basic, default light. */
DirectionalLight light2 = new DirectionalLight();
light2.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
light2.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, .5f));
light2.setDirection(new Vector3f(-1, -1, 0));
light2.setShadowCaster(false);
light2.setEnabled(true);
/** Set up a basic, default light. */
DirectionalLight light3 = new DirectionalLight();
light3.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
light3.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, .5f));
light3.setDirection(new Vector3f(0, -1, 1));
light3.setShadowCaster(false);
light3.setEnabled(true);
/** Set up a basic, default light. */
DirectionalLight light4 = new DirectionalLight();
light4.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
light4.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, .5f));
light4.setDirection(new Vector3f(0, -1, -1));
light4.setShadowCaster(false);
light4.setEnabled(true);
// /** Set up a basic, default light. */
// DirectionalLight light5 = new DirectionalLight();
// light5.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
// light5.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, .5f));
// light5.setDirection(new Vector3f(1, -1, 1));
// light5.setShadowCaster(false);
// light5.setEnabled(true);
//
// /** Set up a basic, default light. */
// DirectionalLight light6 = new DirectionalLight();
// light6.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
// light6.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, .5f));
// light6.setDirection(new Vector3f(1, -1, -1));
// light6.setShadowCaster(false);
// light6.setEnabled(true);
//
// /** Set up a basic, default light. */
// DirectionalLight light7 = new DirectionalLight();
// light7.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
// light7.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, .5f));
// light7.setDirection(new Vector3f(-1, -1, 1));
// light7.setShadowCaster(false);
// light7.setEnabled(true);
//
// /** Set up a basic, default light. */
// DirectionalLight light8 = new DirectionalLight();
// light8.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
// light8.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, .5f));
// light8.setDirection(new Vector3f(-1, -1, -1));
// light8.setShadowCaster(false);
// light8.setEnabled(true);
LightState lightState = display.getRenderer().createLightState();
lightState.setEnabled(true);
lightState.setGlobalAmbient(new ColorRGBA(.2f, .2f, .2f, 1f));
lightState.attach(light);
lightState.attach(light2);
lightState.attach(light3);
lightState.attach(light4);
// lightState.attach(light5);
// lightState.attach(light6);
// lightState.attach(light7);
// lightState.attach(light8);
scene.setRenderState(lightState);
scene.updateRenderState();
}
private void buildPassManager() {
passManager = new BasicPassManager();
RenderPass rPass = new RenderPass();
rPass.add(skybox);
passManager.add(rPass);
shadowPass.add(scene);
shadowPass.addOccluder(playerCar);
shadowPass.addOccluder(testLevel);
shadowPass.setRenderShadows(true);
shadowPass.setLightingMethod(ShadowedRenderPass.MODULATIVE);
passManager.add(shadowPass);
}
private void buildSkyBox() {
skybox = new Skybox("skybox", 150, 150, 150);
Texture north = TextureManager.loadTexture(LightTestMain.class
.getClassLoader().getResource("images/sb_pos_z.jpg"),
Texture.MM_LINEAR, Texture.FM_LINEAR);
Texture south = TextureManager.loadTexture(LightTestMain.class
.getClassLoader().getResource("images/sb_neg_z.jpg"),
Texture.MM_LINEAR, Texture.FM_LINEAR);
Texture east = TextureManager.loadTexture(LightTestMain.class
.getClassLoader().getResource("images/sb_pos_x.jpg"),
Texture.MM_LINEAR, Texture.FM_LINEAR);
Texture west = TextureManager.loadTexture(LightTestMain.class
.getClassLoader().getResource("images/sb_neg_x.jpg"),
Texture.MM_LINEAR, Texture.FM_LINEAR);
Texture up = TextureManager.loadTexture(LightTestMain.class
.getClassLoader().getResource("images/sb_pos_y.jpg"),
Texture.MM_LINEAR, Texture.FM_LINEAR);
Texture down = TextureManager.loadTexture(LightTestMain.class
.getClassLoader().getResource("images/sb_neg_y.jpg"),
Texture.MM_LINEAR, Texture.FM_LINEAR);
skybox.setTexture(Skybox.NORTH, north);
skybox.setTexture(Skybox.WEST, west);
skybox.setTexture(Skybox.SOUTH, south);
skybox.setTexture(Skybox.EAST, east);
skybox.setTexture(Skybox.UP, up);
skybox.setTexture(Skybox.DOWN, down);
skybox.preloadTextures();
scene.attachChild(skybox);
}
}