I am getting odd shadows on a smoothed sphere. Why are they there and how do I get rid of them?

Here’s what I see:


I’m looking at the shadows along the sphere itself. That dark spot next to the sphere is a hole in the ground :stuck_out_tongue:

Really all I did to this sphere was create the default sphere shape in blender, clicked the smooth button, then exported it with the ogre exporter to a mesh.xml.

My code for the material and such is as follows:

geom = assetManager.loadModel("assets/Models/Sphere.mesh.xml");
Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
mat.setBoolean("UseVertexColor", true);
mat.setBoolean("UseMaterialColors", true);
mat.setColor("Ambient", color);
mat.setColor("Diffuse", color);
mat.setColor("Specular", color);
mat.setBoolean("VertexLighting", true);
geom.rotate(0, 180 * FastMath.DEG_TO_RAD, 0);
geom.move(1f, 0, -1f);
geom.setShadowMode(ShadowMode.CastAndReceive);
geom.setMaterial(mat);

And my lighting is set up as such:

DirectionalLight sun = new DirectionalLight();
sun.setColor(ColorRGBA.White);
sun.setDirection(new Vector3f(.7f, -0.5f, 0.05f));
rootNode.addLight(sun);

AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(0.3f));
rootNode.addLight(al);

final int SHADOWMAP_SIZE=4096;
final int nbSplits = 4;

DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer(assetManager, SHADOWMAP_SIZE, nbSplits);
dlsr.setLight(sun);
viewPort.addProcessor(dlsr);

While reducing the SHADOWMAP_SIZE to something like 512 does make the strange shadows on the sphere go away, it also makes the shadow the sphere casts look very bad.

  • Why are these shadows here?
  • How do I get rid of them?

Thank you!

Try to play with PolyOffset parameters in PreShadow technique - make a copy of lighting.j3md file.
You should also make sure that your shadowed surfaces and not lighted up surfaces have the same brightness - it would hide some artifacts. Here on your screen you have black shadow but right side of the sphere is just a bit darker - too much ambient I think.

I don’t remember if DirectionalLightShadowRenderer have the ability to blur edges, check it and enable if it is present (use Poisson), enable hardware shadows. With blurred edges you can try to decrease shadowmap size, try with 2048.

In general, shadows are so large topic that one could write a book about them. And… there are such books :wink:
For simple solutions engine’s stock shaders are all you need. But if you want to make sometging bigger you need to start reading NVidia’s GPU Gems :wink:

Yeah, shadows and transparency are similar in that. The straight-forward things look great and then you have some artifact later and wonder how to fix it… oh, boy. :slight_smile:

Thank you!
Looks like

dlsr.setEdgeFilteringMode(EdgeFilteringMode.PCFPOISSON);

fixed the odd shadows. I still want to try the other things you mentioned though, as my sphere still looks a bit jagged with the shadows.

I see the PolyOffset values in lighting.j3md.
Well, it has two of them actually, one in PreShadow and one in PostShadow.
PolyOffset 5 3
PolyOffset -0.1 0
These just look like magic numbers to me. Where can I go to find out what they mean?

When you say to enable hardware shadows, I assume you mean in the shader.

mat.setBoolean("HardwareShadows", true);

Poking around I also found a ShadowMapSize variable in the shader:

mat.setFloat("ShadowMapSize", 2048);

Is this the shadow map you suggest I set to 2048, or do you suggest I set my dlsr’s shadowmap size to 2048? Does it matter which one I choose? What’s the relationship between these two seemingly similar values, and how do they differ?

Thank you very much for your help!

Polygon offset in PreShadow technique is related to shift on z-axis in projection coordinates during rendering geometries into z-buffer. For now treat them as just magic, until you fully understand how shadowmap is created and how it is working. Long story short - adjusting those values help with selfshadowing artifacts like moire patterns but in other hand can be the cause of ‘peterpanning’ effect.

Both hardware shadows and shadowmap size should be configured in shadow renderer, the reason that such fields exists in material and techniques is that renderer must pass those values into shader.

Something has broken when making my own Lighting.j3md. I copied Lighting.j3md from the github repo and renamed it. However, the error I’m getting is:
java.io.IOException: Shader statement syntax incorrect: VertexShader GLSL100 GLSL150: Common/MatDefs/Light/SPLighting.vert

How do I go about debugging something like this? The stack trace doesn’t seem to indicate where the error occurred in SPLighting.vert. Likewise, this is using the SPLighting.vert in the common assets, which works just fine with the built in SPLighting.vert. I’m not sure why a syntax error has occured just by making another file that refers to it.

I also haven’t changed anything in the file yet, it’s still just an exact copy of the file in the repo.

It’s complaining about your j3md file. That statement is in the j3md.

Wrong branch/version or something… Which version do you have installed? Open JME’s core jar with winrar and look there for that j3md file.

That did the trick. I guess I should update the version of jme3 I’m using. Thanks again for the help!

Keep using the stable version. Btw, I’m still working on 3.0 :slight_smile:

I’ve upgraded from 3.1.0-beta1 to 3.1.0-stable, and it’s changed the shadows of my sphere a little bit:

Should I still try tweaking the PolyOffset?

Now looking at my custom lighting.j3md, which so far is still just a copy of the one in the j3me-3.1.0-stable core jar, and there seems to be two places for the PolyOffset, both in the PostShadow technique, with slight differences. Should I just change both?

I have no idea what BACKFACE_SHADOWS is, as I said I’m still on 3.0 (with my own shaders including very nice shadows), but your adjustment of PolyOffset should be made in PreShadow. Yes, polyoffset have two values. Don’t remember the exact meaning of them, just change one by +/- 0.1 several times and see what happened.

I mean there’s two PostShadow Techniques in this single .j3md file, and one PreShadow Technique. I’ve just been modifying them all, but they don’t seem to be doing anything. I’ve now set them to some absurd values like 20 -10 and I don’t see any difference. Any other ideas?

Thanks again for your help!

Ahh, I see. Two postshadow techniques. One for GLSL100, other for GLSL150. It depends on your settings, but I bet that GLSL150 is the one that is actually active.

Did you created your material with that new j3md file?

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

Oh… I have been.

That would explain why my modifications to my custom lighting j3md aren’t doing anything! Bad mistake on my part, thank you!

Had to set my values in the PreShadow to 6.3 12 to get the artifacts to go away mostly, but I think it looks good enough. Still a little jagged. I don’t think the PostShadow numbers did much, if anything.

Though, once i added my ambient light back in:

AmbientLight al = new AmbientLight();
al.setColor(ColorRGBA.White.mult(0.4f));
rootNode.addLight(al);

The artifacts came back. It also looks far too bright. I just want the area not facing the light to not be pitch black. Is the ambient light the way to do this or is there a better way of doing that?

Thanks again for all your help!

Ambient light is the way but you need to use some small values for it.
Artifacts are still there but they are hidden by the lack of ambient. You need to adjust shadow intensity (??, there was a param to make shadow less black) and ambient color. I did not last too long with stock shadowrenderers and I don’t know all the tricks.

That’s the problem with JME’s approach - shadows are drawn as dark (black) pixels on the objects, but in real life shadow is just an absence of light. Some artifacts will never appear if you don’t draw color because of NdotL and at the same time don’t draw it because of shadowmap.

Are you referring to the shadow intensity param? I played around with that but that just seems to change how dark the shadow casted is, not the lack of light on the object itself. What sort of small values are you thinking? Here’s what I get if I do the following:

Shadows:

dlsr.setShadowIntensity(0.2f);

Ambient Light:

al.setColor(ColorRGBA.White.mult(0.1f));

One side of the sphere is still too dark, and if I raise the intensity of the ambient light, the other side gets clearly brighter, but the other side still stays a bit dark, and artifacts start to show up.

Any ideas?

And thanks again for your help, you’ve been very helpful!

Ambient increases brightness in general - it lights up all surfaces on the scene.
Directional lights lights up only those surfaces that are facing the light vector - that’s why your sphere is lightened up on the left side and darkened on the right. This is simple lighting, there is no shadow at the moment.
So, by applying ambient light you light up the whole scene, including both sides of your sphere.

And here comes shadow renderer - after ‘calculating’ shadow’s positions renderer dims the particular part of your surfaces, it is just the next layer of your rendered scene.
Shadows made by shadowmap sometimes have artifacts, by drawing shadow you draw shadow’s artifacts, especially on the edges, it is simple. So as far as I understand, the only way to get rid of them (with JME’s shadows implementation) is to blur them to make them less visible (edge filtering) or remove ambient and keep shadows black. Black artifacts are not visible on black surfaces.

There was a parameter to set up edge filtering, try setEdgesThickness function.

Few years ago @Perjin was so kind and shared his shadow renderer here on the forum. It was a great starting point for me, because I had serious shadow related problems, including artifacts. All I have today evolved from that code sample. Unfortunately it is only for point lights, but you should try it anyway.