当前位置:   article > 正文

【Directx3D游戏开发】——简单渲染_d3d中fx的渲染

d3d中fx的渲染

            这是个令人十分激动的时刻,用Directx3D去渲染出一些形状,还有会动的形状。感觉就跟中了彩票一样的心情。

           好了,以上都是废话。在上一次的文章中学会了如何初始化Directx3D环境,now!开始真正的干事情了,首先要渲染一个三维三角形。在前面的代码的基础上其实添加小量代码就可以实现渲染了,不过还是要了解几个东西。

           1.可变定点格式FVF(Flexible Vertex Format),Directx3D用这种方法来定义顶点结构,以满足各种不同情况的需求。用户可以根据自己程序的不同需要来定义相应的顶点对象,忽略某些对象,这样实现了在渲染模型是节省内存和最小化流水线宽度的目的。在此并不打算详细的说明FVF,因为其实我也不懂。。。简单来说FVF是Directx3D提供给用户灵活的定义自己的顶点结构的方式,你的顶点结构可以很复杂也可以很简单,只有x, y, z三个坐标,这完全看你的需要。在此我们要渲染一个彩色的三角形,所以我们为我们的顶点结构添加了除坐标之外的一个属性color。

  1. struct CUSTOMVERTEX
  2. {
  3. FLOAT x, y, z, rhw;
  4. DWORD color;
  5. };

除此之外还需要一个描述这个顶点结构的常量FVF,这个常量可以是以下常量或它们的一些组合

  • D3DFVF_DIFFUSE:表示有漫反射颜色对象
  • D3DFVF_NORMAL:表示有顶点法线对象,不可和D3DFVF_XYZRHW同时使用
  • D3DFVF_SPECULAR:表示有镜面反射颜色对象
  • D3DFVF_XYZ:表示未转换顶点坐标,不可和D3DFVF_XYZRHW同时使用
  • D3DFVF_XYZRHW:表示转换过的顶点坐标,不可和D3DFVF_XYZ 及 D3DFVF_NORMAL同时使用
  • D3DFVF_XYZB1 到 D3DFVF_XYZB5:表示顶点混合权重数据,数值后缀为几就用几
  • D3DFVF_TEX0 到 D3DFVF_TEX8:表示纹理映射,几重映射后缀就是几
只是列出了FVF可能的取值,但对于具体什么时候该用什么还是很模糊。

                2.顶点缓冲区:Directx3D中的每个模型都是由三角形组成,每个三角形都是由三个顶点决定(不是废话,是什么?),为了更好地去渲染这些模型,需要把这些顶点放到Direct3D可以识别和读取的地方,这就是顶点缓冲区。
                3.索引缓冲区:在一个物体模型中,组成他们的三角形的顶点被多个面共用着,(如一个正方体它的每个顶点都是由三个面共用),如一个正方体有12个三角形,那顶点缓冲区里面就有36个点。也就是说顶点缓冲区里面其实有大量的重复数据,直接对其进行渲染必然导致效率下降。这时候就引入了索引缓冲区,它定义了一种缓冲区对顶点缓冲区提供索引,给定了顶点缓冲区里面顶点的组织方式,这样顶点缓冲区就没必要存放重复的点,既减少了内存,也提高了渲染时的效率。

                顶点缓冲区的创建:
  1. HRESULT IDirect3Ddevice9::CreateVetexBuffer(
  2. UINT Length, //分配给缓冲区的字节数
  3. DWORD Usage, //标识缓冲区将会被怎样使用,设为0,标识没有附加属性
  4. DWORD FVF, //缓冲区存储的顶点的可变顶点格式FVF
  5. D3DPOOL pool, //缓冲区的内存池类型
  6. IDirect3DVertexBuffer9** ppVertexBuffer, //返回被创建的顶点缓冲区指针
  7. HANDLE* pShareHandle //暂时未使用,扩展部分,设为0
  8. );
              在创建顶点缓冲区后,需要用我们预先定义好的顶点数据去填充这个缓冲区,由于缓冲区有可能在显存或系统内存中,首先调用Lock()方法锁定获取缓冲区的首地址:
  1. HRESULT IDirect3DVertexBuffer9::Lock(
  2. UNIT offsetToLock, //以字节计算的偏移地址,从缓冲区首部开始偏移地质处开始锁定
  3. UNIT sizeToLock, //锁定的字节数
  4. BYTE** ppData, //返回被锁定的缓冲区区域的头指针
  5. DWORD Flags, //描述缓冲区锁定方式的标识
  6. );

      最后还要调用Unlock()解除锁定。
      索引缓冲区的创建:和定点缓冲区类似
  1. HRESULT IDirect3DDevice9::CreateIndexBuffer(
  2. //参数含义基本和CreateVertexBuffer一样,只有Format不同
  3. UINT Length,
  4. DWORD Usage,
  5. D3DFORMAT Format, //确定哪种索引格式,有16位,和32位,它们可以容纳的最大索引不同
  6. D3DPOOL Pool,
  7. IDirect3DIndexBuffer** ppIndexBuffer,
  8. HANDLE* pShareHandle
  9. );


同样要用类似的Lock()方法锁定索引缓冲区:
  1. HRESULT IDirect3DIndexBuffer9::Lock(
  2. UNIT offsetToLock, //以字节计算的偏移地址,从缓冲区首部开始偏移地质处开始锁定
  3. UNIT sizeToLock, //锁定的字节数
  4. BYTE** ppData, //返回被锁定的缓冲区区域的头指针
  5. DWORD Flags, //描述缓冲区锁定方式的标识
  6. );



同样的Unlock()方法


             到此渲染的数据已经准备完毕,在渲染之前还需要做几件事情:

1、设定数据源,也就是顶点缓冲区,把数据挂接到渲染流水线上等待渲染。

  1. HRESULT IDirect3DDevice9::SetStreamSource(
  2. UINT StreamNumber, //根据显卡能力不同,可以支持多条流水线同时工作
  3. IDirect3DVertexBuffer9* pStreamData, //顶点缓冲区数据指针
  4. UINT offsetInBytes, //设置从缓冲区第几个字节开始挂接
  5. UINT Stride, //顶点缓冲区的顶点大小,以字节计算
  6. );

2、设置顶点格式:

SetFVF();


3、设置索引缓冲区:

SetIndices(IndexBuffer);


然后就可以开始渲染了。

下面有两个例子,一个是渲染一个三角形,没用到索引缓冲区,一个是渲染一个旋转立方体。

  1. //----------------------------------------------------------------------------
  2. //---------渲染一个一个基本的三维三角形
  3. //---------by coderLing 2013.3.29
  4. //----------------------------------------------------------------------------
  5. #include <d3d9.h>
  6. //------Some gobal variables---------------------------------------------------
  7. LPDIRECT3D9 g_pD3D = NULL; //用于创建D3DDevice 对象
  8. LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
  9. LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; //指向顶点缓冲区
  10. //------自定义顶点类型---------------------------------------------------------
  11. struct CUSTOMVERTEX
  12. {
  13. FLOAT x, y, z, rhw;
  14. DWORD color;
  15. };
  16. //------自定义的FVF------------------------------------------------------------
  17. #define D3DFVF_CUSTOMVERTEX ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
  18. //------常量-------------------------------------------------------------------
  19. #define WND_NAME L"vertexBuffer"
  20. #define WND_TITLE L"Directx3D深入详解之——创建使用定点缓冲区"
  21. //------初始化Directx3D--------------------------------------------------------
  22. HRESULT InitD3D( HWND hWnd )
  23. {
  24. //创建 D3D 对象
  25. if( NULL == ( g_pD3D = Direct3DCreate9 ( D3D_SDK_VERSION) ) )
  26. return E_FAIL;
  27. //设置D3DPRESENT_PRAMETERS参数
  28. D3DPRESENT_PARAMETERS d3dpp;
  29. SecureZeroMemory( &d3dpp, sizeof(d3dpp) );
  30. d3dpp.Windowed = TRUE;
  31. d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  32. d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
  33. //创建 D3DDevice
  34. if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
  35. D3DCREATE_SOFTWARE_VERTEXPROCESSING,
  36. &d3dpp, &g_pd3dDevice ) ) )
  37. {
  38. return E_FAIL;
  39. }
  40. return S_OK;
  41. }
  42. //------初始化顶点缓冲区--------------------------------------------------------
  43. HRESULT InitVB()
  44. {
  45. CUSTOMVERTEX vertices[] =
  46. {
  47. { 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, //x, y, z, rhw, color
  48. { 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
  49. { 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },
  50. };
  51. //创建顶点缓冲区,要申请足够的内存空间
  52. if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX),
  53. 0, D3DFVF_CUSTOMVERTEX,
  54. D3DPOOL_DEFAULT, &g_pVB, NULL) ) )
  55. return E_FAIL;
  56. //把顶点数据填充到缓冲区中
  57. VOID* pVertices;
  58. if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
  59. return E_FAIL;
  60. memcpy( pVertices, vertices, sizeof(vertices) );
  61. g_pVB->Unlock();
  62. return S_OK;
  63. }
  64. //------释放资源----------------------------------------------------------------------
  65. VOID Cleanup()
  66. {
  67. if( g_pVB != NULL)
  68. g_pVB->Release();
  69. if( g_pd3dDevice != NULL)
  70. g_pd3dDevice->Release();
  71. if( g_pD3D != NULL)
  72. g_pD3D->Release();
  73. }
  74. //--------渲染过程---------------------------------------------------------------------
  75. VOID Render()
  76. {
  77. //把背景缓冲区变为蓝色
  78. g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);
  79. //开始渲染
  80. if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
  81. {
  82. //绘制三角形
  83. g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); //设置数据源
  84. g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); //设置顶点格式
  85. g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 ); //渲染顶点缓冲区中的图形
  86. //渲染结束
  87. g_pd3dDevice->EndScene();
  88. }
  89. g_pd3dDevice->Present( NULL, NULL, NULL, NULL);
  90. }
  91. //---------消息过程---------------------------------------------------------------------
  92. LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  93. {
  94. switch( msg )
  95. {
  96. case WM_DESTROY:
  97. Cleanup();
  98. PostQuitMessage( 0 );
  99. return 0;
  100. }
  101. return DefWindowProc( hWnd, msg, wParam, lParam );
  102. }
  103. //---------WinMain()函数----------------------------------------------------------------
  104. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT)
  105. {
  106. WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
  107. GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
  108. WND_NAME, NULL};
  109. RegisterClassEx( &wc );
  110. HWND hWnd = CreateWindow( WND_NAME, WND_TITLE, WS_OVERLAPPEDWINDOW,
  111. 100, 100, 300, 300, GetDesktopWindow(),
  112. NULL, wc.hInstance, NULL );
  113. if( SUCCEEDED( InitD3D(hWnd) ) )
  114. {
  115. if( SUCCEEDED( InitVB() ) )
  116. {
  117. ShowWindow( hWnd, SW_SHOWDEFAULT );
  118. UpdateWindow( hWnd );
  119. //消息循环
  120. MSG msg;
  121. SecureZeroMemory( &msg, sizeof(MSG) );
  122. while( msg.message != WM_QUIT )
  123. {
  124. if( PeekMessage( &msg, NULL,0U, 0U, PM_REMOVE ) )
  125. {
  126. TranslateMessage( &msg );
  127. DispatchMessage( &msg );
  128. }
  129. else
  130. Render();
  131. }
  132. }
  133. }
  134. UnregisterClass( WND_NAME, wc.hInstance );
  135. return 0;
  136. }



旋转立方体:

  1. //--------ColorfulCube----------------------------------------------------------------
  2. //--------by coderLing 2013.3.30
  3. //------------------------------------------------------------------------------------
  4. #include <d3d9.h>
  5. #include <d3dx9.h> //如果要使用D3DX库就必须加入这个头文件
  6. //定义使用到的顶点结构
  7. struct CUSTOMVERTEX
  8. {
  9. FLOAT x,y,z; //顶点坐标信息
  10. DWORD color; //顶点颜色信息
  11. };
  12. //定义顶点的FVF结构
  13. #define D3DFVF_CUSTOMVERTEX ( D3DFVF_XYZ | D3DFVF_DIFFUSE)
  14. #define WND_NAME L"ColorfulCube"
  15. #define WND_TITLE L"Directx3D游戏开发之-ColorfulCube"
  16. //some gobal variables
  17. LPDIRECT3D9 g_pD3D = NULL; //Direct3D对象指针,LP开头便是指针
  18. LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; //Direct3D 设备
  19. LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; //顶点缓冲区指针
  20. LPDIRECT3DINDEXBUFFER9 g_pIB = NULL; //索引缓冲区指针
  21. //初始化Direct3D设备
  22. HRESULT InitD3D( HWND hWnd)
  23. {
  24. //创建Directx3D对象
  25. if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
  26. return E_FAIL;
  27. //填写创建Direct3D设备的结构体
  28. D3DPRESENT_PARAMETERS d3dpp;
  29. SecureZeroMemory( &d3dpp, sizeof( d3dpp ));
  30. d3dpp.Windowed = TRUE;
  31. d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  32. d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
  33. //创建Direct3D设备
  34. if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
  35. D3DCREATE_SOFTWARE_VERTEXPROCESSING,
  36. &d3dpp, &g_pD3DDevice) ) )
  37. {
  38. return E_FAIL;
  39. }
  40. return S_OK;
  41. }
  42. //初始化绘图相关数据,顶点缓冲区,索引缓冲区
  43. HRESULT InitDraw()
  44. {
  45. //创建顶点缓冲区
  46. g_pD3DDevice->CreateVertexBuffer(
  47. 8 * sizeof(CUSTOMVERTEX),
  48. D3DUSAGE_WRITEONLY,
  49. D3DFVF_CUSTOMVERTEX,
  50. D3DPOOL_MANAGED,
  51. &g_pVB,
  52. 0);
  53. //创建索引缓冲区
  54. g_pD3DDevice->CreateIndexBuffer(
  55. 36 * sizeof(WORD),
  56. D3DUSAGE_WRITEONLY,
  57. D3DFMT_INDEX16,
  58. D3DPOOL_MANAGED,
  59. &g_pIB,
  60. 0);
  61. //创建立方体的8个顶点,每个顶点的颜色都不同
  62. //在绘制是,Direct3D会根据顶点的颜色对三角形内部像素进行插值,所以立方体看起来是彩色的
  63. CUSTOMVERTEX source_vertices[] ={
  64. { -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(255,0,0) },
  65. { -1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0,255,0) },
  66. { 1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0,0,255) },
  67. { 1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(255,255,0) },
  68. { -1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(255,0,255) },
  69. { -1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0,255,255) },
  70. { 1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0,0,0) },
  71. { 1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(255,255,255) }
  72. };
  73. //把上面的顶点数据复制到所创建的缓冲区中
  74. CUSTOMVERTEX* pVertices;
  75. if( FAILED( g_pVB->Lock(0, 8*sizeof(CUSTOMVERTEX), (VOID**)&pVertices, 0) ) )
  76. return E_FAIL;
  77. memcpy( pVertices, source_vertices, 8*sizeof(CUSTOMVERTEX) );
  78. g_pVB->Unlock();
  79. //定义索引缓冲区的内容
  80. WORD* indices = 0;
  81. g_pIB->Lock(0, 0, (VOID**)&indices, 0);
  82. //正面
  83. indices[0] = 0; indices[1] = 1; indices[2] = 2;
  84. indices[3] = 0; indices[4] = 2; indices[5] = 3;
  85. //背面
  86. indices[6] = 4; indices[7] = 6; indices[8] = 5;
  87. indices[9] = 4; indices[10] = 7; indices[11] = 6;
  88. //左面
  89. indices[12] = 4; indices[13] = 5; indices[14] = 1;
  90. indices[15] = 4; indices[16] = 1; indices[17] = 0;
  91. //右面
  92. indices[18] = 3; indices[19] = 2; indices[20] = 6;
  93. indices[21] = 3; indices[22] = 6; indices[23] = 7;
  94. //顶面
  95. indices[24] = 1; indices[25] = 5; indices[26] = 6;
  96. indices[27] = 1; indices[28] = 6; indices[29] = 2;
  97. //顶面
  98. indices[30] = 4; indices[31] = 0; indices[32] = 3;
  99. indices[33] = 4; indices[34] = 3; indices[35] = 7;
  100. g_pIB->Unlock();
  101. //设置摄像机
  102. D3DXVECTOR3 position(0.0f, 0.0f, -5.0f);
  103. D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
  104. D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
  105. D3DXMATRIX V;
  106. D3DXMatrixLookAtLH(&V, &position, &target, &up);
  107. g_pD3DDevice->SetTransform(D3DTS_VIEW, &V);
  108. //设置投影矩阵
  109. D3DXMATRIX proj;
  110. D3DXMatrixPerspectiveFovLH(
  111. &proj,
  112. D3DX_PI * 0.5f,
  113. (float)800 / (float)600,
  114. 1.0f,
  115. 1000.0f
  116. );
  117. g_pD3DDevice->SetTransform( D3DTS_PROJECTION, &proj);
  118. //没有材质,纹理信息,关闭灯光显示出本身颜色
  119. g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
  120. return S_OK;
  121. }
  122. //------释放资源------------------------------------------------------------------------------
  123. VOID Cleanup()
  124. {
  125. if( g_pVB != NULL )
  126. g_pVB->Release();
  127. if( g_pIB != NULL )
  128. g_pIB->Release();
  129. if( g_pD3DDevice != NULL )
  130. g_pD3DDevice->Release();
  131. if( g_pD3D != NULL)
  132. g_pD3D->Release();
  133. }
  134. //--------渲染函数------------------------------------------------------------------
  135. VOID Render()
  136. {
  137. //清除屏幕缓冲区到蓝色屏幕
  138. g_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255),1.0f, 0);
  139. //开始绘制
  140. if( SUCCEEDED( g_pD3DDevice->BeginScene() ) )
  141. {
  142. //创建沿3个轴的矩阵
  143. D3DXMATRIXA16 matWorld_X;
  144. D3DXMatrixIdentity( &matWorld_X);
  145. D3DXMatrixRotationX( &matWorld_X, timeGetTime()/500.0f);
  146. D3DXMATRIXA16 matWorld_Y;
  147. D3DXMatrixIdentity( &matWorld_Y);
  148. D3DXMatrixRotationY( &matWorld_Y, timeGetTime()/500.0f);
  149. D3DXMATRIXA16 matWorld_Z;
  150. D3DXMatrixIdentity( &matWorld_Z);
  151. D3DXMatrixRotationZ( &matWorld_Z, timeGetTime()/500.0f);
  152. //设置物体的世界矩阵
  153. g_pD3DDevice->SetTransform( D3DTS_WORLD,
  154. &(matWorld_X*matWorld_Y*matWorld_Z) );
  155. g_pD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
  156. g_pD3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
  157. g_pD3DDevice->SetIndices( g_pIB );
  158. g_pD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 8, 0,12);
  159. //结束绘制
  160. g_pD3DDevice->EndScene();
  161. }
  162. //显示
  163. g_pD3DDevice->Present( NULL, NULL, NULL, NULL);
  164. }
  165. //消息回调函数
  166. LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  167. {
  168. switch( msg )
  169. {
  170. case WM_DESTROY:
  171. Cleanup();
  172. PostQuitMessage( 0 );
  173. return 0;
  174. }
  175. return DefWindowProc( hWnd, msg, wParam, lParam );
  176. }
  177. //Main函数
  178. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT)
  179. {
  180. //创建及注册窗口类
  181. WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
  182. GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
  183. WND_NAME, NULL};
  184. RegisterClassEx( &wc );
  185. //创建窗口
  186. HWND hWnd = CreateWindow( WND_NAME, WND_TITLE, WS_OVERLAPPEDWINDOW,
  187. 100, 100, 800, 600, GetDesktopWindow(),
  188. NULL, wc.hInstance, NULL );
  189. if( SUCCEEDED( InitD3D(hWnd) ) )
  190. {
  191. if( SUCCEEDED( InitDraw() ) )
  192. {
  193. //显示窗口
  194. ShowWindow( hWnd, SW_SHOWDEFAULT );
  195. UpdateWindow( hWnd );
  196. //消息循环
  197. MSG msg;
  198. SecureZeroMemory( &msg, sizeof(msg) );
  199. while( msg.message != WM_QUIT )
  200. {
  201. if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
  202. {
  203. TranslateMessage( &msg );
  204. DispatchMessage( &msg );
  205. }
  206. else
  207. Render();
  208. }
  209. }
  210. }
  211. UnregisterClass( WND_NAME, wc.hInstance );
  212. return 0;
  213. }



The End ~~~~~~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/571717
推荐阅读
相关标签
  

闽ICP备14008679号