How it works...

The findOffset function determines the texture coordinate to use when shading. We pass in the vector toward the viewer (we negate the direction to move away from the eye), and the function returns the texture coordinate. It also returns the value of the height at that location via the output parameter height. The first line determines the number of discrete height levels (nSteps). We pick a number between 10 and 60 by interpolating using the value of the z coordinate of the view vector. If the z coordinate is small, then the view vector is close to vertical with respect to the height levels. When the view vector is close to vertical, we can use fewer steps because the ray travels a shorter relative horizontal distance between levels. However, when the vector is closer to horizontal, we need more steps as the ray travels a larger horizontal distance when moving from one level to the next.  The deltaT variable is the amount that we move through texture space when moving from one height level to the next. This is the second term in the equation listed previously.  

The ray marching proceeds with the following loop. The ht variable tracks the height level. We start it at 1.0. The height variable will be the value of the height map at the current position. The tc variable will track our movement through texture space, initially at the texture coordinate of the fragment (TexCoord). We look up the value in the height map at tc, and then enter the loop.

The loop continues until the value in the height map (height) is less than the value of the discrete height level (ht). Within the loop, we change ht to move down one level and update the texture coordinate by deltaT. Note that we subtract deltaT because we are moving away from the viewer. Then, we look up the value of the height map (height) at the new texture coordinate and repeat.

When the loop terminates, tc should have the value of the offset texture coordinate, and height is the value in the height map at that location. We return tc, and the value of height at the end of the loop is also returned to the caller via the output parameter.

Note that this loop isn't correct when we are viewing the back side of the face. However, the loop will still terminate at some point because we always decrease ht and the height map texture is assumed to be between 0 and 1. If back faces are visible, we need to modify this to properly follow the ray or invert the normal.

The isOccluded function returns whether or not the light source is occluded by the height map at that point. It is quite similar to the findOffset function. We pass in height previously determined by findOffset, the corresponding texture coordinate (tc), and the direction toward the light source (s). Similar to findOffset, we march the ray in the direction of s, beginning at the height and texture coordinate provided. Note that we begin the loop with a value for ht that is slightly offset from the value of the bump map there (ht= height + htStep * 0.1).  This is to avoid the so-called shadow acne effect. If we don't offset it, we can sometimes get false positives when the ray collides with the surface that it starts on, producing speckled shadows.  

The rest of the function contains a loop that is quite similar to the loop in findOffset.  However, we move upward through the height levels, and we are careful to stop when the value of ht reaches or exceeds 1.0.  At the end of the loop, we don't need the values of height or tc; we only need to know whether or not the loop stopped due to the first of the two conditions.  If ht < 1.0, then we exit the loop before exceeding the range of the height map, indicating that we found a point along the ray that had a larger height.  Therefore, the point must be in shadow, so we return true. Otherwise, the light source is unoccluded, so we return false.

The blinnPhong function calls findOffset to determine the appropriate texture coordinates to use.  It then looks up the values in the normal map and color map at that location.  Next, it evaluates the Blinn-Phong reflection model using those values. However, it uses the isOccluded function to determine whether or not we should include diffuse and specular components. We also won't evaluate those components if the value of sDotN is less than or equal to zero, meaning that the light is behind (or tangent to) the face, as determined by the shading normal. 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.142.146