Lighting and Shadowing problem

Hello everybody.

The problem is that a lightsouce lights also object hidden behind another light object. Is there any known solution (preferable without the pssm because pssm does not look good on high scales and produces lots of artefacts.) to this problem.



Here the problem in detail:

http://i.imgur.com/Dybah.png

Notice the moon’s behind the planet should not get lit. As for lighting, i have only placed a pointlight at the center of the sun.

Have you tried all of the PSSM parameters, in particular the 2nd two PssmShadowRenderer constructor params? It might all break down on a very large scale, I haven’t tried. This will definitely be your easier solution.



If not using PSSM you will have to ray-trace the object to the light, see if it is obstructed, and supply some value to a custom lighting shader that will affect the light intensity.

This video shows the problem with the pssm.



http://www.youtube.com/watch?v=3OW5oFT8WCk



The code for setting up the pssm:
[java]
PssmShadowRenderer pssm = new PssmShadowRenderer(assetManager, 4096, 3);
pssm.setFilterMode(PssmShadowRenderer.FilterMode.PCF8);
pssm.displayDebug();
viewPort.addProcessor(pssm);
[/java]

I have also tried different settings for the two parameters. Always the same strange shadowing errors. The planets and moons are simple spheres generated in jme with lighting material.

For other angles in the 'solar systems the pssm works correctly, but not for all of them... :(

hmm, what sort of distances do you have there (in jme units) between the planets?

Also are you using the latest version?

Hmm, this scene is near to 3000 wu large, nothing fancy i guess. Its just a test cas, the final scene should be much bigger.



I have tested with nightly and todays svn…

It could be related to this topic, but I doubt it.



It almost seems like it, or a parent node, is being culled out as you move the camera. Have you tried just a single planet with no fancy node hierarchy and if has that flicker?

I have indeed a fancy node hierachy to allow all kind of different rotations at the same time.



I am building a testcase to see if this happens also with a simpler layout

I think I have seen this flickering before when I had some parent nodes have different shadow settings than the child nodes, and then some got culled and bad things happened. It was a while ago though and I can’t remember the exact cause.

Ok, here is a testcase showing my problem.



I have not seen the flickering yet, but i have tracked down the issue of wrong shadow drawing. It seems that the pssm does not take my pointlight as source, but using ‘some’ vector for directional light. I said ‘some’ because i tought that if i do not set a direction, no directional light gets simulated.



Hm. Any way to switch off directional light shadows and enable the point light?



[java]package mygame;



import com.jme3.app.SimpleApplication;

import com.jme3.light.AmbientLight;

import com.jme3.light.PointLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.FastMath;

import com.jme3.math.Quaternion;

import com.jme3.math.Vector3f;

import com.jme3.renderer.RenderManager;

import com.jme3.renderer.ViewPort;

import com.jme3.renderer.queue.RenderQueue.ShadowMode;

import com.jme3.scene.Geometry;

import com.jme3.scene.Mesh;

import com.jme3.scene.Mesh.Mode;

import com.jme3.scene.Node;

import com.jme3.scene.Spatial;

import com.jme3.scene.VertexBuffer.Type;

import com.jme3.scene.control.AbstractControl;

import com.jme3.scene.control.Control;

import com.jme3.scene.shape.Sphere;

import com.jme3.shadow.PssmShadowRenderer;

import com.jme3.util.BufferUtils;

import com.jme3.util.TangentBinormalGenerator;

import java.nio.FloatBuffer;



/**

  • test
  • @author normenhansen

    /

    public class Main extends SimpleApplication {



    public static void main(String[] args) {

    Main app = new Main();

    app.start();

    }



    @Override

    public void simpleInitApp() {

    Node mainNode = new Node();

    rootNode.attachChild(mainNode);

    addPlanet(addPlanet(mainNode, 100f, 500f, 20f), 10f, 130f, 50f);

    this.flyCam.setMoveSpeed(1000f);

    this.cam.setFrustumFar(10000000);

    /
    * A white, spot light source. /

    PointLight lamp = new PointLight();

    lamp.setRadius(100000f);

    lamp.setPosition(Vector3f.ZERO);

    lamp.setColor(ColorRGBA.White);

    rootNode.addLight(lamp);







    /
    * Advanced shadows for uneven surfaces */

    PssmShadowRenderer pssm = new PssmShadowRenderer(assetManager, 1024, 3);

    pssm.displayDebug();

    viewPort.addProcessor(pssm);





    }



    @Override

    public void simpleUpdate(float tpf) {

    //TODO: add update code

    }



    @Override

    public void simpleRender(RenderManager rm) {

    //TODO: add render code

    }



    private Node addPlanet(Node parent, float radius, float rotationOffset, float rotationSpeed) {

    Node tmp = new Node();

    Circle circ = new Circle(rotationOffset, 100);

    Geometry circle = new Geometry("g", circ);

    Material mat_tl = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");

    mat_tl.setColor("Color", new ColorRGBA(1f, 0f, 1f, 1f)); // purple

    circle.setMaterial(mat_tl);

    parent.attachChild(circle);



    Sphere rock = new Sphere(100, 100, radius);

    Geometry rock_shiny = new Geometry("Shiny rock", rock);

    TangentBinormalGenerator.generate(rock); // for lighting effect

    Material mat_shiny = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");

    rock_shiny.setShadowMode(ShadowMode.CastAndReceive);

    //mat_shiny.getAdditionalRenderState().setWireframe(true);



    // mat_shiny.setBoolean("UseMaterialColors", true); // needed for shininess

    mat_shiny.setColor("Specular", ColorRGBA.White); // needed for shininess

    mat_shiny.setColor("Diffuse", ColorRGBA.White); // needed for shininess

    mat_shiny.setFloat("Shininess", 5f); // shininess from 1-128

    rock_shiny.setMaterial(mat_shiny);

    tmp.attachChild(rock_shiny);

    tmp.setLocalTranslation(rotationOffset, 0, 0);

    rock_shiny.addControl(new rotationControl(rotationSpeed));



    parent.attachChild(tmp);

    return tmp;

    }



    public class rotationControl extends AbstractControl {



    float rotationSpeed;

    float currentAngle = 0;



    public rotationControl(float rotationSpeed) {

    this.rotationSpeed = rotationSpeed;

    }



    @Override

    protected void controlUpdate(float tpf) {

    currentAngle += this.rotationSpeed * tpf;

    currentAngle = currentAngle % 360;

    if (this.spatial.getParent().getParent() != null) {

    this.spatial.getParent().getParent().setLocalRotation(new Quaternion().fromAngles(0, currentAngle * FastMath.DEG_TO_RAD, 0));

    }

    }



    @Override

    protected void controlRender(RenderManager rm, ViewPort vp) {

    }



    public Control cloneForSpatial(Spatial spatial) {

    throw new UnsupportedOperationException("Not supported yet.");

    }

    }



    public class Circle

    extends Mesh {



    /**
  • The center.

    */

    private Vector3f center;

    /**
  • The radius.

    */

    private float radius;

    /**
  • The samples.

    */

    private int samples;



    /**
  • Constructs a new instance of this class.

    *
  • @param radius

    */

    public Circle(float radius) {

    this(Vector3f.ZERO, radius, 16);

    }



    /**
  • Constructs a new instance of this class.

    *
  • @param radius
  • @param samples

    */

    public Circle(float radius, int samples) {

    this(Vector3f.ZERO, radius, samples);

    }



    /**
  • Constructs a new instance of this class.

    *
  • @param center
  • @param radius
  • @param samples

    */

    public Circle(Vector3f center, float radius, int samples) {

    super();

    this.center = center;

    this.radius = radius;

    this.samples = samples;



    setMode(Mode.Lines);

    updateGeometry();

    }



    protected void updateGeometry() {

    FloatBuffer positions = BufferUtils.createFloatBuffer(samples * 3);

    FloatBuffer normals = BufferUtils.createFloatBuffer(samples * 3);

    short[] indices = new short[samples * 2];



    float rate = FastMath.TWO_PI / (float) samples;

    float angle = 0;

    for (int i = 0; i < samples; i++) {

    float x = FastMath.cos(angle) + center.x;

    float z = FastMath.sin(angle) + center.z;



    positions.put(x * radius).put(center.y).put(z * radius);

    normals.put(new float[]{0, 1, 0});

    indices = (short) i;

    if (i < samples - 1) {

    indices = (short) (i + 1);

    } else {

    indices = 0;

    }



    angle += rate;

    }



    setBuffer(Type.Position, 3, positions);

    setBuffer(Type.Normal, 3, normals);

    setBuffer(Type.Index, 2, indices);



    setBuffer(Type.TexCoord, 2, new float[]{0, 0, 1, 1});



    updateBound();

    }

    }

    }

    [/java]

oooooh I see, it is a point light and not a directional light.



I don’t know enough about PSSM for this, have to pull in @nehon to help. But I think you need the direction vector.

Arr, after rereading the doc i have found the line where it says that point light cannot be used for pssm currently. i guess i have to find another system

there is no shadows for point lights right now in JME3.

I have to implement them. It should not be so hard now we can render to a cube map.

The real difficulty right now is to get me off Diablo 3.

I have the same problem with SpotLight.



Well I hope it get implemented soon :smiley:

Yeah. Looking forward to be able to use PointLight with pssm :slight_smile: Thanks nehon!

@nehon said:
The real difficulty right now is to get me off Diablo 3.


I can understand that. The koreans are finishing the game in 5 hours. :)
@zzuegg said:
I can understand that. The koreans are finishing the game in 5 hours. :)

uhuhuh....too bad I'm french :D

A hacky way I use to make shadow casting point lights in the Source engine is to use six spot lights(spot lights can cast shadows) with a FOV of 90 facing in different directions. It’s not the right way, but it gets the job done.

1 Like

Presumably you have one sun (any binary systems?) and only a modest number of planets and moons on screen at once.



Would it be too expensive (for objects close enough to the camera to be worth it) to cast a line from the centre of the object to the centre of the sun and reduce the brightness based on the size of the largest object that intersects the line?

How’s Diablo? :stuck_out_tongue:



Beat the crap out of him on Inferno yet? :wink:

I’m trying to give up a bit, i just play from time to time so that the withdrawal symptoms are not too heavy…

Tap Tap Tap…

But I’ll eventually beat him…that just a matter of gear… :wink: