Cast shadow on same plane, depth map from alpha value

Hello,
I was reading up on how shadow mapping works. We create basically a depth map from the light’s perspective and if an object is in the way then we make the fragment darker on the object behind the first object. For that you need a) the light source, b) an object and b) some other object on which the shadow is cast.

But I wonder if I can do the same shadow mapping but with just one plane object and cast the shadow on itself.

I have a plane that is showing a terrain using tiles. Each quad of the plane have a different terrain tile. But there is also a z component that is simulating the depth of the terrain. Currently all I do is to add an alpha value so that the greater the z the darker the tile is drawn. For example, z=0 is alpha=0, z=1 is alpha=0.3, z=2 is alpha=0.6, and so on.

To show the depth better to the user I want to add a shadow.

For that I was thinking that I use the same shadow mapping technique. I create a depth map not from other objects but from the alpha value of the fragments on the terrain.

Then alpha=0 would be solid and would cast a shadow “down” to the tiles on the same object.

Is that even possible?
Was something like this done before and I could read somewhere how somebody else done it?
Google is not really a help because I only find descriptions the normal shadow mapping technique.
I did the example in Gimp how it should look like.

tiles-with-shadow tiles-no-shadow

Is your map only ever viewed from above like that?

I assume the first image is the one you want and the second image is something else?

The first image is how it should look like (made in Gimp), the second is how it looks now.

Is your map only ever viewed from above like that?

Yes. The light source is not directly above. I calculate the position of the sun based on the in-game time, based on the earth’s model. So, the shadow should also reflect the position of the sun.

I’m also just using the JME3 TerrainQuad.

I was thinking about a little more and it shouldn’t be that hard. Basically, I need to create a depth map texture, but not using the gl_FragCoord.z for the depth but gl_FragColor.a (where gl_FragColor.a==0 means fragmentdepth=0.0). Based on this tutorial: Tutorial 16 : Shadow mapping

Then I use the depth map texture in the fragment shader of the terrain plane and “cast” a shadow based on that depth map. The only problem is that I need to “cast” the shadow outside the uv-coordinates of the tile.

Maybe I’m thinking it all wrong. It’s not really a shadow. All I need is basically an alpha texture that looks like a shadow that I draw on top of the texture of the tile.

Maybe multi-pass is the easiest solution?

I will just generate an alpha texture from the point of view of the light. Something like this:

tiles-shadow-alpha

In the first pass I will draw the terrain with the tiles texture and in the second pass I will draw the terrain again but now with the generated alpha texture with the shadow. That should work?

The thing with developing games is that half of what you think you see is usually a trick. Smoke and daggers.

You’re explaining your dilemma as best you can - and I comprehend what you’re trying to do, but I think it would be a lot easier to find a solution if we had the “big picture”.

What game is closest to what you’re trying to make? Is it a side scroller? A top-down tile-based game like the old Zelda games? I think if we knew that we could probably point you in the right direction. Most solutions are not what appears to be the most natural.

Right now all we know is you want to project a shadow - but there are many ways to achieve that - and the best way to find out what will suit you is by seeing the “big picture” - or at least see a little more of the canvas than a few tiles with a shadow.

Yes, sure, if it helps. I was trying to describe the problem. It’s basically a game like Dwarf Fortress or Rimworld. The terrain is the JME’s TerrainQuad with an alpha map for the terrain tiles.

As you can see, in Dwarf Fortress the tiles have a shadow around them. But there are no actual lights, everything is just a texture. I was thinking how to replicate that but with a real dynamic light.

My game:

Dwarf Fortress

Terrain quad seems silly to use for this but I understand if you don’t want to create your own mesh.

However… ultimately that’s where you will end up.

This problem would be trivially solved by just changing the near/far value of the quads that make up your terrain, after all.

Sorry, what do you mean?

you have terrain quads which are all stitched together in 3D… which is stuff you don’t need because you never look at it from the side.

If instead of terrain quads you used an actual mesh of just quads. Flat quads. x,y space with each quad having a single Z value for all four corners.

…then if you wanted some part of the terrain to look higher, you’d just set the z value of that quad higher. Shadows would be automatic.

If you do that with the poorly-suited-for-your-needs TerrainQuad then you just end up with smooth shadows like the terrain was actually smooth bumps instead of just raised/lowered quads.

Not sure how else to explain it in words.

What you are doing seems closer to a two block high minecraft world than fully 3D terrain. So TerrainQuad is dragging around 90% stuff you don’t even need.

Thank you, I see what you mean.

Can’t I just rise up the terrain tile? Would there be a shadow cast from the “mountain”? I didn’t actually looked into TerrainQuad and shadows. That would also solve my problem.

You are of course right. But wouldn’t I have then like 16,384 individual objects for a 128x128 terrain (and even more individual objects for a bigger terrain)? I don’t think that’s a good idea because of performance?

Btw, currently it’s not two blocks high, it’s totally flat. The depth is just simulated.

Yes, but I’m saying: stop simulating depth.

Yes, but the shadows would be smooth… like diagonal. Imagine the different side views:
TerrainQuad:
image

Mesh of flat quads:
image

Then imagine the difference from the shadows cast sideways by those terrain profiles.

Your image seemed like you were looking for the second way. Else you need to keep in mind that the elevations gradually increase between tiles… so that raised tile is only raised at one edge (or the lower tile is only lower at one edge).

No. Because you’d be making a custom mesh. One object. One draw call. Split the world up how you like but you’d have some utility where an array of tiles goes in, mesh comes out.

Edit: to be most accurate, the mesh of quads way would be like:
image
…because you likely don’t even need the side walls unless your sun will be extremely horizontal.

Note: if making a custom mesh seems scary and/or you just want to try it and don’t care too much about raw generation efficiency, you could build a big array of regular JME Quad mesh Geometry and then batch them down to one spatial (assuming they all had the same material… one spatial per material otherwise).

Edit: GeometryBatchFactory (jMonkeyEngine3)

…learning how to make custom meshes is very rewarding in the end, though.

I didn’t know about this. I was thinking that I just generate vertices and indices buffers.
But I can use GeometryBatchFactory#mergeGeometries() to merge multiple individual quads into one single mesh?

Who wrote GeometryBatchFactory? It’s missing copyright and documentation.

Thank you for your help.

The JME team wrote it and maintains it. It’s part of jme-core. Specifically, I think normen probably wrote the original version. It’s licensed the same as the rest of the engine and the copyright notice in the source file is just an oversight.

Yes, if you have a bunch of compatible meshes it will merge them together into one mesh.

Making your own mesh is more efficient because you can control everything and won’t have a bunch of intermediate data structures that you will throw away… but it is harder.

I want to thank pspeed and jayfella for your help here. The custom mesh works good for casting shadows. It’s the effect I wanted. If you want to see my implementation for the custom mesh, I put it on Github. It’s basically a terrain made of 5 faces boxes (no need for the bottom face because it’s a terrain).

I think I just need to adjust the shadow effects. But in principle it works.

3 Likes