[lwjgl/joml] shadow mapping and matrices

Hello,

I’m trying to have shadows in my game, I have 2 things that should work quite the same way (in my understanding), one is, but the other is not.

I have a world, with things in it, like a floor, walls, trees etc… and a camera that is flying, looking at the hero, which is on the floor. nothing unusual :slight_smile:
I added a directional light so that i have a sun, and i made it move, and it works great. But during the night, the sun isn’t there, so i added a spotlight on my hero’s belt so that he can see where he walks. And that works great too. But i felt sad because the trees in my world didn’t have shadows, so i wanted shadows.

I could manage a nice shadow for the sun, but it’s been days and days (and nights too ^^), and i can’t do the same for my hero’s spotlight… The way i see it, shadows for a directional light and shadows for a spotlight should work quite the same way, apart from the different projection, but maybe i’m doing a big newbie mistake here.

Here’s the way i do things, i can provide code samples if need be, i hope someone can help me find my mistake.

For the sun’s shadows (the ones that are working) : i have to create a position for the sun, since it’s a directional light, it doesn’t have any. I know the direction, and i known the size of my scene, so i deduce a position somewhere outside the scene, from the direction, not too far away to keep a good resolution in my depth map. Once i have that position and direction (that is my dirlightViewMatrix), i create an orthographic projection, big enough to have all my scene in it (this is my dirlightOrthoProjMatrix). Then i render all my scene into a texture which i call dirlightShadowmap in a dedicated shader program. Then, i have to render my scene to the screen, deciding which position is in shadow and which is not, so in my vertex shader, i do that : mdirlightviewVertexPos = dirlightProjMatrix * dirlightViewMatrix * modelMatrix * vec4(position, 1.0); so that my fragment shader can then knwo the position of a fragment in the sun’s point of view. In my fragment shader, i multiply the color by some constant if the fragment is in shadow (that is, if it’s z position in light view is greater than the corresponding xy position in the depth map). As i understand it, mdirlightVertexPos is in screen coordinates, [-1; 1], so i multiply it by 0.5 and add 0.5 to convert it to texture coordinates (so the values match those in my depth map).

and as i said, it works great.

Now, here’s what i do for my spotlight, which doesn’t work as expected : I already know the position, and direction of my spotlight, so i can use that as spotlightViewMatrix. I also know the cutoff angle of my spotlight, so i can create a perspective with the cutoff angle, a 1:1 aspect ratio, a really near znear and a far enough zfar, this is my spotlightProjMatrix. Then, same as for the sun, i render the scene from that point of view in a second texture, using a dedicated shader program. So i then i render my scene, and i do the same as for the sun : mspotlightviewVertexPos = spotlightProjMatrix * spotlightViewMatrix * modelMatrix * vec4(position, 1.0); so that my fragment shader can know the position of the fragment in the spotlight’s point of view, and decide wether or not the fragment is in shadow.

But it doesn’t work as expected. everything farther than 1 world unit from my hero is in shadow. Between 0 and 1, the shadow works as expected (that is, if i put my hero against a very very thin wall, the light doesn’t go through), but no light farther than 1. If i divide mspotlightviewVertexPos by my perspective’s zfar, the light goes all the way, and there are shadows, but distorted.

So here i am, i think i may have a mistake in my perspective matrix, or the way i compare mspotlightViewVertexPos with the depth map, but i can’t find that mistake.

Hope someone can help =)

Oh, and i forgot. I rendered my shadowmaps on the screen and they show what’s expected, that is my whole scene (in greyscale) for my sun light and my scene seen from the belt of my hero (in greyscale too) for my spotlight.

Hi,

do you have some code or images for us to understand the problem better?

You are probably not using projective texture lookup when sampling the shadow map with the homogeneous light-space coordinates. Since your spot light is using a perspective transformation you need to do perspective divide to get from homogeneous space to 3D space in order to perform the depth comparison.
This was not necessary with directional lights and orthographic projection since there, the W coordinate is always 1 and dividing by 1 does not change anything. So in a way, the orthographic projection is a special-case where homogeneous coordinates = 3D coordinates.
See: http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/#spot-lights

@Stampler:
Here are some pictures, in case anyone has a similar problem. First, the working directional shadow :

https://img11.hostingpics.net/pics/513116dirshadow.png

and then the spot light. Sorry, it’s night time, and the night is dark (and full of terr… nope not yet ^^). The spot light, properly stopped by a thin wall :

https://img11.hostingpics.net/pics/433232spotshadow1.png

and the spot light, shadowed anywhere farther than 1 world unit :

https://img11.hostingpics.net/pics/215856spotshadow.png

@KaiHH:
What you’re saying totally makes sense, i feel quite stupid not understanding that by myself ^^

Thanks a lot guys, I’ll try to comeback soon with a nice shadow =)

Thank you =)

https://img11.hostingpics.net/pics/712342spotShadows.png