?/TD> |
Microsoft DirectX 9.0 |
This example uses a pixel shader to apply a Gouraud interpolated diffuse color to a geometric plane. The example will show the contents of the shader file as well as the code required in the application.
To create a pixel shader
If you already know how to build and run Microsoft?Direct3D?samples, you should be able to cut and paste code from this example into your existing application.
To check for pixel shader support, use the following code. This example checks for pixel shader version 1_1.
D3DCAPS9 caps; m_pd3dDevice->GetDeviceCaps(&caps); // init m_pd3dDevice before using if( caps.PixelShaderVersion < D3DPS_VERSION(1,1) ) return E_FAIL;
The caps structure returns the functional capabilities of the pipeline. Use the D3DPS_VERSION macro to test for all supported shader versions. If the version returned by caps is less than 1_1, this call will fail. Conversely, all version numbers greater than or equal to 1_1 will succeed. If the pipeline does not support the shader version that is tested, the application will have to fall back to another rendering approach (perhaps a lower shader version is available).
This example uses a plane, which is made up of two triangles. The data structure for each vertex will contain position and diffuse color data. The D3DFVF_CUSTOMVERTEX macro defines a data structure to match the vertex data. The actual vertex data is declared in a global array of vertices called g_Vertices. The four vertices are centered about the origin, and each vertex is given a different diffuse color.
// Declare vertex data structure. struct CUSTOMVERTEX { FLOAT x, y, z; DWORD diffuseColor; }; // Declare custom FVF macro. #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE) // Declare the vertex position and diffuse color data. CUSTOMVERTEX g_Vertices[]= { // x y z diffuse color { -1.0f, -1.0f, 0.0f, 0xffff0000 }, // red - lower left { +1.0f, -1.0f, 0.0f, 0xff00ff00 }, // green - lower right { +1.0f, +1.0f, 0.0f, 0xff0000ff }, // blue - upper right { -1.0f, +1.0f, 0.0f, 0xffffffff }, // white - upper left };
This shader moves the Gouraud interpolated diffuse color data to the output pixels. The shader file PixelShader.txt follows:
ps_1_1 // version instruction mov r0,v0 // Move the diffuse vertex color to the output register.
The first instruction in a pixel shader file declares the pixel shader version, which is 1_1.
The second instruction moves the contents of the color register (v0) into the output register (r0). The color register contains the vertex diffuse color because the vertex data is declared to contain the interpolated diffuse color in step 1. The output register determines the pixel color used by the render target (because there is no additional processing, such as fog, in this case).
The pixel shader is created from the pixel shader instructions. In this example, the instructions are contained in a separate file. The instructions could also be used in a text string.
LPD3DXBUFFER pCode; // buffer with the assembled shader code LPD3DXBUFFER pErrorMsgs; // buffer with error messages TCHAR strPixelShaderPath[512];// used to locate the shader file DXUtil_FindMediaFileCb( strPixelShaderPath, sizeof(strPixelShaderPath), _T("PixelShader.txt") );
This function is a helper function used by the sample framework, which is the foundation on which many of the samples are built.
LPDIRECT3DPIXELSHADER9 m_pPixelShader; D3DXAssembleShaderFromFile( strPixelShaderPath, NULL, NULL, 0, &pCode, &pErrorMsgs, NULL ); m_pd3dDevice->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(), &m_pPixelShader );
When the shader is created, the pointer m_pPixelShader is used to refer to it.
Rendering the output pixels is very similar to using the fixed function pipeline sequence of calls except that the pixel shader handle is now used to set the shader.
// Turn lighting off for this example. It will not contribute to the // final pixel color. // Pixel color will be determined solely by interpolating the vertex colors. m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); m_pd3dDevice->SetStreamSource( 0, m_pQuadVB, sizeof(CUSTOMVERTEX) ); m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); m_pd3dDevice->SetPixelShader( m_pPixelShader ); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
The source of the vertex data is set with SetStreamSource. In this example, SetFVF uses the flexible vertex format (FVF) macro used during the vertex data declaration to tell Direct3D to do fixed function vertex processing. Vertex shaders and pixel shaders may be used together or separately. The fixed function pipeline can also be used instead of either pixel or vertex shaders. SetPixelShader sets the pixel shader and DrawPrimitive draws the plane.