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的各种功能做深入的了解。

时间: 2024-08-25 08:25:58

C++小项目:directx11图形程序(八):particleSysclass的相关文章

C++小项目:directx11图形程序(九):总结

整篇文章中对于directx11的知识的介绍并不多,我也不知道怎么介绍,也应该说对于directx,它有它自己的部分,比如设备(device),设备上下文(devicecontext),顶点缓存,索引缓存之类,也有图形学的部分比如世界矩阵,观察矩阵,投影矩阵,三角形渲染,光照,混合.要将这里涉及的api的功能,参数,对象一一说明,非常难.要将图形学里世界矩阵,观察矩阵,投影矩阵的推理,为什么选择渲染三角形而不是渲染四边形五边形这些一一明说,更不易(这个内容是我自己根据<3d游戏大师编程技巧>然

C++小项目:directx11图形程序(六):cameraclass

cameraclass是一个相机类,它的作用是生成非常重要的观察矩阵.本小节涉及到一点数学知识,相对前面需要只是填充,调用,算是比较有趣的吧. cameraclass.h 1 #pragma once 2 #include <d3d11.h> 3 #include <d3dcompiler.h> 4 #include <D3DX11.h> 5 #include <xnamath.h> 6 7 #pragma comment(lib,"d3dx11.

Android开发不得不看的11个实战小项目

是不是想学Android开发(http://www.maiziedu.com/course/android-px/)却不知道如何下手?懂得一点点入门基础知识却无法应用到实际开发中?看相关资料觉得都懂了实际动手却发现什么都不懂?本地搭建Android开发环境太麻烦? 如果你有以上的各种问题,那么今天小编推荐的Android开发的这11个小项目,你一定要看!! 因为,这些实战项目都是基于google 官方的API Demos制作而成,而且全部配有Android在线开发环境,你可以随时动手跟着课程操作

模拟XShell的小项目

不知道大家有没有用过XShell这款工具,这款工具通过windows可以远程操作处于开机状态的linux操作系统,也就是说把你的电脑和一台服务器连入网络,你通过输入服务器所在的IP地址建立一个会话就可以远端操作linux的服务器了,十分方便. 这次这个模拟XShell的小项目就是类似的功能 执行流程: windows客户端输入命令,通过网络传输到linux服务器端上,linux服务器端执行命令,将执行命令产生的结果保存进文件,然后再将文件传输回windows客户端进行展示. 问题思考:真的有必要

小项目特供 贪吃蛇游戏(基于C语言)

C语言写贪吃蛇本来是打算去年暑假写的,结果因为ACM集训给耽搁了,因此借寒假的两天功夫写了这个贪吃蛇小项目,顺带把C语言重温了一次. 是发表博客的前一天开始写的,一共写了三个版本,第一天写了第一版,第二天写了第二版和第三版. 相信C语言写个小游戏或小项目是大多数计算机相关专业的学生都做的事情,但是作为一个数学专业的学生,我们教研室的老师对C语言的要求也就比较低了,大一没有让我们做个小项目实践一次.至今为止用C/C++做过的三个小项目(大作业),一个是外校同学让我帮忙写的学生信息管理系统(天呐,这

小项目创意大集合

每个程序员都可以入手的小项目创意大集合 我经常看有人发帖问关于软件项目创意点子的事,也看到了很多回帖,我自己也回了一些常见的软件项目创意.不过我觉得只列出三两个是远远不够的,因此就收集并这个软件项目创意列表,大家要找简单的编程软件项目创意学习练手的话,可以收藏并扩散本文.这些软件项目创意并不是论文级别的,只是想抛砖引玉让大家能从中受些启发. 下面你们会看到 120 多个个软件项目创意想法,都是我通过头脑风暴得来的.我将其根据主题分成了10 个分类,但有些软件项目创意其实涵盖了不止一个主题. 更新

必知的11个android开发实战小项目

是不是想学Android开发(http://www.maiziedu.com/course/android-px/)却不知道如何下手?懂得一点点入门基础知识却无法应用到实际开发中?看相关资料觉得都懂了实际动手却发现什么都不懂?本地搭建Android开发环境太麻烦? 如果你有以上的各种问题,那么今天小编推荐的Android开发的这11个小项目,你一定要看!! 因为,这些实战项目都是基于google 官方的API Demos制作而成,而且全部配有Android在线开发环境,你可以随时动手跟着课程操作

一个简陋的个人小项目,也是个人第一个真正意义上的独立项目——Graph

由来 我最早接触到图这个概念是在大二的离散数学当中图论相关的内容,当时是以著名的哥尼斯堡七桥问题引出图论的概念,现在依然记忆犹新(不过只是记得这个名字,具体的解题思路我重新温习了一下才想起来),当时也提出了求最短路径的迪杰斯特拉算法,不过没有用编程语言具体实现. 之后在数据结构的学习中,又出现了图的相关知识,提出了在计算机中存储图的几种方式,我们学校的课程中学习的是邻接表和邻接矩阵,同时也用编程语言实现了具体的算法. 离散数学中的图用几何图形表示,清晰明了,但实现算法时步骤不清晰:邻接矩阵和邻接

java小项目之:扫雷,这游戏其实没有那么简单!

扫雷我之前分享的小项目和小游戏,电影购票.坦克大战.捕鱼达人.贪吃蛇等,虽然已经是耳熟能详人尽皆知的项目和游戏,但是保不齐真的有人没接触过.今天分享的这个项目,我不相信没人接触过(仅限80后-00后).扫雷,这几乎所有电脑都有的一款超级小游戏,在全国各地的微机课上饱受欢迎,玩法紧张刺激.老少皆宜,而且还益智.今天便分享用java怎么实现这一款神作.(文末附带源码素材获取方式)游戏介绍:扫雷就是要把所有非地雷的格子揭开即胜利:踩到地雷格子就算失败.游戏主区域由很多个方格组成.使用鼠标左键随机点击一