Game Development Reference
float ComputeLOD( float2 vUV, float nMipLevels )
float2 vDx = ddx(vUV);
float2 vDy = ddy(vUV);
// Compute du and dv magnitude across quad
vDCoords = vDx * vDx;
vDCoords += vDy * vDy;
// Standard mip mapping uses max here
float fMaxTexCoordDelta = max(vDCoords.x, vDCoords.y);
if (fMaxTexCoordDelta == 0)
fMipLevelPower = nMipLevels - 1;
// 0.5 is for the square root
fMipLevelPower = 0.5 * log2(1.0 / fMaxTexCoordDelta);
float mipLevel = clamp(fMipLevelPower , 0, nMipLevels - 1);
return nMipLevels - 1 - mipLevel;
Listing 2.1. Texture LOD Selection. Allowing for nonsquare textures simply requires a
scale by aspect ratio on one of the directions.
width including borders is w , then the number of faces in a row is n =
Using i as the index within the block, we can compute the row as
column as i % n .
Each face has its own implicit UV parametrization. We adopt a convention
with respect to the order of the vertices in the quad. For example, we choose
the first index to be (0,0), the next is (1,0) and the last as (0,1). These can be
assigned in the hull-shader stage. The pixel shader will receive the interpolated
coordinate, which we call the “face UV.” We also need the primitive ID, which is
also defined in the hull-shader stage.
Tab l e 2 . 1 . If faces are sorted by resolution, and you have the prefix sum of face count
for each resolution bin, you can look up the resolution for any given face from the index
in the sorting. In this example, a face of index 7 would have a maximum resolution of
32 × 32 because it is greater than 5 and less than 10. If we want the index of that face
within that bin, it is 7 − 5=2.