|
Streamlining the calculationsHowever, the processing overhead can be greatly reduced with a bit of consideration. The first thing that we can do is cutout two thirds of the operations right off the bat. While complex surfaces would usually employ splines that interpolate vertex coordinates as the parameter, since we are using a uniform grid the X and Z of each control point will be implicit. Our splines will only need to control a 1-D parameter, the altitude. To further optimize the calculation, we will look at ways that we can pre-calculate as much as possible. If we look back on Equation 1, you will see that the spline calculation contains a scalar constant as well as a constant basis matrix. By pre-multiplying these by the control points to form a 4D vector, the calculation for a a point on a spline segment can be reduced to a single dot product operation: q(t) = (1,t,t2,t3) • (P2,
(P3-P1)/2, (2P1-5P2+4P3-P4)/2,
(-P1+3P2-3P3+P4)/2) Since we will be calculating multiple values from each spline segment, we can pre-calculate the second term of this equation as a 4D vector for each segment, using a function like this:
When calculating a point in a patch, we have to perform this operation with four parallel spline segments. To bundle these operations together, we can place the four 4D vectors that will be used for each spline calculation into a 4x4 matrix:
Finally, we post-multiply the results by the basis matrix, to eliminate having to perform an additional transformation on the results:
At this point, we have a matrix that we can use to calculate the height at any point in a quad, by first using it to transform the vector (1,x,x2,x3), then performing a dot product of the result with (1,z,z2,z3):
Using Vertex Shaders to Render PatchesWhen handling very large landscapes, the size of the mesh involved often precludes loading of the entire mesh at one time. Instead, a local region is maintained, and as the viewer moves new sections are created for the region the viewer is approaching, while old sections are discarded as the viewer moves away from them. This can consume a considerable amount of bandwidth, and also means that the vertex buffers involved must be updated in video memory if hardware vertex processing is used. Vertex shaders, as we will see, can provide an interesting alternative. By moving the calculations into the shader, we can strip our vertex format down to a point that allows reuse of vertex buffers to render all of the landscape quads using the a single vertex buffer containing the vertices necessary to render a single quad, without ever changing the vertices in the buffer! Note that the implementation we will provide here uses a fixed LOD (Level of Detail), meaning that all quad patches are rendered using the same level of subdivision. Variable LOD is possible, we will discuss that in the Potential Improvements section later on. Storage of Common Quad DataTo facilitate such reuse of vertices, the vertex format will contain only x and z coordinates, relative to the quad and normalized in the range of 0.0 to 1.0. These will be stored in a pair of 4D vectors, containing (1,x,x2,x3) and (1,z,z2,z3), providing pre-calculated powers of the coordinates. The vertex format is shown below:
For our fixed LOD application, we will generate a single vertex buffer and corresponding index buffer, forming a regular grid of a specified resolution, with vertices ranging from (0,0) to (1,1):
Downloadable demo for this article |
Visitors Since 1/1/2000:
|