Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
82 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:


RacorX12 has only a minor improvement over RacorX11. It uses the ps.1.2 pixel shader instruction texdp3tex.

Alload (Arnaud Floesser) sent me an e-mail, in which he pointed me to the idea to use this instruction together with a 2048x1 texture for specular lighting.

This way, we can reduce the number of passes to two. The diffCubeMap.psh and the Specular.psh pairs of RacorX11 are combined into Specular.psh:

tex t0 ; color map + gloss map
tex t1 ; normal map
tex t2 ; cube map
texdp3tex t3, t1_bx2 ; t3.a = (N dot H)^16
dp3 r0, t2_bx2, t1_bx2 ; diffuse
mul r1.rgb, t0, r0 ; diffuse * color
+mul r1.a, t0.a, t3.a ; (N dot H)^16 * gloss value
add r0, r1, r1.a

texdp3tex performs a three-component dot product between the texture coordinate set corresponding to the destination register number and the texture data in the source register. The result of this operation is used to do a 1D texture lookup into the texture in the destination register. The result of the lookup is stored in the destination register.

The 1D texture used for this instruction is build up with the D3DXFillTexture() function provided by the Direct3D utility library:

if (FAILED(D3DXCreateTexture(m_pd3dDevice, 2048, 1, 0, 0, D3DFMT_A8R8G8B8, 
   return S_FALSE;

FLOAT fPower = 16;
if (FAILED(D3DXFillTexture(m_pIllumMap, LightEval, &fPower)))
   return S_FALSE;

The main reason for this function is to get a simple interface to create procedural textures, that can be used in the pixel shader. The callback function in the second parameter is a user-written function:

void LightEval(D3DXVECTOR4 *col,D3DXVECTOR2 *input,
               D3DXVECTOR2 *sampSize, void *pfPower)
   float fPower = (float) pow(input->x,*((float*)pfPower));
   col->x = 0;
   col->y = 0;
   col->z = 0;
   col->w = fPower;

The size of the texture produced by this piece of code is 2048x1 (maximum width of a texture on a RADEON 8x00). The callback function gets called for every texel, at every mip level. Though it doesn't give you the dimensions of the current surface its working on, you can deduce these by looking at the texel size vector - which is basically 1/dimx, 1/dimy, etc. The coordinate used in the first parameter of LightEval(), is in the center of the texel.

The result is converted by D3DX to whatever format your texture is, since internally this function deals with everything as 32-bit floats, there shouldn't be any precision lose.



  Printable version
  Discuss this article

The Series
  Fundamentals of Vertex Shaders
  Programming Vertex Shaders
  Fundamentals of Pixel Shaders
  Programming Pixel Shaders
  Diffuse & Specular Lighting with Pixel Shaders