0
\$\begingroup\$

I have read some other posts with almost identical titles on here, but they are not exactly what I am looking for. (What I have seen come up a lot in 2D shadows is some sort of "ray-cast effect").

Songs of Syx screenshot

I am trying to figure out something similar to how it's done in "Songs of Syx" (picture above is from this article) or this video

I am pretty sure, the shadows in that game or similar are done in another way. The shadows could perhaps be sprites.

You have some dynamic directional light (effectively the sun) that revolves around the the terrain. Every sprite cast a shadow on the terrain (only).

I'm not sure, but I THINK that each sprite has a "depth texture" in addition to its color (and normals). Similar to to the illustration below:

Depth + colour

So [2.] (the depth texture) has a value [0-1] for every pixel. Where 0 (or black) cast no shadow, and 1 (or white) indicates a "maximum height". Let's say a height (Y-value) of 1 correspond to 1 in world units. And you could imagine that the blue rectangle in the picture has dimensions of (1,1,1).

I am somewhat familiar with 3D-lighting and shadow-mapping, where I rendered the geometry first from the light's perspective to a a depth texture bound to a framebuffer object. Then I render all geometry again to do depth testing with the depth texture.

I would think something similar can be done in this case? Only with the depth texture instead of vertex geometry.

And since no sprites need to cast shadow on other sprites (only the terrain), maybe it's possible to render the sprites and a "depth map" in a single shader pass?

But I am not sure how I could do this. I would like the light position to be a 3D coordinate. So when the light is above the sprite it cast no visible shadow (it does, but the sprite hides it). And when the light is all the way down the horizon (below the virtual height of the sprite), the shadow cast has to be limited in distance (let's say the shadow cast cannot have a length greater than the virtual height of the sprite).

The terrain that receives the shadow lies entirely flat on the XZ-plane. The camera is not orthographic perspective. And you can pan around and "pitch" it to some degree.

How can I achieve this?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I have found a solution where I am using a depth texture for each sprite to simulate 3D shadows similar to the illustration in my question.

I don't know if "Songs of Syx" in particular does it the same way, but i suspect it's in the same ball park.

I am rendering the scene to multiple textures bound to a framebuffer object.

Diffuse (rgb8), Normals(rgb8), Height(red8) (Off screen buffers)

After the entire scene is rendered I do another shader pass where I calculate shadows. (Height texture only). In the fragment shader, every fragment cast a ray FROM it's position TOWARDS the light. I sample pixels from the height texture along that ray (with a delta value), if any sampled pixel values are greater than the value of the fragment you are processing, then you know it is in shadow.

Here you could "accumulate shadow" if you want, based on how many pixels you "hit" while tracing the light.

Then you could store the accumulation in another "shadow texture" used in the final lighting calculations.

At this point, you have a "shadow texture", "normal texture" and "color texture" of the entire scene. To use with any lighting algorithms you want.

I am still testing things out, but I am very happy with how it looks, feels and performs. :)

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .