Shadows not rendering "beautifully" always

Hey!
I’m having a problem with the shadows, it’s not rendering as it shoud be when the mesh is far away from the center of the scene. Like this:
The mesh at the center:

The mesh far away from center:

So, don’t matter if i start the game with the mesh at the center and move it away, or just start the game with the mesh far from the (0,0,0).

Here is the code:
[java]package AppStates;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.asset.AssetManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.BetterCharacterControl;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.input.ChaseCamera;
import com.jme3.input.InputManager;
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.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.CartoonEdgeFilter;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.renderer.Camera;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.debug.SkeletonDebugger;
import com.jme3.scene.shape.Box;
import com.jme3.shadow.BasicShadowRenderer;
import com.jme3.shadow.DirectionalLightShadowFilter;
import com.jme3.shadow.DirectionalLightShadowRenderer;
import com.jme3.shadow.PssmShadowRenderer;

/**
*

  • @author Paulo
    */
    public class GameRunningAppState extends AbstractAppState{

    private SimpleApplication app;

    // Objects and Nodes
    private Node player;
    private Node city;
    private Geometry box1;
    private DirectionalLight dl;
    private ChaseCamera chaseCam;
    private Camera cam;

    // Cameras
    private Camera cam2, cam3, cam4;
    private ViewPort viewPort2, viewPort3, viewPort4;

    // Character Moving Variables
    private boolean up, down, left, right, sprint;
    private Vector3f walkDirection = new Vector3f();
    private float speed = 10f;
    private Vector3f camLeft;
    private Vector3f camDir;

    // Physics variables
    private BulletAppState bulletAppState;
    private RigidBodyControl cityControl;
    private CapsuleCollisionShape playerCapsuleShape;
    private CharacterControl playerControl;
    private BetterCharacterControl betterPlayerControl;

    // Animation variables
    private AnimChannel channel;
    private AnimControl control;

    // References to Main class fields
    private Node rootNode;
    private AssetManager assetManager;
    private ViewPort viewPort;
    private InputManager inputManager;

    // Class Constructor
    public GameRunningAppState(){

    }

    @Override
    public void initialize(AppStateManager stateManager, Application app){
    super.initialize(stateManager, app);

     this.app = (SimpleApplication) app;
     
     // Guarda as referencias dos campos do Main
     this.assetManager = this.app.getAssetManager();
     this.rootNode     = this.app.getRootNode();
     this.viewPort     = this.app.getViewPort();
     this.inputManager = this.app.getInputManager();
     this.cam          = this.app.getCamera();
     
     setUpEnvironment();
     initKeys();
     loadModels();
     loadLights();
     setUpCamera();
     setUpShadows();
     initAnimVariables();
    

// debugSkeleton();
setUpCollisionShapes();
setUpPlayerCollisionShape();

    lastAttaching();
    
    viewPort.setBackgroundColor(ColorRGBA.LightGray);
}

private void setUpEnvironment(){
    this.app.getFlyByCamera().setMoveSpeed(50);

// this.app.getFlyByCamera().setEnabled(false);

    bulletAppState = new BulletAppState();
    bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);
    app.getStateManager().attach(bulletAppState);
}

private void loadModels(){
    player = (Node) assetManager.loadModel("Models/Character.mesh.j3o");
    player.scale(0.3f);
    player.setLocalTranslation(495, 0, 12);
    player.setShadowMode(ShadowMode.CastAndReceive);
    rootNode.attachChild(player);
    
    city = (Node) assetManager.loadModel("Scenes/Cidade/Cidade.j3o");
    city.scale(30f);
    city.setLocalTranslation(0, -2, 0);
    for(Spatial a : city.getChildren()){
        a.setShadowMode(ShadowMode.CastAndReceive);
    }
    city.getChild("Cidade-entity").setShadowMode(ShadowMode.Receive);
    rootNode.attachChild(city);
    
    Box b1 = new Box(1, 1, 1);
    box1 = new Geometry("Center", b1);
    Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat1.setColor("Color", ColorRGBA.Blue);
    box1.setMaterial(mat1);
    rootNode.attachChild(box1);
}

private void loadLights(){
    dl = new DirectionalLight();
    dl.setDirection(new Vector3f(-0.1f, -1f, -1f).normalizeLocal());
    dl.setColor(ColorRGBA.White.mult(1f));
    rootNode.addLight(dl);
    
    AmbientLight al = new AmbientLight();
    al.setColor(ColorRGBA.White.mult(.5f));
    rootNode.addLight(al);
}

private void setUpShadows(){
    FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
    // ShadowRenderer
    final int SHADOWMAP_SIZE = 1024;

// DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer(assetManager, SHADOWMAP_SIZE, 3);
// dlsr.setLight(dl);
// viewPort.addProcessor(dlsr);

    //ShadowFilter (Best One Untill now)
    DirectionalLightShadowFilter dlsf = new DirectionalLightShadowFilter(assetManager, SHADOWMAP_SIZE, 3);
    dlsf.setLight(dl);
    dlsf.setEnabled(true);
    fpp.addFilter(dlsf);
    
    //Parallel-SplitShadowMap(deprecated)

// PssmShadowRenderer pssmRenderer = new PssmShadowRenderer(assetManager, SHADOWMAP_SIZE, 3);
// pssmRenderer.setDirection(dl.getDirection());
// viewPort.addProcessor(pssmRenderer);

    //BasicShadowRenderer(deprecated)

// BasicShadowRenderer bsr = new BasicShadowRenderer(assetManager, SHADOWMAP_SIZE);
// bsr.setDirection(dl.getDirection());
// viewPort.addProcessor(bsr);

    // Ambient Occlusion
    SSAOFilter ssaoFilter = new SSAOFilter(12.94f, 30f, 0.33f, 0.61f);
    fpp.addFilter(ssaoFilter);
    
    // Toon Edge Filter

// CartoonEdgeFilter toon = new CartoonEdgeFilter();
// fpp.addFilter(toon);
viewPort.addProcessor(fpp);
}

private void setUpCamera(){

// chaseCam = new ChaseCamera(cam, player, inputManager);
// chaseCam.setInvertVerticalAxis(true);
//// chaseCam.setSmoothMotion(true);
//// chaseCam.setTrailingEnabled(true);
//// chaseCam.setTrailingSensitivity(1f);
// chaseCam.setDragToRotate(false);
}

private void initKeys(){
    inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
    inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
    inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W));
    inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S));
    inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
    inputManager.addMapping("Sprint", new KeyTrigger(KeyInput.KEY_LSHIFT));
    inputManager.addMapping("Walk", new KeyTrigger(KeyInput.KEY_1));
    inputManager.addMapping("Stop", new KeyTrigger(KeyInput.KEY_S));
    inputManager.addMapping("Joke", new KeyTrigger(KeyInput.KEY_J));
    inputManager.addListener(actionListener, "Left", "Right", "Up", "Down", "Jump", "Sprint", "Walk", "Joke", "Stop");
}

private void initAnimVariables(){
    control = player.getControl(AnimControl.class);
    control.addListener(animEventListener);
    
    channel = control.createChannel();
    channel.setAnim("Breath");
}

private void debugSkeleton(){
    SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton", control.getSkeleton());
    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat.setColor("Color", ColorRGBA.Green);
    mat.getAdditionalRenderState().setDepthTest(false);
    skeletonDebug.setMaterial(mat);
    player.attachChild(skeletonDebug);
}

private void setUpCollisionShapes(){
    CollisionShape sceneShape = CollisionShapeFactory.createMeshShape(city);
    
    cityControl = new RigidBodyControl(sceneShape, 0);// RigidBodyControl(CollisionShape, Mass);
    cityControl.setKinematic(false);
    city.addControl(cityControl);
}

private void setUpPlayerCollisionShape(){
    playerCapsuleShape = new CapsuleCollisionShape(1.1f, 3f, 1);
    
    playerControl = new CharacterControl(playerCapsuleShape, 2f);
    playerControl.setJumpSpeed(20f);
    playerControl.setFallSpeed(10f);
    playerControl.setGravity(30f);
    
    //player.addControl(playerControl);
    playerControl.setPhysicsLocation(new Vector3f(0, 10, 0));
    
    betterPlayerControl = new BetterCharacterControl(0.9f, 3.1f, 4);
    betterPlayerControl.setJumpForce(new Vector3f(0, 18, 0));
    betterPlayerControl.setGravity(new Vector3f(0, -10, 0));
    player.addControl(betterPlayerControl);
}

private void lastAttaching(){
    bulletAppState.getPhysicsSpace().add(cityControl);
    //bulletAppState.getPhysicsSpace().add(playerControl);
    bulletAppState.getPhysicsSpace().add(betterPlayerControl);
    //playerControl.getPhysicsSpace().enableDebug(assetManager);
    bulletAppState.setDebugEnabled(true);
}

private AnimEventListener animEventListener = new AnimEventListener() {

    public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
        if (animName.equals("StartWalk")) {
            channel.setAnim("Walk", 1f);
            channel.setLoopMode(LoopMode.Loop);
            channel.setSpeed(2f);
        }
        if(animName.equals("Stand")){
            channel.setAnim("Breath", 1f);
            channel.setLoopMode(LoopMode.Loop);
            channel.setSpeed(1f);
        }
    }

    public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
        
    }
};

private ActionListener actionListener = new ActionListener() {

    public void onAction(String name, boolean isPressed, float tpf) {
        if (name.equals("Walk") && !isPressed) {
            if (!channel.getAnimationName().equals("StartWalk") || !channel.getAnimationName().equals("Walk")) {
                channel.setAnim("StartWalk", 1f);
                channel.setLoopMode(LoopMode.DontLoop);
                channel.setSpeed(2f);
            }
        }
        else if (name.equals("Joke") && !isPressed){
            if(!channel.getAnimationName().equals("Stand")){
                channel.setAnim("Stand", 1f);
                channel.setLoopMode(LoopMode.DontLoop);
            }
        }
        else if (name.equals("Stop") && !isPressed){
            channel.setAnim("Breath", 1f);
            channel.setLoopMode(LoopMode.Loop);
        }
        else if (name.equals("Left")) {
            left = isPressed;
        } else if (name.equals("Right")) {
            right = isPressed;
        } else if (name.equals("Up")) {
            up = isPressed;
        } else if (name.equals("Down")) {
            down = isPressed;
        } else if (name.equals("Jump")) {
            //playerControl.jump();
            betterPlayerControl.jump();
        } else if (name.equals("Sprint")){
            sprint = isPressed;
        }
    }
};

@Override
public void update(float tpf){
    
    /*
    if (sprint){
       speed = 20f; 
    } else {
        speed = 10f;
    }

// if(!left && !right)
camLeft = cam.getLeft().clone().multLocal(speed);
camDir = cam.getDirection().clone().multLocal(speed);
// Vector3f camLeft = new Vector3f(1,0,0);
// Vector3f camDir = new Vector3f(0,0,1);
camLeft.y = 0;
camDir.y = 0;
walkDirection.set(0, 0, 0);

    if (left) {
        walkDirection.addLocal(camLeft);
    }
    if (right) {
        walkDirection.addLocal(camLeft.negate());
    }
    if (up) {
        walkDirection.addLocal(camDir);
    }
    if (down) {
        walkDirection.addLocal(camDir.negate());
    }
    //playerControl.setWalkDirection(walkDirection);
    betterPlayerControl.setWalkDirection(walkDirection);
    if (walkDirection.length() != 0){
        //playerControl.setViewDirection(walkDirection);
        betterPlayerControl.setViewDirection(walkDirection);
    }*/
}

@Override
public void setEnabled(boolean enabled){
    super.setEnabled(enabled);
    
}

@Override
public void cleanup(){
    super.cleanup();
}

}
[/java]
This is just a appState for the game running, the main file just call this one.

And i have too much commented code because i’ve tested many things but nothing works.

At first i thought the chaseCam was causing this problem, but after i figured out that with the FlyCam also have the same problem. so it’s not a cam problem.

As a newbie at jme, i don’t know what can i do now to solve this problem.

So, help me!!! hahaha:-D

Later i’ll record a video to show better what is happening.

Thanks

1 Like

Gonna look into it, thanks for the test case

1 Like

I think I know what the problem is.
What if you set the floor to castAndReceive too?
on line 146.

The thing is the shadow processor crops the projection matrix to the casting objects, so depending how much objects you have in the cam frustum the area where the shadow map is projected can vary.

For exemple in the first picture, the character is alone on screen. In the second shot, there are buildings all around.
Setting the ground to also cast shadows will always ccropo to the maximum suize soo you shouldn’t have any variation.

Another test is to remove the buildings and see if you still have the issue.

Could you try?

EDIT : mhh actually that may not be the issue. I’ve seen the other post where you posted and the issue seems to occur even if there is only one object. Still try to make the ground to CastAndReceive.

1 Like

I set the floor to castAndReceive, and it “worked” but in the wrong way… haha
Here is a center of the scene screen Shoot:

My loadModel() method was thus:
[java] private void loadModels(){
player = (Node) assetManager.loadModel(“Models/Character.mesh.j3o”);
player.scale(0.3f);
player.setLocalTranslation(0, 0, 0);
player.setShadowMode(ShadowMode.CastAndReceive);
rootNode.attachChild(player);

    city = (Node) assetManager.loadModel("Scenes/Cidade/Cidade.j3o");
    city.scale(30f);
    city.setLocalTranslation(0, -2, 0);
    city.setShadowMode(ShadowMode.CastAndReceive);
    /*
    for(Spatial a : city.getChildren()){
        a.setShadowMode(ShadowMode.CastAndReceive);
    }
    city.getChild("Cidade-entity").setShadowMode(ShadowMode.CastAndReceive);
    */
    rootNode.attachChild(city);
}[/java] 

And int the other test i drew the model out, and put a Quad in place. But sadly don’t worked…
The scrSchoot from the center(The blue Box mark the center of the scene):

The scrShoot far from center:

And the new loadModel() Method:
[java] private void loadModels(){
player = (Node) assetManager.loadModel(“Models/Character.mesh.j3o”);
player.scale(0.3f);
player.setLocalTranslation(0, 0, 0);
player.setShadowMode(ShadowMode.CastAndReceive);
rootNode.attachChild(player);

    //city = (Node) assetManager.loadModel("Scenes/Cidade/Cidade.j3o");
    // Load a Quad as a terrain
    Geometry planeGeom = new Geometry("plane", new Quad(100, 100));
    Material mat_ground = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat_ground.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));
    planeGeom.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
    planeGeom.setLocalTranslation(-50, 0, 50);
    planeGeom.setMaterial(mat_ground);
    
    city = new Node("Cidade");
    city.attachChild(planeGeom);
    city.scale(30f);
    city.setLocalTranslation(0, -2, 0);
    city.setShadowMode(ShadowMode.CastAndReceive);
    /*
    for(Spatial a : city.getChildren()){
        a.setShadowMode(ShadowMode.CastAndReceive);
    }
    city.getChild("Cidade-entity").setShadowMode(ShadowMode.CastAndReceive);
    */
    rootNode.attachChild(city);
    
    Box b1 = new Box(1, 1, 1);
    box1 = new Geometry("Center", b1);
    Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat1.setColor("Color", ColorRGBA.Blue);
    box1.setMaterial(mat1);
    rootNode.attachChild(box1);
}

[/java]
P.S.: I’ve changed my code, so you could see what is really happening XD.
Here it goes:
[java]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package AppStates;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.asset.AssetManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.BetterCharacterControl;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.input.ChaseCamera;
import com.jme3.input.InputManager;
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.FastMath;
import com.jme3.math.Plane;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.CartoonEdgeFilter;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.renderer.Camera;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.debug.SkeletonDebugger;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Quad;
import com.jme3.shadow.BasicShadowRenderer;
import com.jme3.shadow.DirectionalLightShadowFilter;
import com.jme3.shadow.DirectionalLightShadowRenderer;
import com.jme3.shadow.PssmShadowRenderer;

/**
*

  • @author Paulo
    */
    public class GameRunningAppState extends AbstractAppState{

    private SimpleApplication app;

    // Objects and Nodes
    private Node player;
    private Node city;
    private Geometry box1;
    private DirectionalLight dl;
    private ChaseCamera chaseCam;
    private Camera cam;

    // Cameras
    private Camera cam2, cam3, cam4;
    private ViewPort viewPort2, viewPort3, viewPort4;

    // Character Moving Variables
    private boolean up, down, left, right, sprint;
    private Vector3f walkDirection = new Vector3f();
    private float speed = 10f;
    private Vector3f camLeft;
    private Vector3f camDir;

    // Physics variables
    private BulletAppState bulletAppState;
    private RigidBodyControl cityControl;
    private CapsuleCollisionShape playerCapsuleShape;
    private CharacterControl playerControl;
    private BetterCharacterControl betterPlayerControl;

    // Animation variables
    private AnimChannel channel;
    private AnimControl control;

    // References to Main class fields
    private Node rootNode;
    private AssetManager assetManager;
    private ViewPort viewPort;
    private InputManager inputManager;

    // Class Constructor
    public GameRunningAppState(){

    }

    @Override
    public void initialize(AppStateManager stateManager, Application app){
    super.initialize(stateManager, app);

     this.app = (SimpleApplication) app;
     
     // Guarda as referencias dos campos do Main
     this.assetManager = this.app.getAssetManager();
     this.rootNode     = this.app.getRootNode();
     this.viewPort     = this.app.getViewPort();
     this.inputManager = this.app.getInputManager();
     this.cam          = this.app.getCamera();
     
     setUpEnvironment();
     initKeys();
     loadModels();
     setUpLights();
     setUpCamera();
     setUpShadows();
    

// initAnimVariables();
// debugSkeleton();
setUpCollisionShapes();
setUpPlayerCollisionShape();

    lastAttaching();
    
    viewPort.setBackgroundColor(ColorRGBA.LightGray);
}

private void setUpEnvironment(){

// this.app.getFlyByCamera().setMoveSpeed(50);
this.app.getFlyByCamera().setEnabled(false);

    bulletAppState = new BulletAppState();
    bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);
    app.getStateManager().attach(bulletAppState);
}

private void loadModels(){
    //player = (Node) assetManager.loadModel("Models/Character.mesh.j3o");
    player = new Node();
    Spatial ninja = assetManager.loadModel("Models/Ninja/Ninja.mesh.xml");
    ninja.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.PI, Vector3f.UNIT_Y));
    player.attachChild(ninja);
    
    player.scale(0.015f);
    player.setLocalTranslation(0, 0, 0);
    player.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_Y));
    player.setShadowMode(ShadowMode.CastAndReceive);
    rootNode.attachChild(player);
    
    //city = (Node) assetManager.loadModel("Scenes/Cidade/Cidade.j3o");
    // Load a Quad as a terrain
    Geometry planeGeom = new Geometry("plane", new Quad(100, 100));
    Material mat_ground = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat_ground.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));
    planeGeom.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
    planeGeom.setLocalTranslation(-50, 0, 50);
    planeGeom.setMaterial(mat_ground);
    
    city = new Node("Cidade");
    city.attachChild(planeGeom);
    city.scale(30f);
    city.setLocalTranslation(0, -2, 0);
    city.setShadowMode(ShadowMode.Receive);
    /*
    for(Spatial a : city.getChildren()){
        a.setShadowMode(ShadowMode.CastAndReceive);
    }
    city.getChild("Cidade-entity").setShadowMode(ShadowMode.CastAndReceive);
    */
    rootNode.attachChild(city);
    
    Box b1 = new Box(1, 1, 1);
    box1 = new Geometry("Center", b1);
    Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat1.setColor("Color", ColorRGBA.Blue);
    box1.setMaterial(mat1);
    rootNode.attachChild(box1);
}

private void setUpLights(){
    dl = new DirectionalLight();
    dl.setDirection(new Vector3f(-0.1f, -1f, -1f).normalizeLocal());
    dl.setColor(ColorRGBA.White);
    rootNode.addLight(dl);
    
    AmbientLight al = new AmbientLight();
    al.setColor(ColorRGBA.White.mult(.5f));
    rootNode.addLight(al);
}

private void setUpShadows(){
    FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
    // ShadowRenderer
    final int SHADOWMAP_SIZE = 1024;

// DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer(assetManager, SHADOWMAP_SIZE, 3);
// dlsr.setLight(dl);
// viewPort.addProcessor(dlsr);

    //ShadowFilter (Best One Untill now)
    DirectionalLightShadowFilter dlsf = new DirectionalLightShadowFilter(assetManager, SHADOWMAP_SIZE, 3);
    dlsf.setLight(dl);
    dlsf.setEnabled(true);
    fpp.addFilter(dlsf);
    
    //Parallel-SplitShadowMap(deprecated)

// PssmShadowRenderer pssmRenderer = new PssmShadowRenderer(assetManager, SHADOWMAP_SIZE, 3);
// pssmRenderer.setDirection(dl.getDirection());
// viewPort.addProcessor(pssmRenderer);

    //BasicShadowRenderer(deprecated)

// BasicShadowRenderer bsr = new BasicShadowRenderer(assetManager, SHADOWMAP_SIZE);
// bsr.setDirection(dl.getDirection());
// viewPort.addProcessor(bsr);

    // Ambient Occlusion
    SSAOFilter ssaoFilter = new SSAOFilter(12.94f, 30f, 0.33f, 0.61f);
    fpp.addFilter(ssaoFilter);
    
    // Toon Edge Filter

// CartoonEdgeFilter toon = new CartoonEdgeFilter();
// fpp.addFilter(toon);
viewPort.addProcessor(fpp);
}

private void setUpCamera(){
    chaseCam = new ChaseCamera(cam, player, inputManager);
    chaseCam.setInvertVerticalAxis(true);

// chaseCam.setSmoothMotion(true);
// chaseCam.setTrailingEnabled(true);
// chaseCam.setTrailingSensitivity(1f);
chaseCam.setDragToRotate(false);
}

private void initKeys(){
    inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
    inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
    inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W));
    inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S));
    inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
    inputManager.addMapping("Sprint", new KeyTrigger(KeyInput.KEY_LSHIFT));

// inputManager.addMapping(“Walk”, new KeyTrigger(KeyInput.KEY_1));
// inputManager.addMapping(“Stop”, new KeyTrigger(KeyInput.KEY_S));
// inputManager.addMapping(“Joke”, new KeyTrigger(KeyInput.KEY_J));
inputManager.addListener(actionListener, “Left”, “Right”, “Up”, “Down”, “Jump”, “Sprint”/, “Walk”, “Joke”, “Stop”/);
}

private void initAnimVariables(){
    control = player.getControl(AnimControl.class);
    control.addListener(animEventListener);
    
    channel = control.createChannel();
    channel.setAnim("Breath");
}

private void debugSkeleton(){
    SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton", control.getSkeleton());
    Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat.setColor("Color", ColorRGBA.Green);
    mat.getAdditionalRenderState().setDepthTest(false);
    skeletonDebug.setMaterial(mat);
    player.attachChild(skeletonDebug);
}

private void setUpCollisionShapes(){
    CollisionShape sceneShape = CollisionShapeFactory.createMeshShape(city);
    
    cityControl = new RigidBodyControl(sceneShape, 0);// RigidBodyControl(CollisionShape, Mass);
    cityControl.setKinematic(false);
    city.addControl(cityControl);
}

private void setUpPlayerCollisionShape(){
    playerCapsuleShape = new CapsuleCollisionShape(1.1f, 3f, 1);
    
    playerControl = new CharacterControl(playerCapsuleShape, 2f);
    playerControl.setJumpSpeed(20f);
    playerControl.setFallSpeed(10f);
    playerControl.setGravity(30f);
    
    //player.addControl(playerControl);
    playerControl.setPhysicsLocation(new Vector3f(0, 10, 0));
    
    betterPlayerControl = new BetterCharacterControl(0.9f, 3.1f, 4);
    betterPlayerControl.setJumpForce(new Vector3f(0, 18, 0));
    betterPlayerControl.setGravity(new Vector3f(0, -10, 0));
    player.addControl(betterPlayerControl);
}

private void lastAttaching(){
    bulletAppState.getPhysicsSpace().add(cityControl);
    //bulletAppState.getPhysicsSpace().add(playerControl);
    bulletAppState.getPhysicsSpace().add(betterPlayerControl);
    //playerControl.getPhysicsSpace().enableDebug(assetManager);
    bulletAppState.setDebugEnabled(true);
}

private AnimEventListener animEventListener = new AnimEventListener() {

    public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
        if (animName.equals("StartWalk")) {
            channel.setAnim("Walk", 1f);
            channel.setLoopMode(LoopMode.Loop);
            channel.setSpeed(2f);
        }
        if(animName.equals("Stand")){
            channel.setAnim("Breath", 1f);
            channel.setLoopMode(LoopMode.Loop);
            channel.setSpeed(1f);
        }
    }

    public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
        
    }
};

private ActionListener actionListener = new ActionListener() {

    public void onAction(String name, boolean isPressed, float tpf) {
        if (name.equals("Walk") && !isPressed) {
            if (!channel.getAnimationName().equals("StartWalk") || !channel.getAnimationName().equals("Walk")) {
                channel.setAnim("StartWalk", 1f);
                channel.setLoopMode(LoopMode.DontLoop);
                channel.setSpeed(2f);
            }
        }
        else if (name.equals("Joke") && !isPressed){
            if(!channel.getAnimationName().equals("Stand")){
                channel.setAnim("Stand", 1f);
                channel.setLoopMode(LoopMode.DontLoop);
            }
        }
        else if (name.equals("Stop") && !isPressed){
            channel.setAnim("Breath", 1f);
            channel.setLoopMode(LoopMode.Loop);
        }
        else if (name.equals("Left")) {
            left = isPressed;
        } else if (name.equals("Right")) {
            right = isPressed;
        } else if (name.equals("Up")) {
            up = isPressed;
        } else if (name.equals("Down")) {
            down = isPressed;
        } else if (name.equals("Jump")) {
            //playerControl.jump();
            betterPlayerControl.jump();
        } else if (name.equals("Sprint")){
            sprint = isPressed;
        }
    }
};

@Override
public void update(float tpf){
    
    
    if (sprint){
       speed = 20f; 
    } else {
        speed = 10f;
    }

// if(!left && !right)
camLeft = cam.getLeft().clone();
camDir = cam.getDirection().clone();
// Vector3f camLeft = new Vector3f(1,0,0);
// Vector3f camDir = new Vector3f(0,0,1);
camLeft.y = 0;
camDir.y = 0;
walkDirection.set(0, 0, 0);

    if (left) {
        walkDirection.addLocal(camLeft);
    }
    if (right) {
        walkDirection.addLocal(camLeft.negate());
    }
    if (up) {
        walkDirection.addLocal(camDir);
    }
    if (down) {
        walkDirection.addLocal(camDir.negate());
    }
    //playerControl.setWalkDirection(walkDirection);
    betterPlayerControl.setWalkDirection(walkDirection.normalize().multLocal(speed));
    if (walkDirection.length() != 0){
        //playerControl.setViewDirection(walkDirection);
        betterPlayerControl.setViewDirection(walkDirection);
    }
}

@Override
public void setEnabled(boolean enabled){
    super.setEnabled(enabled);
    
}

@Override
public void cleanup(){
    super.cleanup();
}

}
[/java]
Copy it to an appState and call at your main(Why i said this… you know how to do it better than me…)

Thanks for your answer.

WOW

After reading again your post, i understand what you are talking about!!(I think…)

And the i’ve done 2 things

1 - Changed the floor to CastAndRecieve;
2 - Multiplied by 4 the SHADOWMAP_SIZE;

And it worked nicely!

The shadowMode ensures me to that the shadow of my model will not vary, although it spoil the shadow quality, what is solves by raising the shadowMap applied to the shadow filter.

And i still have two questions.

1- Multiplying the shadowMap by 4 will raise too much the use of the GPU to render my scene?

2 - Replacing the scene with a quad was not effective, so i’ve concluded that the number of objects in the scene does not spoil the shadow, and the “moving away from center” problem is still there.
(Other thing i’ve noticed is that if the came is showing the oposite side of the center of the scene, the quality of the shadow raises, and if shows the center of the scene the quality goes down).
So what is the point of removing my scene?

Thanks

@PauloAlvares said: WOW

After reading again your post, i understand what you are talking about!!(I think…)

And the i’ve done 2 things

1 - Changed the floor to CastAndRecieve;
2 - Multiplied by 4 the SHADOWMAP_SIZE;

And it worked nicely!

The shadowMode ensures me to that the shadow of my model will not vary, although it spoil the shadow quality, what is solves by raising the shadowMap applied to the shadow filter.

And i still have two questions.

1- Multiplying the shadowMap by 4 will raise too much the use of the GPU to render my scene?

2 - Replacing the scene with a quad was not effective, so i’ve concluded that the number of objects in the scene does not spoil the shadow, and the “moving away from center” problem is still there.
(Other thing i’ve noticed is that if the came is showing the oposite side of the center of the scene, the quality of the shadow raises, and if shows the center of the scene the quality goes down).
So what is the point of removing my scene?

Thanks

  1. yeah a 4096x4096 map uses 16 times the memory of a 1024x1024 map which is too much. Something is wrong
    2.Something is wrong
1 Like

Mine the appState is up there on the other post, could you try and check if you have the same problem when compiling and executing it?

It is ready to copy, paste and execute. Just need to add the test-data library.

Thanks.