This technique demonstrates the use of a flow map with traditional scrolling normal map water. The purpose of the flow map is to perturb the water around objects (i.e. the flow map would be generated based on the position of objects in the water).
It is based on the technique Valve presented at Siggraph 2010. They use this technique in L4D and Portal, using the flow direction of the water to guide the player.
The flow map is sampled in the pixel shader and the result (coupled with a per-frame offset vector) is used to index the two normal maps. In order to prevent popping when the scrolling UV’s are reset; the technique is applied across a half cycle. The second normal map UV set is also offset by a half cycle. This means that when one normal map resets the other effectively covers for it.
To reduce the pulsing effect that occurs the flow map sample has some random noise applied from a noise filter.
The below example was created using DirectX 10:
A deferred shading framework that incorporates directional lights, point lights, shadow maps and SSAO. Traditional forward shading can be expensive, especially when applying multiple lights to the scene. This is because each lighting pass requires the geometry to be rendered; therefore the complexity of the scene is proportional to the cost of the lighting. Deferred shading decouples scene geometry from lighting etc using a G-Buffer. The G-Buffer is created by rendering the scene and outputting its components to different render targets. In my example the G-Buffer consists of 3 128-bit buffers. The first holds the linear depth in a single 128 bit channel (the world and view space position of the pixel can be reconstructed from this), the second holds the world-space normals of the object and the third hold the diffuse texture colour and the specular value of the object in the alpha channel. This is allows lighting to be calculated as a post process and therefore the maximum number of calculations is dependent on the number of pixels and not the scene complexity. This technique easily allows the inclusion of multiple lights by rendering each light-map as a fullscreen quad; then simply additively blend the results. All the maps (lighting, AO and shadows) are then combined with the diffuse colour to create the final scene.
Video demonstrating deferred shading with 60 dynamic lights:
Screen Space Ambient Occlusion
Simulates global illumination as a post process. Unlike other AO methods involving ray tracing; this method is performed solely in screen space using only two passes. The first pass renders the view space normals and linear depth to an RGBA texture. The second pass uses this information to calculate the occlusion factor of each pixel.
For each pixel a sample number of rays are set in view space. These rays are shot in random directions within the radius of a hemisphere centred round the view vector. By comparing the normals and depth of the sampled pixels with the current one we can work out how much the sample occludes the pixel.
My implementation uses a reflection vector between the sampled normal and a random normal, this eliminates certain artifacts. The AO pass is rendered to a smaller texture which is scaled up to make the shadows seem less defined. Finally the SSAO map is blurred to further soften the shadows.
Parallax Occlusion Mapping
This technique is an improved form of bump mapping that simulates 3D geometry in a 2D image. It does this by offsetting the texture co-ordinates based on the viewing position. A ray is cast from the camera to the current pixel. The height at that pixel is stored in the alpha channel of the normal map. This height is then used to determine how much the texture co-ordinates are offset for that pixel. These new texture co-ordinates are then used to sample the diffuse map; giving the illusion of 3D without all the added polygons!
The technique can be quite expensive, especially the method I have used to implement occlusion shadows; which requires 8 additional texture look-ups. The number of total look-ups depends on how much displacement is required and the number of iterations. The technique allows self occlusion using only linear intersection. The technique could be improved using binary search or cone stepping.