The goal of this project was to create an engine in DirectX 11 that would implement and utilise several advanced graphics techniques used in the industry. Such techniques include:
• Bump/Normal Mapping
• Parallax & Parallax Occlusion Mapping
• Simple Screen-Space Effects such as a color tint, blur and depth of field
• Screen Space Ambient Occlusion (SSAO)
• Shadow Mapping
• Deferred Rendering
• Cel Shading
• Physically Based Rendering
Bump Mapping is a technique used on 2D polygon faces to simulate how light would reflect and refract when hitting a 3D object without the additional geometry cost. This can be acheived by supplying the appropiate Pixel Shader with a bump/normal map where each pixel's RGB value represents a normal vector.
Figure 1 - Bump Mapping on a stack of crates.
Parallax Occlusion Mapping
Much like Bump/Normal Mapping, Parallax Occlusion Mapping strives to achieve the look of a 3D object without the geometry cost by applying another map. This new map holds information regarding the depth of the pixel. A ray-trace is then done between the eye vector and the heightmap to determine what the texture offset should be, tricking the user into thinking the object is 3D. The same ray-tracing technique can be used between the offset texture position and the light vector to test if the pixel is occluded by a "higher" pixel for shadowing.
Figure 2 - Parallax Occlusion Mapping on a stack of crates.
Screen-Space Ambient Occlusion (SSAO)
Ambient light is defined as the combined effect of multiple light sources reflecting off multiple objects to contribute to the overall illumination of a scene. It is possible to ray-cast each individual ray of light at significant computational cost (Too much for a real-time application). Instead, Screen-Space Ambient Occlusion is used to check for nearby polygons and, if close, subtract from an ambient accessability value that determines the average ambient light that should reach that pixel.
Multiple shader passes are required to achieve this effect, therefore all but the last shader pass are rendered to a texture rather than the back-buffer. The first pass generates the normal and depth information for the scene [Figure 3]. Then, for the second pass, random vectors are generated from each pixel and test for nearby objects that could potentially occlude it to generate the SSAO map [Figure 4]. This SSAO map is the subjected to a vertical and horizontal blur as the SSAO effect alone creates a grainy image [Figure 5].
Figure 3 - Normal & Depth Map for SSAO (RGB (normal) values on the left, W (depth) values on the right).
Figure 4 - SSAO Map for a scene.
Figure 5 - Blurred SSAO Map for a scene.
Figure 6 - SSAO being enabled and disabled on a scene.
Shadow Mapping is a commonly used technique used to create shadows in the sections of the map that would be naturally occluded. To do this, a shadow map is generated by rendering the scene from the perspective of the light onto a depth stencil view (not a render target) [Figure 7]. This shadow/depth map is then passed to the second shader pass from the camera's perspective and projected into world space. The depth values of both the shadow and second pass scene are evaluated to determine if the pixel is occluded, drawing a shadow if it is [Figure 8].
Figure 7 - Depth Map from the Light's Perspective (Zoomed in).
Figure 8 - Scene with the projected shadow/depth map applied.
Simple Screen-Space Effects
These are just a few simple examples of a scene rendered to a texture and then passing through a blur or color filter on the second pass.
Figure 9 - Gaussian Blur
Figure 10 - Color Tint
Figure 11- Greyscale
Figure 12 - Sepia
Depth of Field
Using the Gaussian Blur effect shown previously, it was possible to implement a Depth of Field technique by altering the blur amounts dependent on a user-controlled depth [Figure 13].
Figure 13 - Depth of Field using Gaussian Blur
Another screen space effect that was implemented was to increase the intensity of very light objects to create a bloom effect. This is done by extracting all of the pixels that have a light RGB value against a "bloom threshold", which determines how light that pixel should be, to create a glow map [Figure 14]. This glow map is then blurred to create the effect of bright spots being difficult to focus on, as happens with the human eye when looking at bright objects [Figure 15]. This glow map is then applied on the final shader pass with the scene map to create the final effect [Figure 16].
Figure 14 - Glow Map
Figure 15 - Blurred Glow Map
Figure 16 - Bloom Effect
A cel shading effect was implemented that used the previous scene shader pass and normal/depth shader passes described above on this page. The last shader pass used the normals and depth values of neighbouring pixels to test if there was enough difference to be considered an edge of an object [Figure 17].