Game Development Reference
damaged areas, but due to how floating-point numbers work, we are limited to
24 damaged areas per single-precision floating-point variable. 1
One might note that this effectively limits us to 32 or 24 damaged areas at
most (depending on whether we use integer or floating-point mathematics). But,
in fact, it is still possible to support more bits at a fixed cost by utilizing more
than one variable to store the bit field. The only reason we have limited ourselves
to a single variable for the bit field so far is for ease of explanation and that it is
expected that not many objects exceed that number of damage areas. Thus, the
general case we are going to show next.
Expanding the bit field into a bit array. To support an unrestricted number of
damage areas, we have to modify the above method slightly. First, the bit field
is now turned into a bit array on the CPU side. At render time, the bit array
must be converted into an array of floating-point vectors of enough size to hold all
bits in the array in the same way we did in the single variable case. Next, in the
shader, based on the damage ID, we calculate the array index of the floating-point
variable that holds the bit value. That variable is then passed to checkBit() and
everything else remains unchanged. Listing 3.3 adds this operation to the same
sample code in Listing 3.2.
Rendering replacement damage geometry. Now that we have managed to hide poly-
gons of a damaged area in an effective manner, all that remains is to fill the gaps
with replacement geometry that depicts the damage shapes.
There are a few
ways to do this, each having its pros and cons:
1. Rendering damage geometry in the same draw call as the main object:
The benefit of this way is that no additional draw calls are ever needed
for the damaged object. The disadvantage is that if the damage geometry
is dense then rendering power may be wasted on processing vertices that
remain hidden for quite some time (depending on gameplay circumstances).
On some platforms this might be OK, as vertex processing power is often
underused. However, this is not always the case (e.g., the Playstation 3
RSX is relatively slow in vertex processing).
To implement this method, the damage-geometry vertices must be identified
uniquely from the main-object vertices. This can be represented by one
single bit in the vertex attributes (e.g., the sign of UV coordinate x ). Then,
depending on whether the vertex belongs to the main object or not, the
condition for collapsing the vertex based on its damage ID is reversed.
1 You can safely represent integer numbers in a 32-bit floating-point variable to a value up
to 16,777,215 (0xFFFFFF) that is 24-bits wide. Higher numbers can still be represented, but
discontinuities occur (e.g., 16,777,217 cannot be represented), thus going to such limits is not