A Quick Recap
In the development of making a custom engine with it’s own 3D-renderer in addition to skinned mesh animations we wanted to add something that would add a bit of flare to our game, and a very common project for a 3D-renderer is shadow mapping, so that’s what we chose.
Surprisingly Simple
In the beginning having no knowledge of shadow mapping it immediately seemed daunting and a little scary but it turns out it’s actually really simplistic. So, if you wanted to learn how to program shadow maps into your own project here is how you would do it.
Rendering the Shadow Map
First you need to determine what kind of light you wish to project shadows, for this instance I’m going to use a directional light because it is the easiest. Second, you’re going to need a second camera completely separate from your main camera. This new camera will be a representation of the position of the light, so find the perfect location and angle of your camera so you get the outcome you’d like. In addition to getting the perfect location and the proper angle, you need to have the correct camera view depending on your light type. For a directional light you would normally use an orthographic projection while for a point light you would use perspective projection. The type of projection is important for the type of light you are using in order to get the correct output. Now that we have our light and our camera, we can start using render to texture to render our scene to our depth buffer. It is important when rendering to the depth buffer you need to render in light space in the vertex shader, to do this you need to multiply the objects World matrix by the lights view matrix and the lights projection matrix. Fortunately, you don’t need to render anything in the pixel shader as the API you’re using will render to the depth buffer for you.
Using the shadow map
Now that we have the shadow map rendered to our depth buffer, we can now use it to render our shadows to the screen. What we need to do now is once again convert our objects into light space but we need to do it in our normal vertex shader for our objects. Once we have our objects in light space, we need to convert it into texture space so we can use these coordinates to get our information from the shadow map. The next step is to head into the pixel shader and homogenize our new coordinates and sample our shadow map texture. What we now have is a bunch of texture coordinates in homogeneous space with the x and y being your coordinates and your z being the value to test against. From there all that needs to be done is determine if the value from the shadow map is less than the z component of the coordinates. If the shadow map is less than the z component then that means the object is in shadow, otherwise it is in light. Now that we have all of our information if we start rendering, we will see we finally have shadows! Hooray! But you might notice that the shadows look very pixelated, blocky, and very hard shadows, this is partially because of the resolution of our texture so there are some techniques we can use to improve the quality of these shadows which I will explain next time.
Gage Dietz
Top comments (0)