Shadow Maps, Particles and Animations
This is a retrospective post on the work done on Salvager from the 28th of September to the 5th of October. There were a lot of tasks that were in progress during this week due to tasks spilling over from the sprint right before this one, but the biggest priority was in implementing Shadow maps for Lights, an Effects System and refining the current Animation system. For this post, we'll discuss Shadow maps and some of the issues I faced in quickly implementing this feature into the game.
Shadow maps are a traditional way to emulate Shadows in Video Game rendering where you draw the world from the Light's point of view, marking what areas of the world are being directly lit by it and what areas are being obscured from it. I'd previously implemented Shadows in another Rendering project I'd done and was confident that I'd be able to implement some form of it in the Game without too many issues. But the devil's in the details as they say and some of the decisions I'd made with how my Rendering Pipeline worked became surprising obstacles during the implementation.
I'd been using a Deferred Rendering Pipeline with a G-Buffer that stores the Depth from the Camera, the World Normal, the Diffuse Color and some Material Properties like Metallic and Roughness. These components were sufficient for my Lighting calculations so far and with some tricks like Octohedral mapping, I'd been able to compress these to 3 Render Targets to keep the memory bandwidth costs low, a key limiting factor with Deferred pipelines. But now that I needed to sample from shadow maps, I needed some extra information about the Position and Orientation of the Light in the world and the actual World Position of the Pixel being shaded. Another challenge was implementing Shadow maps for Point Lights which needed to draw shadow map information for all directions around the Light. I also wanted to use a Shadow Map Atlas to keep the GPU memory footprint down at this point which meant the simple solution of having a cube map resource per Point Light would be too wasteful to use.
In the end, I found some very interesting solutions by researching about this online. I was able to use the depth value already present in the G-Buffer to reconstruct the World Position of the Pixel, a technique that was detailed in a wonderful blog post (https://mynameismjp.wordpress.com/2010/09/05/position-from-depth-3/). This helped me avoid adding in an extra Render Target just for Pixel Positions. I also came across the idea to use some custom sampling code to read from an atlas as if it were six faces of a cube map resource placed adjacently which meant that I'd be able to keep a fixed ceiling on the Shadow map memory cost for Point Lights as well. The one issue that remained was sampling from Shadow Maps during shading which was a pain point because I'd only been storing Light positions to handle culling and shading so far but the convert a Pixel Position to Light space to find it on a Shadow Map, I'd need the full transform of the light. This wasn't a hugely complicated problem but due to time constraints and other priorities I ended up not being able to work on it and finish it. Currently we render some shadow maps in the background but we don't use them in our lighting calculations in the Game.
Salvager
Sci-Fi Action RPG
Status | Prototype |
Author | threewastaken |
Genre | Action |
More posts
- Mixamo Mesh Bone WeightsOct 22, 2023
- Particle Systems and Burn outOct 22, 2023
- Splash Screens: aka Don't mix your Drawing APIsOct 21, 2023
- Scaling to every Circumstance: UI LayoutsSep 09, 2023
- Separating the Game from the EngineSep 02, 2023
- Catching Up: Refactors and UI ScreensAug 12, 2023
- Slow and Steady Systems BuildsJul 18, 2023
- Setup for SuccessJul 08, 2023