Advertisement

Shadow mapping - pass custom varying to FBO, and read it?

Started by April 10, 2020 10:16 AM
9 comments, last by Jernej.L 4 years, 9 months ago

I'm using shadow mapping with GLSL on a partially 3d game, where shadows are cast from 3d objects onto 2d sprites - this works very well.

Now i would also like to have sprites cast proper shadows (with depth), and consequently i need to render them into shadowmapping pass - but i would like them to NOT cast shadows over the sprites themselves and just ignore the shadows (but take into account shadows from buildings / 3d objects), i can mark when sprites are rendered by sending a varying from vertex to fragment shader, but i'm not sure how to send - to - and sample this out of shadowmapping texture in the end(using texture() shader function )

How would be a good idea to approach this?

Projects: Top Down City: http://mathpudding.com/

Are you talking about the removing self shadowing?

NBA2K, Madden, Maneater, Killing Floor, Sims

Advertisement

I guess a robust solution would be to render 2 SMs, one for 3D objects and one for sprites.
When shading 3D objects you'd need to sample both SMs (or combine them to a single SM if that's faster).
When shadowing sprites you sample only SMs from 3D objects.

But maybe you get away with a single shadow map, and add bias from the sprites (so moving them slightly towards the light), to prevent self shadowing.
For a top down game this could work pretty well because precision should be good everywhere.

Yes, i am talking about self-shadowing, and JoeJ's guess is good, it's for a top-down game. But this self shadowing issue is with 2d sprites - which cannot be discarded by means of bias and z-buffer, because they can be on surface of 3d shape that also casts shadows.

Let me show in pictures, the game has a hybrid shadows system right now, where buildings cast shadow map, but vehicles are simply double rendered fake shadows on the same spot (without depth test), where 1 pass renders sprite shadow and other one the proper sprite. This is all rendered on the same ground level, so the coordinates are same (depth test is off, otherwise this would all get discarded).

The problem with using 2 ways to render shadows is, that it doesn't look good, the vehicle shadow shows up overlaid in existing map building shadows, so you get some kind of a double shadow effect that i cannot figure out how to correctly remove / combine:

 

What i am thinking is, to somehow combine this approach, i'd like to render vehicles into shadow map pass at some height above car (so that shadow would show up projected parallax based on sun location properly), but when the shadowmap pass would be checked for vehicle, they should not be checked against its own casted shadow map (just from buildings and other buildings). - i'd like to do this without adding additional pass (i could solve this by having 2 shadow maps, one for sprites and other for map, but this seems like such a overkill for this game)

Projects: Top Down City: http://mathpudding.com/

Jernej.L said:
The problem with using 2 ways to render shadows is, that it doesn't look good

Maybe it would look good enough if you would blur the vehicle shadows, so they look more like AO. Worth a try. Many games do this and i guess it looks fine if your SM shadows are also soft, like shown in the images.

that's an option sure, but it won't look as good, if there was a way to combine these 2 approaches, this would look far better imo, i know i can do it with 1 extra pass but it seems truly redundant to do that just for this.

Projects: Top Down City: http://mathpudding.com/

Advertisement

Jernej.L said:
i know i can do it with 1 extra pass but it seems truly redundant to do that just for this.

I see multiple ways to do this extra pass work, either using multiple passes or multiple render targets to accumulate both shadow terms and then combine using a maximum of 1. No idea what's best here.

But maybe i can help to accept the need for such extra pass work, by describing what would be the alternative single pass approach:
To evaluate shadow term per pixel, you do the usual SM lookup which is constant time.
Next you need to get sprite shadows, which can't be done in constant time. You have to loop over all sprites, or put them into some spatial acceleration structure AS like a regular grid to limit search space.
I guess this is is more work to implement and ends up slower.

Ok, i am considering your suggestions and i'm thinking about render targets - because i can render to multiple at the same time, and iterating thru all shadows would indeed most likely be a worse solution.

I could render to 2 render targets - one unshaded, and 2nd one would contain shadow mapping opacity, and when sprite shadows are rendered, that would be combined with the shadow map pass. Lights (rendered as texture sprites) however, would get additively blended in 1st render target, and subtract out a “portion / area” of shadow mapping.

So.. shadow amout = (shadow mapping combined with sprite shadow opacity) minus (light intensity from rendering lights)

Then i just need to combine this out into seen framebuffer with 1 more step / simple shader where i clamp shadow to min / max ambient environment and add it to rgb pixel:

final = rgb pixel - shadow

Does this seem like a good / sane way of doing this?

Projects: Top Down City: http://mathpudding.com/

Jernej.L said:
Does this seem like a good / sane way of doing this?

Yeah, it's what i had in mind, but i assumed you only have 1 sunlight and constant ambient. You mentioning multiple (shadowed?) lights could complicate thing further maybe.

While thinking of it all, i got back to the initial thought about self shadowing, which would allow single pass obviously working this way:
Include alpha tested sprites to shadow map, rendered as quads slightly above the ground. Then when rendering framebuffer render the visible sprites slightly above their shadow to prevent self shadowing.
This should work, if you can live with the popping caused by SM texels turned on / off as vehicles are moving. Surely an option if SM resolution is high.

There is an often used technique to prevent shadow acne, which works by using SM texel frustum and slope from occluder polygon plane to calculate exact displacement necessary to avoid acne.
I don't remember the name of this, but would work to avoid self shadowing too, and to minimize ‘slight’ displacement if necessary.

The sun is only one, and is meant to be the only thing that would cast shadows (during night, it can simulate full moon lighting).

Lights from vehicles and other lights would not cast shadows - just provide basic lighting (but one that should not go thru walls as in top down game this would be immediately seen as a bug)

The solution you suggest for rendering shadows to shadow map makes sense - i already do this for trees, which are basically sprites that are above ground.
But this being suitable for trees, would probably not work well for cars since i cannot render cars above their actual position - this would make cars appear to hover above ground and probably make players sea-sick since camera is in permanent top-down view.

I suppose i can try instead to render the car shadows under their position instead, and see if they would still get casted on the ground properly.

Projects: Top Down City: http://mathpudding.com/

This topic is closed to new replies.

Advertisement