Microsoft DirectX 8.0 (C++)

Sending Data Through the Pixel Shader Virtual Machine

The address used for the texture operation for stage 0 is the bump map addresses presented through the first texture coordinate register (t0). The operation is a simple look-up of the bump data, as illustrated by the following pixel shader code.

tex t0

The texture operation for stage 1 is more complicated. In this case, you must set the texture stage state so that the 2×2 matrix is loaded. Note that there is a 2×2 matrix that can be loaded to simulate the change between the eye-point and the light source. This enables the bump and environment map to be reused as the eye-point is moved around a scene. Therefore, the address into the environment map is a base address, presented through the second texture coordinate, t1, modulated by the eye-point adjustment and local bump value. More precisely, the u coordinate into the environment map is u = t1.r + mat00 * t0.r + mat01 * t0.g, and the v coordinate into the environment map is v = t1.g + mat10 * t0.r + mat11 * t0.g. The values in the t0.r and t0.g register components are actually the du and dv values that represent the bump data looked-up in stage 0 and stored in register t0.

Note  The u and v address calculations can require two slots in the actual pixel shader code. This is because most hardware reuses the logic for the u and then the v address calculation. Current hardware does not provide for the addresses to be computed in parallel.

The following example shows how this is done in pixel shader code.

ps.1.0         // DirectX8 Version.
tex t0         // Declare the texture (the bump data).
texbem t1, t0  // Declare the environment map and get data from t0.
mov r0, v0     // Note the assumption that the diffuse orange color 
               // is fed into the pixel shader through register v0 for 
               // each pixel.
add r0, r0, t1 // Add the specular environment data.

However, this simple example is not the most common case. Typically, there is a base texture applied to the object before performing the bump environment mapping. For example, you might send a white sphere that is used as a base for applying the texture data. This is the diffuse light that is brighter on part of the surface and less bright on other parts. In this case, you move the bump environment mapping operations out a stage and modulate the base texture by the diffuse light. The following example shows how this is done in pixel shader code.

ps.1.0         // DirectX8 Version.
tex t0         // Declare the base texture. It could be something 
               // like marble or wood or any other surface material.
tex t1         // Declare the texture (the bump data).
texbem t2, t1  // Declare the environment map.
mul r0, v0, t0 // Modulate the base texture by the diffuse light.
add r0, r0, t2 // Add the specular environment data.

You can use traditional texture mapping (one stage), interpolate the specular, and have it available through register v1 of the pixel shader virtual machine. Other complex pixel shaders can be constructed using a set of fixed constants stored in the constant registers (c0-c7). Also, the texture registers are often used with texture stages but are read/write to the pixel arithmetic logic unit (ALU). Thus the pixel shader can use a texture register as a temporary register. Note also that r0 and r1 are read/write to the ALU, but the results stored in r0 are the only results that are sent to the depth and stencil logic. In fact, the only way that results can be passed downstream is through the r0 register.