Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Use vertex shader.doc
252.93 Кб

BaseVs Vertex Shader Sample

With our simple DirectX 8 graphics framework sample that renders a quad in hand, it's now time to experiment with vertex shaders. Remember that we are using software vertex shaders and that AMD and Intel have provided highly tuned implementations. Indeed, you can consider software vertex shaders as the easiest way to get portable SIMD code. While it will be great to get hardware shader cards, significant prototyping work with vertex shaders can be done now, so don't let lack of hardware stop you from experimenting.

This sample, BaseVS, uses several vertex shaders in order to give an idea about both the syntax and power of vertex shaders, as well to familiarize you with the process of using shaders. This sample also needs to be located in the Direct3D folder in the SDK for all the path information to work. Figure 4 below shows the BaseVS project window.

Figure 4. BaseVS project

In the interests of time, I am not going to cover all the framework functions again, you can check the code out in the download. Please note the download contains a bitmap, dx8_logo.bmp, that needs to be copied to the DX SDK media directory for the sample to execute correctly. One interesting code detail is the ConfirmDevice method shown below. Here the device is rejected if it supports hardware or mixed vertex processing and does not support shaders in hardware. This allows us to run on a hardware TnL device (with software vertex processing) like the geForce2, as well as on a shader card with hardware vertex processing.

You will note that vertex shaders in software still perform quite well. This is because AMD and Intel tuned the software pipelines for their respective processors. Indeed software vertex shaders can be considered the easiest way to get portable SIMD code. Still, once shader cards are available most serious developers wont be able to live without them.


// Name: ConfirmDevice()

// Desc: Called during device intialization, this code checks the device

// for some minimum set of capabilities


HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,

D3DFORMAT Format )





if( pCaps->VertexShaderVersion < D3DVS_VERSION(1,0) )

return E_FAIL;


return S_OK;


Let’s now focus on vertex shaders. There are several pieces to master when working with vertex shaders:

  • API Usage

  • Vertex Definitions

  • Shader Declarations

  • Shader Definition

Api Usage

Last column we briefly covered the new API methods for working with shaders, and they included:

  • D3DXAssembleShader

  • IDirect3DDevice8::CreateVertexShader

  • IDirect3DDevice8::SetVertexShaderConstant

  • IDirect3DDevice8::SetStreamSource

  • IDirect3DDevice8::SetVertexShader

  • IDirect3DDevice8::DeleteVertexShader

D3DXAssembleShader and IDirect3DDevice8::CreateVertexShader are used to generate the runtime representation of the shader and return a shader handle to that representation. The code snippet below shows usage, assumingSimpleVertexShader0has a shader definition anddwDecl0has a shader declaration (more on those in a bit):

ID3DXBuffer* pshader0;

ID3DXBuffer* perrors;

// Assemble the shader

rc = D3DXAssembleShader( SimpleVertexShader0 ,

sizeof(SimpleVertexShader0)-1, 0 , NULL ,

&pshader0 , perrors );

// Create the vertex shader handle

rc = m_pd3dDevice->CreateVertexShader( dwDecl0,


&m_hVertexShader0, 0 );

IDirect3DDevice8::SetVertexShaderConstant is used to load constant definitions used by a shader. IDirect3DDevice8::SetStreamSourceinforms the runtime as to the source of vertex components, that is, what vertex buffer contains the vertex components and what size or stride of data the shader expects.IDirect3DDevice8::SetVertexShadertakes the shader handle created byIDirect3DDevice8::CreateVertexShader and makes that the current vertex shader on the device. The code snippets below use these methods:

//set shader constants

float color[4] = {0,1,0,0};

m_pd3dDevice->SetVertexShaderConstant( 8 , color , 1 );

//set shader stream

m_pd3dDevice->SetStreamSource( 0, m_pVBVertexShader0,


//set shader handle

m_pd3dDevice->SetVertexShader( m_hVertexShader0 );

Note an alternate usage for IDirect3DDevice8::SetVertexShadertakes an FVF code to enable a fixed-function vertex shader using stream 0 only, as shown below:

//set the FVF vertex shader

m_pd3dDevice->SetVertexShader( D3DFVF_VERTEXSHADER0VERTEX );

Finally, IDirect3DDevice8::DeleteVertexShader is used to remove a vertex shader from a device; it's important to do this to leave a device "clean" without dangling assets. The code snippet below shows how to invoke this method:

//delete shader from device

m_pd3dDevice->DeleteVertexShader( m_hVertexShader0 );

With those APIs in hand, you can examine the BuildVertexShadersandDestroyVertexShadersfunctions that are invoked inRestoreDeviceObjectsandInvalidateDeviceObjectsto handle the mechanics of creating and destroying shaders. Now we are ready to dive into the shader details.