[Solved] Some Point Lights are not lighting Terrains in 3.3

I just upgraded to 3.3, and I noticed that point lights are not affecting terrains anymore. And strangely some point lights will work while others don’t. (even with the exact same color, radius, and parentNode)

When I add a new light to the scene with a terrain, it lights up all the models in its radius except the terrain. However if I cut/paste the terrain so that it is essentially reloaded, then the point light begins affecting it properly. So the shader is working with some point lights, but some point lights that are attached after the terrain do not seem to be getting passed to the shader.

Does anyone have any thoughts on what may be causing this or what I could do as a work around?

Edit: I should also mention that the issue occurs with my custom PBR terrains but not the stock terrain shader, so I thought it was a bug in my shaders at first… but since some point lights work with my shader then I think the code is okay, so I don’t know if it is a problem that I can solve within the .j3md .frag and .vert files, in which case I am lost on where to look next

Thanks :slightly_smiling_face:

That sounds like an issue with the way the lights get passed into shaders. I’m not sure if there were any breaking changes in 3.3, but the way I’d start debugging it is to apply the same material to a regular mesh object and see if the problem also happens there. The terrain mesh has some custom LOD stuff going on and I wouldn’t be surprised if the calculations of what’s in the range of a light somehow broke.
If the problem persists with a more simple mesh, it’s probably either an issue with the material itself or with the way the engine calculates what’s in range of a point light.

1 Like

I tested this and found that the problem still happens with a standard mesh using the terrain material.

I didn’t expect that to be the case, since I did manage to get the same terrain material to render point lights in the scene editor by cutting/pasting the terrain to forcibly reload it.

I’ve also tried calling a handful of methods like forceRefresh() and updateBounds() on the terrain, with no success.

Hmm, this is beyond my knowledge then :confused: Maybe someone with the knowledge how lighrs work internally can pitch in?

1 Like

After some more testing, I’ve found that it only occurs with my Terrain shaders that are using the SinglePassAndImageBasedLighting Technique - I have an older custom Terrain shader that uses the old MultiPassLighting Tehcnique thats used in Lighting.j3md, and point lights work 100% of the time in that custom terrain shader.

So this is happening exclusively with Terrain Shaders using the SinglePassAndImageBased Technique, but can be “fixed” if the terrain is reloaded (although this isn’t a feasible work-around in-game unfortunately)

So that makes me think again that it is a bug in my shader code - but then I am still confused as to why some point lights will work but only if they were in the scene before the terrain was loaded in, as that makes me think it is not a shader code problem.

Just thought I’d point out that even though it says single pass that it still might make multiple passes if there are more lights than can be handled in a single pass. I don’t really know enough about your scene to know if that’s an issue or not… but it could be one explanation of why sometimes lights work and sometimes they don’t. Could be that only one pass out of ‘n’ is working and the lights are sometimes in the working pass and sometimes not.

1 Like

I decided to look back at my fragment shader code based on what you said, and I compared my 3.3 version to the working 3.2 version on github.

And it turns out it the issue was caused by one single line of code that I mistakenly commented out at the end of the terrain shader while upgrading it to work with 3.3:

gl_FragColor.a = albedo.a;

Apparently the point lights were not working because I was never assigning an alpha value to gl_FragColor as a final output, which I think I overlooked since a terrain material doesn’t typically have partial transparency like a normal shader.

A dumb mistake on my part, but I’m glad I can call this solved now. I’ve lost count of how many times I’ve wasted multiple days due to a single line of code, but its probably best I don’t know the exact number :sweat_smile:

I appreciate the help debugging this :slightly_smiling_face:

2 Likes

Something to keep in mind. When all is said and done, a rendered mesh is nearly directly a single OpenGL draw call. The Geometry picks the shader and then the mesh is the draw call.

It was a really nice realization for those of us old dogs that used to have to do OpenGL directly. The buffers make a lot of sense in that case… they are bound to vertex attributes and then the draw call is made.

The point being, the vertex buffers of the mesh are there in the shader. If you think you see them not in the shader then it is your perception and not fact… because they are in the shader. They cannot escape the draw call… because they ARE the draw call.

Sometimes in this chaotic world of software development, we need to build a base of ‘ground truth’, things we never have to question… that should be one of them for JME developers. It helps us focus on the million other things that could be wrong.

2 Likes