RacorX12RacorX12 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: ps.1.2 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, D3DPOOL_MANAGED,&m_pIllumMap))) 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. |