We can use either a floating-point texture or an integer texture.

We can use either a floating-point texture or an integer texture.

  • When we use floating-point textures, we write out the squared distance from the pixel to the light source, as in this pixel shader code:

             return dot(vLight, vLight)

    Why do we use squared distance? Because it's faster to compute—it's just a dot product, and no square root operation is necessary. We use squared distance when filling the shadow map, and we will use squared distance when accessing the shadow map in the base rendering pass. This saves pixel shader instructions twice. But using the squared distance can cause some precision problems, so we need to be careful when using it.

  • When we use integer textures, we need to pack the squared distance value and write it into the color channel. How can we pack a floating-point number into an integer texture? Here are two ways:
    1. Out.r = SquaredDistance * 2^0
      Out.g = SquaredDistance * 2^8
      Out.b = SquaredDistance * 2^16
      Out.a = SquaredDistance * 2^24
      
        float4 vPack = {1.0f, 256.0f, 65536.0, 16777216.0f};
        return vPack * dot(vLight, vLight);
    2. Out.r = floor(fDepth) / 256.0;
      Out.g = frac(fDepth);
      
        float fDepth = dot(vLight, vLight);
        return float(floor(fDepth) / 256.0, frac(fDepth),
                     frac(fDepth), frac(fDepth));

By writing frac(fDepth) into the green and alpha channels, we save this pixel shader instruction (otherwise, we need an additional instruction to fill these channels):

mov r2.gba, r0.g  // r0.g contains frac(fDepth)

Method 1 is computationally cheaper, but the second one gives you higher precision.

你可能感兴趣的:(Integer,float,shader,distance,textures)