收藏 分享(赏)

【Visual C 】游戏开发笔记二十九 一步一步教你用优雅的DirectD代码画一个三角形.doc

上传人:dzzj200808 文档编号:3164217 上传时间:2018-10-05 格式:DOC 页数:29 大小:164KB
下载 相关 举报
【Visual C  】游戏开发笔记二十九 一步一步教你用优雅的DirectD代码画一个三角形.doc_第1页
第1页 / 共29页
【Visual C  】游戏开发笔记二十九 一步一步教你用优雅的DirectD代码画一个三角形.doc_第2页
第2页 / 共29页
【Visual C  】游戏开发笔记二十九 一步一步教你用优雅的DirectD代码画一个三角形.doc_第3页
第3页 / 共29页
【Visual C  】游戏开发笔记二十九 一步一步教你用优雅的DirectD代码画一个三角形.doc_第4页
第4页 / 共29页
【Visual C  】游戏开发笔记二十九 一步一步教你用优雅的DirectD代码画一个三角形.doc_第5页
第5页 / 共29页
点击查看更多>>
资源描述

1、【Visual C+】游戏开发笔记二十九 一步一步教你用优雅的 Direct3D11 代码画一个三角形本系列文章由 zhmxy555(毛星云)编写,转载请注明出处。http:/ 邮箱: 这个 demo 演示的效果是用 Direct3D11 在屏幕上渲染一个三角形,当然是通过这个 demo 进一步巩固和学习Direct3D11,而不是单单为了画一个三角形这么简单。正如之前所说,这个 demo 是建立在笔记二十八中讲解的 D3D BlankWindows Demo 之上的。那么,我们就开门见山,直入正题吧。一、 载入几何体我们知道,为了渲染几何图形,我们需要一个顶点缓存,一个描述顶点布局的输入层

2、,以及一系列的着色器,自 DirectX10 以来,着色器开始作为图形渲染的基础组成部分,在这个 demo 之中我们会指定顶点着色器与像素着色器,渲染一种简单的纯色表面。后面我们将延伸的讲解如何拓展使用这种效果来在表面映射图形纹理。下面就开始进行这个 demo 的书写:这个 demo 的核心内容当然是一个叫做 TriangleDemo 的类,我们为这个类定义几个成员变量,他们分别是ID3D11VertexShader 类型的取名为 solidColorVS_的变量,一个 ID3D11PixelShader 类型的唤作solidColorPS 的变量。一个 ID3D11InputLayout 类

3、型的唤作 inputLayout_的变量,以及一个 ID3D11Buffer类型的叫做 vertexBuffer_的变量。下面就是 TriangleDemo.h 头文件的源代码,简单的勾勒出了本文主角 TriangleDemo 类的轮廓:代码段一 TriangleDemo.h 头文件cpp view plaincopyprint?1. #include“Dx11DemoBase.h“ 2. 3. class TriangleDemo : public Dx11DemoBase 4. 5. 6. 7. public: 8. 9. TriangleDemo( ); 10. 11. virtual

4、TriangleDemo( ); 12. 13. bool LoadContent( ); 14. 15. void UnloadContent( ); 16. 17. void Update( float dt ); 18. 19. void Render( ); 20. 21. private: 22. 23. ID3D11VertexShader* solidColorVS_; 24. 25. ID3D11PixelShader* solidColorPS_; 26. 27. ID3D11InputLayout* inputLayout_; 28. 29. ID3D11Buffer* v

5、ertexBuffer_; 30. 31. ; 顶点我们采用一个简单的三分量式的浮点型结构体,在 XNA Math library 中一个叫做 XMFLOAT3 的结构体可以胜任这项殊荣。接下来,开始丰富我们的 TriangleDemo 类,我们在代码段二中书写顶点结构体 VertexPos 和 TriangleDemo的类的构造函数以及析构函数代码段二 TriangleDemo 顶点结构体, 构造函数和析构函数.cpp view plaincopyprint?1. #include“TriangleDemo.h“ 2. 3. #include 4. 5. struct VertexPos 6

6、. 7. 8. 9. XMFLOAT3 pos; 10. 11. ; 12. 13. TriangleDemo:TriangleDemo( ) : solidColorVS_( 0 ), solidColorPS_( 0 ), 14. 15. inputLayout_( 0 ), vertexBuffer_( 0 ) 16. 17. 18. 19. 20. 21. TriangleDemo:TriangleDemo( ) 22. 23. 24. 25. 下面继续丰富我们的 TriangleDemo 类,在代码段三中我们进行 UnloadContent 函数的书写,顾名思义,UnloadCont

7、ent 是进行 unload content 工作的,与后面将书写的 LoadContent 函数相对应。代码段三 TriangleDemo 类的 UnloadContent 函数的书写cpp view plaincopyprint?1. void TriangleDemo:UnloadContent( ) 2. 3. 4. 5. if( solidColorVS_ ) solidColorVS_-Release( ); 6. 7. if( solidColorPS_ ) solidColorPS_-Release( ); 8. 9. if( inputLayout_ ) inputLayou

8、t_-Release( ); 10. 11. if( vertexBuffer_ ) vertexBuffer_-Release( ); 12. 13. solidColorVS_ = 0; 14. 15. solidColorPS_ = 0; 16. 17. inputLayout_ = 0; 18. 19. vertexBuffer_ = 0; 20. 21. 顺理成章的,下一步便是 LoadContent 函数的书写。这个函数由顶点着色器载入,在文件SolidGreenColor.fx 中可以查看。一旦顶点着色器的源代码编译完成,着色器便创建一个 CreateVertexShader 函

9、数的调用,我们接着创建顶点格式。由于顶点着色器与顶点格式相关联,所以我们还需要将顶点着色器加载到内存中。创建完顶点着色器和输入格式后,下一步我们创建像素着色器。下面这段代码实现了 LoadContent 方法的一半的功能:代码段四 LoadContent 函数着色器载入代码cpp view plaincopyprint?1. bool TriangleDemo:LoadContent( ) 2. 3. 4. 5. ID3DBlob* vsBuffer = 0; 6. 7. bool compileResult = CompileD3DShader( “SolidGreenColor.fx“,

10、8. 9. “VS_Main“, “vs_4_0“, 10. 11. if( compileResult = false ) 12. 13. 14. 15. MessageBox( 0, “载入顶点着色器错误!“, “编译错误“ , MB_OK ); 16. 17. return false; 18. 19. 20. 21. HRESULT d3dResult; 22. 23. d3dResult = d3dDevice_-CreateVertexShader( vsBuffer-GetBufferPointer( 24. 25. ), 26. 27. vsBuffer-GetBufferSi

11、ze( ), 0, 28. 29. if( FAILED( d3dResult ) ) 30. 31. 32. 33. if( vsBuffer ) 34. 35. vsBuffer-Release( ); 36. 37. return false; 38. 39. 40. 41. D3D11_INPUT_ELEMENT_DESC solidColorLayout = 42. 43. 44. 45. “POSITION“, 0, DXGI_FORMAT_R32G32B32_FLOAT, 46. 47. 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 48. 49. ;

12、 50. 51. unsigned int totalLayoutElements = ARRAYSIZE( solidColorLayout ); 52. 53. d3dResult = d3dDevice_-CreateInputLayout( solidColorLayout, 54. 55. totalLayoutElements, vsBuffer-GetBufferPointer( ), 56. 57. vsBuffer-GetBufferSize( ), 58. 59. vsBuffer-Release( ); 60. 61. if( FAILED( d3dResult ) )

13、62. 63. 64. 65. return false; 66. 67. 68. 69. ID3DBlob* psBuffer = 0; 70. 71. compileResult = CompileD3DShader( “SolidGreenColor.fx“, 72. 73. “PS_Main“, “ps_4_0“, 74. 75. if( compileResult = false ) 76. 77. 78. 79. MessageBox( 0, “载入像素着色器错误!“, “编译错误“, MB_OK ); 80. 81. return false; 82. 83. 84. 85. d

14、3dResult = d3dDevice_-CreatePixelShader( psBuffer-GetBufferPointer( ), 86. 87. psBuffer-GetBufferSize( ), 0, 88. 89. psBuffer-Release( ); 90. 91. if( FAILED( d3dResult ) ) 92. 93. 94. 95. return false; 96. 97. 98. 99. . 100. 101. /后接函数的下半段 102. 103. CompileD3DShader 相关的代码在代码段五中进行了演绎,这段代码巧妙地被分离于 Load

15、Content 之外,这样在加载多个不同的着色效果的时候便可以避免大段大段的冗余代码:代码段五 CompileShader 函数的实现方法cpp view plaincopyprint?1. bool Dx11DemoBase:CompileD3DShader( char* filePath, char* entry, char* 2. 3. shaderModel, ID3DBlob* buffer ) 4. 5. 6. 7. DWORD shaderFlags = D3DCOMPILE_ENABLE_STRICTNESS; 8. 9. #if defined( DEBUG ) | defi

16、ned( _DEBUG ) 10. 11. shaderFlags |= D3DCOMPILE_DEBUG; 12. 13. #endif 14. 15. ID3DBlob* errorBuffer = 0; 16. 17. HRESULT result; 18. 19. result = D3DX11CompileFromFile( filePath, 0, 0, entry, shaderModel, 20. 21. shaderFlags, 0, 0, buffer, 22. 23. if( FAILED( result ) ) 24. 25. 26. 27. if( errorBuff

17、er != 0 ) 28. 29. 30. 31. OutputDebugStringA( ( char* )errorBuffer-GetBufferPointer( ) ); 32. 33. errorBuffer-Release( ); 34. 35. 36. 37. return false; 38. 39. 40. 41. if( errorBuffer != 0 ) 42. 43. errorBuffer-Release( ); 44. 45. return true; 46. 47. 上面我们介绍了上半段 LoadContent 函数的构成,而下半段 LoadContent 函数

18、主要实现了顶点缓存的创建。这段代码行文思路很明朗,首先定义一个简单的三角形,沿 X 轴与 Y 轴都是 0.5f(半个单位的长度)。Z 轴依然设为为 0.5f,来使此三角形可见。因为若镜头隔表面太近或者太远,表面都不会成功的渲染。顶点列表存储于一个叫做 vertices 的数组中,它提供了一个子资源数据,在 CreateBuffer 函数开始调用进行实际顶点缓存的创建的时候,这些数据可以派上用场。下面就是上面这段叙述的代码实现,LoadContent 函数的下半部分书写风格如下:代码段六 LoadContent 函数的几何图形载入代码cpp view plaincopyprint?1. bool

19、 TriangleDemo:LoadContent( ) 2. 3. 4. 5. /前接函数的上半段 6. 7. 8. 9. . 10. 11. VertexPos vertices = 12. 13. 14. 15. XMFLOAT3( 0.5f, 0.5f, 0.5f ), 16. 17. XMFLOAT3( 0.5f, -0.5f, 0.5f ), 18. 19. XMFLOAT3( -0.5f, -0.5f, 0.5f ) 20. 21. ; 22. 23. D3D11_BUFFER_DESC vertexDesc; 24. 25. ZeroMemory( 26. 27. vertex

20、Desc.Usage = D3D11_USAGE_DEFAULT; 28. 29. vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 30. 31. vertexDesc.ByteWidth = sizeof( VertexPos ) * 3; 32. 33. D3D11_SUBRESOURCE_DATA resourceData; 34. 35. ZeroMemory( 36. 37. resourceData.pSysMem = vertices; 38. 39. d3dResult = d3dDevice_-CreateBuffer( 42

21、. 43. if( FAILED( d3dResult ) ) 44. 45. 46. 47. return false; 48. 49. 50. 51. return true; 52. 53. 二、渲染几何体Direct11 三角形 Demo 代码的最后两部分由实现几何渲染功能的代码和着色器本身构成。渲染几何图形的构成代码在 TriangleDemo 类中的 Render 函数中进行。函数中有有一个条件语句,这样可以确保在 Direct3D 的上下文是有效的。接下来,我们清除渲染目标,并设定输出程序集(input assembler)。而实际上,因为在这个 demo 之中的三角形是静态的,

22、我们并不一定非要清除渲染目标,这里只是为了规范我们的代码书写,以免养成不良的开发习惯。在输出程序集阶段的设置由我们已经创建的输出结构(input layout)进行绑定,并提供顶点缓存,设置拓扑三角形的列表。下面贴出 Render 函数的书写思路:代码段七 TriangleDemo 类的 render 函数书写cpp view plaincopyprint?1. void TriangleDemo:Render( ) 2. 3. 4. 5. if( d3dContext_ = 0 ) 6. 7. return; 8. 9. float clearColor4 = 0.5, 0.5f, 0.5f

23、, 1.0f ; /设定背景颜色 10. 11. d3dContext_-ClearRenderTargetView( backBufferTarget_, clearColor ); 12. 13. unsigned int stride = sizeof( VertexPos ); 14. 15. unsigned int offset = 0; 16. 17. d3dContext_-IASetInputLayout( inputLayout_ ); 18. 19. d3dContext_-IASetVertexBuffers( 0, 1, 20. 21. d3dContext_-IAS

24、etPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_ 22. 23. TRIANGLELIST ); 24. 25. d3dContext_-VSSetShader( solidColorVS_, 0, 0 ); 26. 27. d3dContext_-PSSetShader( solidColorPS_, 0, 0 ); 28. 29. d3dContext_-Draw( 3, 0 ); 30. 31. swapChain_-Present( 0, 0 ); 32. 33. 最后一部分要介绍的代码是着色器。笼统的来说,顶点着色器基于它得到的内容。详细的

25、来说,顶点着色器的作用是将内部得到的顶点位置传递到输出处,之后,我们须处理这些数据,正确绘制出我们的图形。但对于这个非常基础的 demo,仅仅进行顶点位置内容的传递就够了。如果没有几何图形着色器绑定到输出程序集之上,顶点着色器的输出的数据就是像素着色器的输入的数据。其中,像素着色器的输出就是写到输出缓存之中的颜色值。当交换链中的 Present 函数调用的时候,这个缓存就会最终显示给用户。TriangleDemo 的顶点着色器和像素着色器的书写方法如下代码段八:代码段八 Triangledemo 着色器的实现代码cpp view plaincopyprint?1. float4 VS_Main

26、( float4 pos : POSITION ) : SV_POSITION 2. 3. 4. 5. return pos; 6. 7. 8. 9. float4 PS_Main( float4 pos : SV_POSITION ) : SV_TARGET 10. 11. 12. 13. return float4( 0.0f, 1.0f, 0.0f, 1.0f ); 14. 15. 这样,Triangledemo 类就随着一步一步的勾勒,被我们书写完成了。三、Dx11DemoBase 类的书写接下来,我们将之前讲解的 BlankD3DWindows Demo 模板中的 Dx11DemoB

27、ase 类进行丰富和修改,即可得到适用于本节 demo 的 Dx11DemoBase 类。代码段九 Dx11DemoBase.hcpp view plaincopyprint?1. #ifndef _DEMO_BASE_H_ 2. 3. #define _DEMO_BASE_H_ 4. 5. 6. 7. #include 8. 9. #include 10. 11. #include 12. 13. 14. 15. 16. 17. class Dx11DemoBase 18. 19. 20. 21. public: 22. 23. Dx11DemoBase(); 24. 25. virtual

28、 Dx11DemoBase(); 26. 27. 28. 29. bool Initialize( HINSTANCE hInstance, HWND hwnd ); 30. 31. void Shutdown( ); 32. 33. 34. 35. bool CompileD3DShader( char* filePath, char* entry, 36. 37. char* shaderModel, ID3DBlob* buffer ); 38. 39. 40. 41. virtual bool LoadContent( ); 42. 43. virtual void UnloadCon

29、tent( ); 44. 45. 46. 47. virtual void Update( float dt ) = 0; 48. 49. virtual void Render( ) = 0; 50. 51. 52. 53. protected: 54. 55. HINSTANCE hInstance_; 56. 57. HWND hwnd_; 58. 59. 60. 61. D3D_DRIVER_TYPE driverType_; 62. 63. D3D_FEATURE_LEVEL featureLevel_; 64. 65. 66. 67. ID3D11Device* d3dDevice

30、_; 68. 69. ID3D11DeviceContext* d3dContext_; 70. 71. IDXGISwapChain* swapChain_; 72. 73. ID3D11RenderTargetView* backBufferTarget_; 74. 75. ; 76. 77. 78. 79. #endif 80. 81. 代码段十 Dx11DemoBase.cppcpp view plaincopyprint?1. #include“Dx11DemoBase.h“ 2. 3. #include 4. 5. 6. 7. 8. 9. Dx11DemoBase:Dx11Demo

31、Base( ) : driverType_( D3D_DRIVER_TYPE_NULL ), featureLevel_( D3D_FEATURE_LEVEL_11_0 ), 10. 11. d3dDevice_( 0 ), d3dContext_( 0 ), swapChain_( 0 ), backBufferTarget_( 0 ) 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. Dx11DemoBase:Dx11DemoBase( ) 24. 25. 26. 27. Shutdown( ); 28. 29. 30. 31. 32. 33.

32、 34. 35. bool Dx11DemoBase:Initialize( HINSTANCE hInstance, HWND hwnd ) 36. 37. 38. 39. hInstance_ = hInstance; 40. 41. hwnd_ = hwnd; 42. 43. 44. 45. RECT dimensions; 46. 47. GetClientRect( hwnd, 48. 49. 50. 51. unsigned int width = dimensions.right - dimensions.left; 52. 53. unsigned int height = d

33、imensions.bottom - dimensions.top; 54. 55. 56. 57. D3D_DRIVER_TYPE driverTypes = 58. 59. 60. 61. D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, 62. 63. D3D_DRIVER_TYPE_REFERENCE, D3D_DRIVER_TYPE_SOFTWARE 64. 65. ; 66. 67. 68. 69. unsigned int totalDriverTypes = ARRAYSIZE( driverTypes ); 70. 71. 72.

34、 73. D3D_FEATURE_LEVEL featureLevels = 74. 75. 76. 77. D3D_FEATURE_LEVEL_11_0, 78. 79. D3D_FEATURE_LEVEL_10_1, 80. 81. D3D_FEATURE_LEVEL_10_0 82. 83. ; 84. 85. 86. 87. unsigned int totalFeatureLevels = ARRAYSIZE( featureLevels ); 88. 89. 90. 91. DXGI_SWAP_CHAIN_DESC swapChainDesc; 92. 93. ZeroMemory

35、( 94. 95. swapChainDesc.BufferCount = 1; 96. 97. swapChainDesc.BufferDesc.Width = width; 98. 99. swapChainDesc.BufferDesc.Height = height; 100. 101. swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 102. 103. swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; 104. 105. swapChainDesc.Bu

36、fferDesc.RefreshRate.Denominator = 1; 106. 107. swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 108. 109. swapChainDesc.OutputWindow = hwnd; 110. 111. swapChainDesc.Windowed = true; 112. 113. swapChainDesc.SampleDesc.Count = 1; 114. 115. swapChainDesc.SampleDesc.Quality = 0; 116. 117. 1

37、18. 119. unsigned int creationFlags = 0; 120. 121. 122. 123. #ifdef _DEBUG 124. 125. creationFlags |= D3D11_CREATE_DEVICE_DEBUG; 126. 127. #endif 128. 129. 130. 131. HRESULT result; 132. 133. unsigned int driver = 0; 134. 135. 136. 137. for( driver = 0; driver GetBuffer( 0, _uuidof( ID3D11Texture2D

38、), ( LPVOID* ) 182. 183. 184. 185. if( FAILED( result ) ) 186. 187. 188. 189. DXTRACE_MSG( “获取交换链后台缓存失败!“ ); 190. 191. return false; 192. 193. 194. 195. 196. 197. result = d3dDevice_-CreateRenderTargetView( backBufferTexture, 0, 198. 199. 200. 201. if( backBufferTexture ) 202. 203. backBufferTexture

39、-Release( ); 204. 205. 206. 207. if( FAILED( result ) ) 208. 209. 210. 211. DXTRACE_MSG( “创建渲染目标视图失败!“ ); 212. 213. return false; 214. 215. 216. 217. 218. 219. d3dContext_-OMSetRenderTargets( 1, 220. 221. 222. 223. D3D11_VIEWPORT viewport; 224. 225. viewport.Width = static_cast(width); 226. 227. vie

40、wport.Height = static_cast(height); 228. 229. viewport.MinDepth = 0.0f; 230. 231. viewport.MaxDepth = 1.0f; 232. 233. viewport.TopLeftX = 0.0f; 234. 235. viewport.TopLeftY = 0.0f; 236. 237. 238. 239. d3dContext_-RSSetViewports( 1, 240. 241. 242. 243. return LoadContent( ); 244. 245. 246. 247. 248. 2

41、49. 250. 251. bool Dx11DemoBase:CompileD3DShader( char* filePath, char* entry, char* shaderModel, ID3DBlob* buffer ) 252. 253. 254. 255. DWORD shaderFlags = D3DCOMPILE_ENABLE_STRICTNESS; 256. 257. 258. 259. #if defined( DEBUG ) | defined( _DEBUG ) 260. 261. shaderFlags |= D3DCOMPILE_DEBUG; 262. 263.

42、 #endif 264. 265. 266. 267. ID3DBlob* errorBuffer = 0; 268. 269. HRESULT result; 270. 271. 272. 273. result = D3DX11CompileFromFile( filePath, 0, 0, entry, shaderModel, 274. 275. shaderFlags, 0, 0, buffer, 276. 277. 278. 279. if( FAILED( result ) ) 280. 281. 282. 283. if( errorBuffer != 0 ) 284. 285

43、. 286. 287. OutputDebugStringA( ( char* )errorBuffer-GetBufferPointer( ) ); 288. 289. errorBuffer-Release( ); 290. 291. 292. 293. 294. 295. return false; 296. 297. 298. 299. 300. 301. if( errorBuffer != 0 ) 302. 303. errorBuffer-Release( ); 304. 305. 306. 307. return true; 308. 309. 310. 311. 312. 3

44、13. 314. 315. bool Dx11DemoBase:LoadContent( ) 316. 317. 318. 319. / 进行相关重载 320. 321. return true; 322. 323. 324. 325. 326. 327. 328. 329. void Dx11DemoBase:UnloadContent( ) 330. 331. 332. 333. / 进行相关重载 334. 335. 336. 337. 338. 339. 340. 341. void Dx11DemoBase:Shutdown( ) 342. 343. 344. 345. UnloadC

45、ontent( ); 346. 347. 348. 349. if( backBufferTarget_ ) backBufferTarget_-Release( ); 350. 351. if( swapChain_ ) swapChain_-Release( ); 352. 353. if( d3dContext_ ) d3dContext_-Release( ); 354. 355. if( d3dDevice_ ) d3dDevice_-Release( ); 356. 357. 358. 359. backBufferTarget_ = 0; 360. 361. swapChain_ = 0; 362. 363. d3dContext_ = 0; 364. 365. d3dDevice_ = 0; 366. 367. 四、 赋予程序生命 wWinMain 函数的书写最后一步,依旧是主函数的书写,这个函数大家应该是最熟悉的,任何想顺利运行的 C/C+程序中必不可少,而且这里的书写方式和前面 demo 中的也大同小异,浅墨在这里就不多赘言了,代码如下:代码段十一 wWinMain 函数的书写cpp view plaincopypr

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 实用文档 > 往来文书

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报