I wasn’t really sure where I should have started posting code. my project is quite large I felt like I would just be bombarding the thread with code no one wants to read.
All the game assets (including the scene) are made in blender, then exporter to ogre before imported into jmonkey. Everything is directly added to the rootNode. I don’t do anything like add the plane to the node that holds the scene model or anything, as far as I can tell it doesnt make a difference.
I use 2 renders in my game, i create them with this code:
[java]PssmShadowRenderer shadowRenderer = new PssmShadowRenderer(assetManager, 1024, 3);
Vector3f dir = UtJme.convertBlenderVectorToJmeVectorLocal(new Vector3f(107, -24, 160));
shadowRenderer.setDirection(dir);
shadowRenderer.setLambda(0.7f);
shadowRenderer.setShadowIntensity(.3f);
shadowRenderer.setCompareMode(PssmShadowRenderer.CompareMode.Hardware);
shadowRenderer.setFilterMode(PssmShadowRenderer.FilterMode.Dither);
FilterPostProcessor filterPostProcessor = new FilterPostProcessor(assetManager);
CartoonEdgeFilter cef = new CartoonEdgeFilter();
cef.setEdgeIntensity(.5f);
cef.setEdgeWidth(.6f);
filterPostProcessor.addFilter(cef);[/java]
Everything in the game is in the opaque render bucket. except for the propellers of the airplanes, which are in the transparent bucket (the propellers are just plane meshes with a texture that lookings like whirring blades)
this is the code I use to load the airplane model:
[java]Node node = (Node) assetManager.loadModel(“Models/Aircraft/c130/c130.mesh.j3o”);
Geometry c130 = (Geometry) node.getChild("c130");
c130.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
Geometry prop = (Geometry) node.getChild("prop");
c130.setShadowMode(RenderQueue.ShadowMode.Cast);
Material mat;
RenderState renderState;
mat = prop.getMaterial();
ColorRGBA diffuseColor = (ColorRGBA) mat.getParam("Diffuse").getValue();
diffuseColor = diffuseColor.clone();
diffuseColor.a = 1;
mat.setFloat("AlphaDiscardThreshold", .08f);
mat.setColor("Diffuse", diffuseColor);
mat.setBoolean("UseAlpha", true);
mat.setBoolean("UseMaterialColors", true);
prop.setQueueBucket(RenderQueue.Bucket.Transparent);
renderState = mat.getAdditionalRenderState();
renderState.setBlendMode(RenderState.BlendMode.Alpha);[/java]
The desert scene is just a regular model, except for the foliage which are flat planes with textures that use alpha. The rocks and cactuses are regular models. The code I use to go through the desert scene and modify the foliage to use alpha looks like this:
[java]private static Geometry applyAlpha(Spatial spatial) {
if (spatial instanceof Geometry) {
Geometry geom = (Geometry) spatial;
Material mat = geom.getMaterial();
ColorRGBA diffuseColor = (ColorRGBA) mat.getParam(“Diffuse”).getValue();
if (diffuseColor.a == 0) {
diffuseColor = diffuseColor.clone();
diffuseColor.a = 1;
mat.setColor(“Diffuse”, diffuseColor);
mat.setFloat(“AlphaDiscardThreshold”, .08f);
mat.setBoolean(“UseMaterialColors”, true);
geom.setQueueBucket(RenderQueue.Bucket.Opaque);
}
return geom;
} else {
Node node = (Node) spatial;
Geometry geom = null;
for (Spatial s : node.getChildren()) {
geom = applyAlpha(s);
}
return geom;
}
}[/java]
so to use this I would load the desert scene with this code:
[java]Node scene = (Node) assetManager.loadModel(“Scenes/DesertScene_05/DesertScene_05.j3o”);
scene.setShadowMode(ShadowMode.Receive);
scene.move(0, .2f, -280);
rootNode.attachChild(scene);
applyAlpha(scene);[/java]
the scene is just an ambient light and a directional light (in the same direction as the shadow)
[java]
AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(0.5f));
rootNode.addLight(al);
DirectionalLight sun;
sun = new DirectionalLight();
sun.setDirection(dir); //this is the same dir used in the shadow renderer.
sun.setColor(ColorRGBA.White.mult(1.4f));
rootNode.addLight(sun);
[/java]