Hello.
I’ve got 2 problems:
- Looks like PSSM Shadow Renderer is not working at all on video cards supporting GLSL 1.50.
I’ve got a GTX 460 card for which PostShadowPSSM15.frag shader is used.
When I run the example program attached below, I get this error after running around for a few seconds:
WARNING: Common/MatDefs/Shadow/PostShadowPSSM15.frag compile error: 0(90) : error C1115: unable to find compatible overloaded function “textureGather(sampler2DShadow, vec2, float)”
And shadows are not working at all.
I’ve checked this decription: http://www.opengl.org/registry/specs/ARB/texture_gather.txt
And it says the syntax for the textureGather functions is the next:
gvec4 textureGather(gsampler2D sampler, vec2 coord)
gvec4 textureGather(gsampler2DArray sampler, vec3 coord)
gvec4 textureGather(gsamplerCube sampler, vec3 coord)
gvec4 textureGather(gsamplerCubeArray sampler, vec4 coord)
So looks like it really takes 2 params and not 3 like in the PostShadowPSSM15.frag file.
That’s why I think it’s a bug, but I don’t know how to fix itPlease suggest.
- DirectionalLight is not working as expected.
Please check this screenshot from the same example:
Blue arrow shows the direction of light.
The wall to the left is lighted as expected. But the wall to the right and the floor are lighted too (see red arrows)! As if the light has passed through the first wall!
Actually, I can wall off completely building the last 4th wall and if I look from inside one wall will be still light, while it should be completely dark inside! (Please note that ambient light is disabled)
Is it an expected behaviour or is it a bug too?
This is how I expect the directional light to work (this is a screenshot generated using another 3D engine - Leadwerks):
When ambient lighting is disabled and only one directional light is kept, the walls inside this “shaft” are completely dark (black) except the small area on the top which is hit by the light directly.
I’m using the last JME3 nightly build from 21th February.
Example code:
pre type="java"
package mygame;
import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.PhysicsControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;
import com.jme3.shadow.BasicShadowRenderer;
import com.jme3.shadow.PssmShadowRenderer;
import java.sql.BatchUpdateException;
import jme3tools.optimize.GeometryBatchFactory;
public class Main2 extends SimpleApplication {
private Vector3f walkDirection = new Vector3f();
private boolean left = false, right = false, up = false, down = false;
private BulletAppState appState;
private CharacterControl player;
private int cubeCount = 0;
public static void main(String[] args) {
new Main2().start();
}
@Override
public void simpleInitApp() {
appState = new BulletAppState();
stateManager.attach(appState);
Material brickMaterial = new Material(assetManager, “Common/MatDefs/Light/Lighting.j3md”);
brickMaterial.setTexture(“DiffuseMap”, assetManager.loadTexture(“Textures/Terrain/BrickWall/BrickWall.jpg”));
brickMaterial.setTexture(“NormalMap”, assetManager.loadTexture(“Textures/Terrain/BrickWall/BrickWall_normal.jpg”));
brickMaterial.setTexture(“ParallaxMap”, assetManager.loadTexture(“Textures/Terrain/BrickWall/BrickWall_height.jpg”));
brickMaterial.setTexture(“ColorMap”, assetManager.loadTexture(“Textures/Terrain/BrickWall/BrickWall_height.jpg”));
brickMaterial.setFloat(“Shininess”, 2f);
Node cubes = new Node(“All Cubes”);
for (int i = -8; i <= 8; i++) {
cubes.attachChild(createCube(brickMaterial, 1f, i 2, 2f, -16));
cubes.attachChild(createCube(brickMaterial, 1f, i 2, 2f, 16));
cubes.attachChild(createCube(brickMaterial, 1f, -16, 2f, i 2));
cubes.attachChild(createCube(brickMaterial, 1f, 16, 2f, i 2));
for (int j = -8; j <= 8; j++) {
cubes.attachChild(createCube(brickMaterial, 1f, i 2, 0f, j 2));
}
}
for (int i = -7; i <= 5; i++) {
for (int j = 1; j <= 10; j++) {
cubes.attachChild(createCube(brickMaterial, 1f, i 2, j 2, 4f));
if (i <= 4) {
cubes.attachChild(createCube(brickMaterial, 1f, i 2, j 2, -4f));
}
}
}
for (int i = -7; i <= 5; i++) {
for (int k = -3; k <= 3; k++) {
cubes.attachChild(createCube(brickMaterial, 1f, i 2, 20, k 2));
}
}
for (int j = 2; j <= 10; j++) {
for (int k = -3; k <= 3; k++) {
cubes.attachChild(createCube(brickMaterial, 1f, -16, j 2, k 2));
}
}
rootNode.attachChild(GeometryBatchFactory.optimize(cubes));
rootNode.attachChild(createCube(brickMaterial, 1f, 0f, 0f, 0f));
setupPlayer();
setupLights();
setupShadows();
setupKeys();
}
private Geometry createCube(Material mat, float size, float x, float y, float z) {
cubeCount++;
Box box = new Box(Vector3f.ZERO, size, size, size);
Geometry cube = new Geometry("Cube " + cubeCount, box);
cube.setMaterial(mat);
cube.setLocalTranslation(x, y, z);
cube.setShadowMode(ShadowMode.CastAndReceive);
CollisionShape cubeCollissionShape = CollisionShapeFactory.createMeshShape(cube);
PhysicsControl cubePhysics = new RigidBodyControl(cubeCollissionShape, 0.0f);
cube.addControl(cubePhysics);
appState.getPhysicsSpace().add(cubePhysics);
return cube;
}
private void setupLights() {
DirectionalLight dl = new DirectionalLight();
dl.setColor(ColorRGBA.White.clone().multLocal(2));
dl.setDirection(new Vector3f(0f, -1f, -1f).normalizeLocal());
rootNode.addLight(dl);
//AmbientLight al = new AmbientLight();
//al.setColor(new ColorRGBA(1.8f,1.8f,1.8f,1.0f));
//rootNode.addLight(al);
}
private void setupShadows() {
//BasicShadowRenderer sr = new BasicShadowRenderer(assetManager, 256);
PssmShadowRenderer sr = new PssmShadowRenderer(assetManager, 512, 2);
sr.setFilterMode(PssmShadowRenderer.FilterMode.Bilinear);
sr.setCompareMode(PssmShadowRenderer.CompareMode.Hardware);
sr.setDirection(new Vector3f(0f, -1f, -1f).normalizeLocal());
viewPort.addProcessor(sr);
rootNode.setShadowMode(ShadowMode.Off);
}
public void setupPlayer() {
CollisionShape playerShape = new CapsuleCollisionShape(1.3f, 2f, 1);
player = new CharacterControl(playerShape, 0.05f);
player.setJumpSpeed(20);
player.setFallSpeed(30);
player.setGravity(30);
player.setPhysicsLocation(new Vector3f(0f, 3f, 0f));
appState.getPhysicsSpace().add(player);
}
private void setupKeys() {
inputManager.addMapping(“Lefts”, new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping(“Rights”, new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping(“Ups”, new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping(“Downs”, new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping(“Jumps”, new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addListener(actionListener, new String[] {
“Lefts”, “Rights”, “Ups”, “Downs”, “Jumps”
});
}
@Override
public void simpleUpdate(float tpf) {
Vector3f camDir = cam.getDirection().clone().multLocal(0.2f);
Vector3f camLeft = cam.getLeft().clone().multLocal(0.1f);
walkDirection.set(0, 0, 0);
if (left) {
walkDirection.addLocal(camLeft);
}
if (right) {
walkDirection.addLocal(camLeft.negate());
}
if (up) {
walkDirection.addLocal(camDir);
walkDirection.y = 0;
}
if (down) {
walkDirection.addLocal(camDir.negate());
walkDirection.y = 0;
}
player.setWalkDirection(walkDirection);
cam.setLocation(player.getPhysicsLocation());
}
private ActionListener actionListener = new ActionListener() {
public void onAction(String binding, boolean value, float tpf) {
if (binding.equals(“Lefts”)) {
left = value;
} else if (binding.equals(“Rights”)) {
right = value;
} else if (binding.equals(“Ups”)) {
up = value;
} else if (binding.equals(“Downs”)) {
down = value;
} else if (binding.equals(“Jumps”) && value && player.onGround()) {
player.jump();
}
}
};
}/pre