C++小项目:directx11图形程序:particleSysclass

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++小项目:directx11图形程序:particleSysclass相关的知识,希望对你有一定的参考价值。

粒子系统类,粒子系统是游戏里细小元素的控制系统,虽然感觉上它对游戏的影响不大,但是其实有了它能给游戏增色不少。粒子系统控制着细小元素的生死,运动,纹理。对它的编写让我知道,游戏里的这一片从天空飘落的雪花其实是之前那一朵已经融化在地上的雪花。

 

这个类我还没有编写完整,因为我发现如果要真正实现那种很美的效果我还要多加学习啊。使用广告版技术让人觉得它真的是个粒子,开启alpha通道能让粒子与背景融为一体,开启光照能让粒子煜煜生辉,给纹理混合上颜色才能让粒子真正的变幻幻幻(不是打错字)起来。

particleSysclass.h

 1 #pragma once
 2 #include <d3d11.h>
 3 #include <d3dcompiler.h>
 4 #include <D3DX11.h>
 5 #include <xnamath.h>
 6 #include<time.h>
 7 #pragma comment(lib,"d3dx11.lib")
 8 #pragma comment(lib,"d3d11.lib")
 9 #pragma comment(lib,"d3dcompiler.lib")
10 class particleSysclass
11 {
12 public:
13     particleSysclass();
14     ~particleSysclass();
15 
16 private:
17     ID3D11ShaderResourceView* m_texture;
18     struct vertex
19     {
20         XMFLOAT3 pos;
21         XMFLOAT2 tex;
22     };
23     struct particle
24     {
25         XMFLOAT3 pos;
26         float size;
27         bool alive;
28     };
29     struct constantBuffer
30     {
31         XMMATRIX world;
32         XMMATRIX view;
33         XMMATRIX pro;
34     };
35 
36     vertex *m_vertexarray;
37     particle *m_particlearray;
38     int m_particlecountMAX;
39     int m_particlecountCUR;
40     XMFLOAT3 m_sourcepos;
41 
42     ID3D11Buffer *m_vertexBuffer, *m_indexBuffer;
43     ID3D11Buffer *m_constantBuffer;
44     int m_vertexCount, m_indexCount;
45     ID3D11SamplerState *m_samplerstate;
46     XMMATRIX m_worldMatrix;
47 
48 public:
49     bool Initialize(ID3D11Device* device, LPCWSTR texture, int maxcount);
50     void Render(ID3D11DeviceContext* context, XMMATRIX& viewmatrix, XMMATRIX& pro,
51         ID3D11VertexShader* vertexshader, ID3D11PixelShader* pixelshader);
52     void Shutdown();
53 
54 private:
55     void Emitparticle();
56     void Killparticle();
57     void Updatebuffer(ID3D11DeviceContext* context);
58     void ChangeparticlePos();
59     bool Initbuffer(ID3D11Device* device);    
60     void Loadtexture(ID3D11Device* device,LPCWSTR texture);
61 };

可以看到,粒子系统类与之前的模型类非常相像只是多了:

  • 粒子数据结构,粒子数组指针,粒子最大数量,粒子当前数量(m_particlecountCUR)
  • 私有方法:生成粒子,粒子湮灭,更新缓存,改变例子位置(运动),初始化缓存

particleSysclass.cpp

  1 #include "particleSysclass.h"
  2 
  3 
  4 particleSysclass::particleSysclass()
  5 {
  6     m_worldMatrix = XMMatrixIdentity();
  7 }
  8 
  9 
 10 particleSysclass::~particleSysclass()
 11 {
 12 }
 13 
 14 
 15 bool particleSysclass::Initialize(ID3D11Device* device, LPCWSTR texture, int maxcount)
 16 {
 17     m_particlecountMAX = maxcount;
 18 
 19     Loadtexture(device,texture);
 20 
 21     Initbuffer(device);
 22 
 23     m_particlearray = new particle[m_particlecountMAX];
 24 
 25     srand((unsigned)time(NULL));
 26     for (int i = 0; i < m_particlecountMAX; i++)
 27     {
 28         m_particlearray[i].alive = true;
 29         m_particlearray[i].pos.x = (((float)rand() - (float)rand()) / RAND_MAX) * 5;
 30         m_particlearray[i].pos.y = (((float)rand() - (float)rand()) / RAND_MAX) * 5;
 31         m_particlearray[i].pos.z = (((float)rand() - (float)rand()) / RAND_MAX) * 3;
 32 
 33         m_particlearray[i].size = 0.05;
 34     }
 35 
 36     return false;
 37 }
 38 
 39 
 40 void particleSysclass::Shutdown()
 41 {
 42     if (m_particlearray)
 43     {
 44         delete m_particlearray;
 45     }
 46     if (m_samplerstate)
 47     {
 48         m_samplerstate->Release();
 49     }
 50     if (m_constantBuffer)
 51     {
 52         m_constantBuffer->Release();
 53     }
 54     if (m_indexBuffer)
 55     {
 56         m_indexBuffer->Release();
 57     }
 58     if (m_vertexBuffer)
 59     {
 60         m_vertexBuffer->Release();
 61     }
 62     if (m_vertexarray)
 63     {
 64         delete[] m_vertexarray;
 65     }
 66     if (m_texture)
 67     {
 68         m_texture->Release();
 69     }
 70 }
 71 
 72 
 73 void particleSysclass::Emitparticle()
 74 {
 75     
 76 }
 77 
 78 
 79 void particleSysclass::Killparticle()
 80 {
 81 }
 82 
 83 
 84 void particleSysclass::Updatebuffer(ID3D11DeviceContext* context)
 85 {
 86     HRESULT hr = S_OK;
 87 
 88     memset(m_vertexarray, 0, sizeof(vertex)*m_particlecountMAX*6);
 89     for (int i = 0; i < m_particlecountMAX; i++)
 90     {
 91         m_vertexarray[i * 6].pos.x = m_particlearray[i].pos.x - m_particlearray[i].size;
 92         m_vertexarray[i * 6].pos.y = m_particlearray[i].pos.y - m_particlearray[i].size;
 93         m_vertexarray[i * 6].pos.z = m_particlearray[i].pos.z;
 94         m_vertexarray[i * 6].tex.x = 0;
 95         m_vertexarray[i * 6].tex.y = 1;
 96 
 97         m_vertexarray[i * 6 + 1].pos.x = m_particlearray[i].pos.x - m_particlearray[i].size;
 98         m_vertexarray[i * 6 + 1].pos.y = m_particlearray[i].pos.y + m_particlearray[i].size;
 99         m_vertexarray[i * 6 + 1].pos.z = m_particlearray[i].pos.z;
100         m_vertexarray[i * 6 + 1].tex.x = 0;
101         m_vertexarray[i * 6 + 1].tex.y = 0;
102 
103         m_vertexarray[i * 6 + 2].pos.x = m_particlearray[i].pos.x + m_particlearray[i].size;
104         m_vertexarray[i * 6 + 2].pos.y = m_particlearray[i].pos.y - m_particlearray[i].size;
105         m_vertexarray[i * 6 + 2].pos.z = m_particlearray[i].pos.z;
106         m_vertexarray[i * 6 + 2].tex.x = 1;
107         m_vertexarray[i * 6 + 2].tex.y = 1;
108 
109         m_vertexarray[i * 6 + 3].pos.x = m_particlearray[i].pos.x - m_particlearray[i].size;
110         m_vertexarray[i * 6 + 3].pos.y = m_particlearray[i].pos.y + m_particlearray[i].size;
111         m_vertexarray[i * 6 + 3].pos.z = m_particlearray[i].pos.z;
112         m_vertexarray[i * 6 + 3].tex.x = 0;
113         m_vertexarray[i * 6 + 3].tex.y = 0;
114 
115         m_vertexarray[i * 6 + 4].pos.x = m_particlearray[i].pos.x + m_particlearray[i].size;
116         m_vertexarray[i * 6 + 4].pos.y = m_particlearray[i].pos.y + m_particlearray[i].size;
117         m_vertexarray[i * 6 + 4].pos.z = m_particlearray[i].pos.z;
118         m_vertexarray[i * 6 + 4].tex.x = 1;
119         m_vertexarray[i * 6 + 4].tex.y = 0;
120 
121         m_vertexarray[i * 6 + 5].pos.x = m_particlearray[i].pos.x + m_particlearray[i].size;
122         m_vertexarray[i * 6 + 5].pos.y = m_particlearray[i].pos.y - m_particlearray[i].size;
123         m_vertexarray[i * 6 + 5].pos.z = m_particlearray[i].pos.z;
124         m_vertexarray[i * 6 + 5].tex.x = 1;
125         m_vertexarray[i * 6 + 5].tex.y = 1;
126     }
127 
128     D3D11_MAPPED_SUBRESOURCE mappedResource;
129 
130     hr = context->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
131     if (FAILED(hr))
132     {
133         return;
134     }
135 
136     vertex* verticesPtr = (vertex*)mappedResource.pData;
137 
138     memcpy(verticesPtr, (void*)m_vertexarray, (sizeof(vertex)* m_vertexCount));
139 
140     context->Unmap(m_vertexBuffer, 0);
141 }
142 
143 
144 void particleSysclass::ChangeparticlePos()
145 {
146     
147     for (int i = 0; i < m_particlecountMAX; i++)
148     {
149         static bool flag = true;
150         if (m_particlearray[i].pos.y < -5)
151         {
152             flag = true;
153         }
154         if (m_particlearray[i].pos.y > 5)
155         {
156             flag = false;
157         }        
158         if (flag)
159         {
160             m_particlearray[i].pos.y += 0.0001;
161         }
162         else
163         {
164             m_particlearray[i].pos.y -= 0.0001;
165         }
166     }
167 }
168 
169 
170 void particleSysclass::Render(ID3D11DeviceContext* context, XMMATRIX& viewmatrix, XMMATRIX& pro,
171     ID3D11VertexShader* vertexshader, ID3D11PixelShader* pixelshader)
172 {
173 
174     Killparticle();
175 
176     Emitparticle();    
177 
178     Updatebuffer(context);
179 
180     ChangeparticlePos();
181 
182     UINT stride = sizeof(vertex);
183     UINT offset = 0;
184     context->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset);
185     context->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0);
186     context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
187 
188     context->VSSetShader(vertexshader, NULL, 0);
189 
190 
191     D3D11_MAPPED_SUBRESOURCE mappedResource;
192     HRESULT hr = S_OK;
193 
194     hr = context->Map(m_constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
195     if (FAILED(hr))
196     {
197         return;
198     }    
199     constantBuffer* dataPtr = (constantBuffer*)mappedResource.pData;
200 
201     XMMATRIX worldmatrix = m_worldMatrix;
202     XMMATRIX promatrix = pro;    
203     dataPtr->world = XMMatrixTranspose(worldmatrix);
204     dataPtr->view = XMMatrixTranspose(viewmatrix);
205     dataPtr->pro = XMMatrixTranspose(promatrix);
206 
207     context->Unmap(m_constantBuffer, 0);
208 
209 
210     context->VSSetConstantBuffers(0, 1, &m_constantBuffer);
211     context->PSSetShader(pixelshader, NULL, 0);
212     context->PSSetShaderResources(0, 1, &m_texture);
213     context->PSSetSamplers(0, 1, &m_samplerstate);
214     context->DrawIndexed(m_vertexCount, 0, 0);    
215 }
216 
217 
218 bool particleSysclass::Initbuffer(ID3D11Device* device)
219 {
220     m_vertexCount = m_indexCount = m_particlecountMAX * 6;
221 
222     m_vertexarray = new vertex[m_vertexCount];
223 
224     WORD *indices = new WORD[m_indexCount];
225     for (int i = 0; i < m_indexCount; i++)
226     {
227         indices[i] = i;
228     }
229 
230     D3D11_BUFFER_DESC vertexbd, indexbd, constantbd;
231     D3D11_SUBRESOURCE_DATA vertexdata, indexdata;
232     HRESULT hr = S_OK;
233 
234     vertexbd.Usage = D3D11_USAGE_DYNAMIC;
235     vertexbd.ByteWidth = sizeof(vertex)* m_vertexCount;
236     vertexbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
237     vertexbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
238     vertexbd.MiscFlags = 0;
239     vertexbd.StructureByteStride = 0;
240 
241     vertexdata.pSysMem = m_vertexarray;
242     vertexdata.SysMemPitch = 0;
243     vertexdata.SysMemSlicePitch = 0;
244 
245     hr = device->CreateBuffer(&vertexbd, &vertexdata, &m_vertexBuffer);
246     if (FAILED(hr))
247     {
248         return false;
249     }
250 
251     indexbd.Usage = D3D11_USAGE_DEFAULT;
252     indexbd.ByteWidth = sizeof(WORD)* m_indexCount;
253     indexbd.BindFlags = D3D11_BIND_INDEX_BUFFER;
254     indexbd.CPUAccessFlags = 0;
255     indexbd.MiscFlags = 0;
256     indexbd.StructureByteStride = 0;
257 
258     indexdata.pSysMem = indices;
259     indexdata.SysMemPitch = 0;
260     indexdata.SysMemSlicePitch = 0;
261 
262     hr = device->CreateBuffer(&indexbd, &indexdata, &m_indexBuffer);
263     if (FAILED(hr))
264     {
265         return false;
266     }
267 
268     constantbd.Usage = D3D11_USAGE_DYNAMIC;
269     constantbd.ByteWidth = sizeof(constantBuffer);
270     constantbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
271     constantbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
272     constantbd.MiscFlags = 0;
273     constantbd.StructureByteStride = 0;    
274     hr = device->CreateBuffer(&constantbd, NULL, &m_constantBuffer);    
275     if (FAILED(hr))
276     {
277         return false;
278     }
279 
280     D3D11_SAMPLER_DESC sampDesc;
281     ZeroMemory(&sampDesc, sizeof(sampDesc));
282     sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
283     sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
284     sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
285     sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
286     sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
287     sampDesc.MinLOD = 0;
288     sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
289     device->CreateSamplerState(&sampDesc, &m_samplerstate);
290 
291     delete[] indices;
292     indices = 0;
293 
294     return false;
295 }
296 
297 
298 void particleSysclass::Loadtexture(ID3D11Device*device, LPCWSTR texture)
299 {
300     D3DX11CreateShaderResourceViewFromFile(device, texture, NULL, NULL, &m_texture, NULL);
301 }

Initialize():  与前不同,这里创建缓存的工作交给了私有方法Initbuffer(),从参数获得最大粒子数量,创建并随机给他们设置位置和大小

Emitparticle(),Killparticle():偷懒还没写、、

Updatebuffer():根据粒子位置,粒子大小更改顶点的位置纹理坐标,更改好后再更新到顶点缓存里

ChangeparticlePos():更改粒子位置,即使粒子做运动,对每个粒子做位置判断,使之在-5<y<5的范围内移动,如果到了边界就往回移动

Render():渲染,与之前的model类的渲染函数类似

  • 产生粒子
  • 杀死粒子
  • 更改顶点缓存
  • 更改粒子位置
  • 设置顶点缓存
  • 设置索引缓存
  • 设置绘制方式
  • 设置顶点着色器
  • 更改常量缓存,这里需要使用动态的更改方式
  • 设置常量缓存
  • 设置像素着色器
  • 设置纹理源
  • 设置取样器取样方式
  • 绘制各个顶点

Initbuffer():其实这才是与之前model类最为不一样的地方,他创建的顶点缓存,常量缓存都是动态的

  • 填充顶点描述结构,usage字段设置为D3D11_USAGE_DYNAMIC,CPUAccessFlags字段设置为D3D11_CPU_ACCESS_WRITE,创建顶点缓存
  • 填充索引描述结构,创建索引缓存
  • 填充常量缓存描述结构,usage字段设置为D3D11_USAGE_DYNAMIC,CPUAccessFlags字段设置为D3D11_CPU_ACCESS_WRITE,创建常量缓存
  • 填充取样器描述,创建取样器状态。

这就是粒子系统的实现方式了,总的来说是根据1个粒子位置设置6个顶点(两个三角形)位置,更新顶点缓存,再像渲染模型一样渲染就好了。我们其实也很容易想到,粒子就是微小的、结构更加简单、数量更为庞大的模型。不过虽说如此,要实现非常漂亮的图形学程序,还是需要对高级着色语言,directx的各种功能做深入的了解。

 

以上是关于C++小项目:directx11图形程序:particleSysclass的主要内容,如果未能解决你的问题,请参考以下文章

C++小项目:directx11图形程序:particleSysclass

Directx11 项目将不显示图形输出

如何确保 DirectX 11 应用程序在带有 C++ 的双 GPU 笔记本电脑上使用独立 GPU?

Visual Studio图形调试器详细使用教程(基于DirectX11)

Part2 数据类型与流程控制

vs2017新建DirectX11项目