1In This Chapter
This chapter is a collection of short programming tips. You will read about:
snapping vertex coordinates to a grid to avoid anomalies when rendering very small triangles
avoiding redundant state changes
minimizing screen clears
controlling texture aliasing artifacts with an LOD bias
precision compression artifacts that can arise when z buffering
state coherency and contention between processes
Glide’s rasterization primitives, such as grDrawTriangle(), perform area calculations in order to determine parameter gradients, facedness, etc. A potential inconsistency may arise between Glide’s and the Voodoo Graphics hardware’s perception of area and vertex values when Glide’s floating point values change upon conversion to the hardware’s fixed point <12.4> representation. This typically only occurs with very small triangles, however, in certain cases this may cause the hardware to begin rendering outside of a triangle and in the wrong direction, leading to anomalies such as long horizontal stripes on the screen and very long rendering times.
To avoid this problem, software should “snap” vertices to .0625 resolution before passing them to Glide, but after they have been projected. On most processors, snapping can be performed by adding a large number (219) to the vertices then subtracting this same large number, which in effect normalizes the value to a known range and precision.
Example Programming Tips and Techniques.1 Snapping coordinates to .0625 resolution.
const float vertex_snapper = ( float ) ( 3L << 18 );
vertex.x += vertex_snapper;
vertex.x -= vertex_snapper;
vertex.y += vertex_snapper;
vertex.y -= vertex_snapper;
The only caveat is that an Intel FPU must be configured to operate in 24-bit precision so that temporaries are not immediately promoted to a higher precision internal to the FPU. This is accomplished by masking off the precision control bits in the floating point control world. The assembly code in Example Programming Tips and Techniques.2 performs this function.
Example Programming Tips and Techniques.2 Masking off precision control bits on Intel processors.
finit ; initialize the FPU
fwait ; wait for operation to complete
fstcw [memvar] ; store FPU control word to memvar
fwait ; wait for operation to complete
mov eax, [memvar] ; move memvar to a register
and eax, 0fffffcffh ; mask off precision bits to set to 24-bit precision
mov [memvar], eax ; save control word to memory
fldcw [memvar] ; load control word back to FPU
fwait ; wait for operation to complete
The same effect can be realized by multiplying by 16, casting to a long to truncate off trailing bits, then dividing by 16.0 to reconvert back to floating point, as shown in Example Programming Tips and Techniques.3. This is not an ideal solution, but it is portable and simple to implement. Note that this solution is very inefficient and should never be used in production code.
Example Programming Tips and Techniques.3 A portable way to snap coordinates to .0625 resolution.
Note that this solution is very inefficient and should never be used in production code.
long tmp;
tmp = vertex.x * 16; // increase by 4 bits, truncate off the rest
tmp = vertex.y * 16; // increase by 4 bits, truncate off the rest
vertex.x = tmp / 16.0; // remove extra 4 bits, convert back to float
vertex.y = tmp / 16.0; // remove extra 4 bits, convert back to float
Share with your friends: |