Sử dụng VertexShader và PixelShader trong chương trình

Một phần của tài liệu nghiên cứu và xây dựng thử nghiệm 3G Engine (Trang 36 - 39)

Ở các phần trước chúng ta chỉ mới tìm hiểu cách thức hoạt động và cấu trúc của 1 chương trình Vertex Shader và Pixel Shader. Nhưng Vertex Shader và Pixel Shader không phải là 1 chương trình độc lập để có thể chạy 1 cách riêng lẽ như các chương trình Window khác. Vertex Shader và Pixel Shader chỉ là các đoạn mã máy chạy trên GPU được Direct3D điều khiển trong chương trình chính. Trong phần này chúng ta sẽ xem qua 1 ví dụ cụ thể để có thể ứng dụng Vertex Shader vào trong chương trình.

Muốn dùng Vertex Shader trước tiên ta cần tạo một dự án mới có sử dụng Direct3D. Sau đó tiến hành các bước sau đây:

Công đoạn khởi tạo bao gồm:

Khởi tạo môi trường 3D và khởi tạo các trạng thái dựng hình mặc định (Render State), tạo mới giao diện IDirect3DDevice9.

Thíết kế và lập trình Vertex Shader, biên dịch Vertex Shader thành mã máy. // Design a vertex shader

const char* strAsmVertexShader =

"vs_1_1 // version instruction\n"

"dcl_position v0 // define position data in register v0\n" "m4x4 oPos, v0, c0 // transform vertices by view/proj matrix\n" ";\n"

"";

// Assemble shader

LPD3DXBUFFER pShader = NULL; D3DXAssembleShader(

strAsmVertexShader,

(UINT)strlen(strAsmVertexShader),

NULL, // A NULL terminated array of D3DXMACROs NULL, // #include handler

D3DXSHADER_DEBUG, &pShader,

NULL // error messages );

Tạo mới giao diện IDirect3DVertexShader9 bằng phương thức

IDirect3DDevice9::CreateVertexShader.

LPDIRECT3DVERTEXSHADER9 m_pAsm_VS; // Create the vertex shader

g_pd3dDevice->CreateVertexShader(

(DWORD*)pShader->GetBufferPointer(), &m_pAsm_VS );

Tạo mới giao diện IDirect3DVertexDeclaration9 bằng phương thức

IDirect3DDevice9::CreateVertexDeclaration. D3DVERTEXELEMENT9 decl[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },D3DDECL_END() };

// Create the vertex declaration

g_pd3dDevice->CreateVertexDeclaration( decl, &m_pVertexDeclaration ); Tạo mới giao diện IDirect3DVertexBuffer9 bằng phương thức

IDirect3DDevice9::CreateVertexBuffer và đổ dữ liệu vertex vào trong buffer, dữ liệu này sau đó sẽđược vẽ ra màn hình bằng Vertex Shader.

// A structure for our custom vertex type struct CUSTOMVERTEX

{

FLOAT x, y, z; // The transformed position for the vertex };

// Initialize three vertices for rendering a triangle CUSTOMVERTEX vertices[] = { {-1, -1, 0}, // lower left { 0, 1, 0}, // top { 1, -1, 0}, // lower right }; LPDIRECT3DVERTEXBUFFER9 m_pVB = 0;

// Create the vertex buffer. Here we are allocating enough memory // (from the default pool) to hold three custom vertices (adsbygoogle = window.adsbygoogle || []).push({});

g_pd3dDevice->CreateVertexBuffer(

3*sizeof(CUSTOMVERTEX), 0, 0, D3DPOOL_DEFAULT, &m_pVB, NULL ); // Now we fill the vertex buffer. To do this, we need to Lock() the // vertex buffer to gain access to the vertices

VOID* pVertices;

m_pVB->Lock( 0, sizeof(vertices), (VOID**)&pVertices, 0 ); memcpy( pVertices, vertices, sizeof(vertices) );

Sau công đoạn khởi tạo ta đã có đủ các giao diện sử dụng cần thiết. Trong hàm render ta cần tiến hành các bước sau:

Thiết lập các hằng cần thiết dùng trong Vertex Shader vào trong các thanh ghi hằng (constant registers) bằng các phương thức:

IDirect3DDevice9::SetVertexShaderConstantF, IDirect3DDevice9::SetVertexShaderConstantI, IDirect3DDevice9::SetVertexShaderConstantB

// Calculate World * View * Projection matrix D3DXMATRIX compMat;

D3DXMatrixMultiply(&compMat, &m_matWorld, &m_matView); D3DXMatrixMultiply(&compMat, &compMat, &m_matProj); // Transpose the matrix

D3DXMatrixTranspose( &compMat, &compMat ); // Set constant

g_pd3dDevice->SetVertexShaderConstantF( 0, (float*)&compMat, 4 );

Sử dụng IDirect3DVertexDeclaration9 (đã tạo trước đó) bằng phương thức

IDirect3DDevice9::SetVertexDeclaration

g_pd3dDevice->SetVertexDeclaration( m_pVertexDeclaration);

Sử dụng IDirect3DVertexShader9 (đã tạo trước đó) bằng phương thức

IDirect3DDevice9::SetVertexShader

g_pd3dDevice->SetVertexShader(m_pAsm_VS);

Vẽ dữ liệu vertex trong IDirect3DVertexBuffer9 ra màn hình

g_pd3dDevice->SetStreamSource(0, m_pVB, 0, sizeof(CUSTOMVERTEX)); g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);

Trả quyền điều khiển về cho Fixed Function để thực hiện vẽ các đối tượng khác bằng phương thức IDirect3DDevice9::SetVertexShader.

g_pd3dDevice->SetVertexShader(NULL); Kết quả của chương trình

Ý nghĩa cũng như tham số của các phương thức minh họa ở trên có thể xem trong Direct3D SDK. Ví dụ trên đây chỉ minh họa 1 chương trình Vertex Shader rất đơn giản, nhưng thực tế chương trình Vertex Shader phức tạp hơn rất nhiều, lúc đó việc lập trình bằng hợp ngữ trở nên cực kỳ khó khăn nhưng mọi việc đã được giải quyết từ khi HLSL (High-Level Shader Language) ra đời.

Một phần của tài liệu nghiên cứu và xây dựng thử nghiệm 3G Engine (Trang 36 - 39)