C++小项目:directx11图形程序(八):particleSysclass
粒子系统类,粒子系统是游戏里细小元素的控制系统,虽然感觉上它对游戏的影响不大,但是其实有了它能给游戏增色不少。粒子系统控制着细小元素的生死,运动,纹理。对它的编写让我知道,游戏里的这一片从天空飘落的雪花其实是之前那一朵已经融化在地上的雪花。
这个类我还没有编写完整,因为我发现如果要真正实现那种很美的效果我还要多加学习啊。使用广告版技术让人觉得它真的是个粒子,开启alpha通道能让粒子与背景融为一体,开启光照能让粒子煜煜生辉,给纹理混合上颜色才能让粒子真正的变幻幻幻(不是打错字)起来。
particleSysclass.h
#pragma once
#include <d3d11.h>
#include <d3dcompiler.h>
#include <D3DX11.h>
#include <xnamath.h>
#include<time.h>
#pragma comment(lib,"d3dx11.lib")
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"d3dcompiler.lib")
class particleSysclass
{
public:
particleSysclass();
~particleSysclass(); private:
ID3D11ShaderResourceView* m_texture;
struct vertex
{
XMFLOAT3 pos;
XMFLOAT2 tex;
};
struct particle
{
XMFLOAT3 pos;
float size;
bool alive;
};
struct constantBuffer
{
XMMATRIX world;
XMMATRIX view;
XMMATRIX pro;
}; vertex *m_vertexarray;
particle *m_particlearray;
int m_particlecountMAX;
int m_particlecountCUR;
XMFLOAT3 m_sourcepos; ID3D11Buffer *m_vertexBuffer, *m_indexBuffer;
ID3D11Buffer *m_constantBuffer;
int m_vertexCount, m_indexCount;
ID3D11SamplerState *m_samplerstate;
XMMATRIX m_worldMatrix; public:
bool Initialize(ID3D11Device* device, LPCWSTR texture, int maxcount);
void Render(ID3D11DeviceContext* context, XMMATRIX& viewmatrix, XMMATRIX& pro,
ID3D11VertexShader* vertexshader, ID3D11PixelShader* pixelshader);
void Shutdown(); private:
void Emitparticle();
void Killparticle();
void Updatebuffer(ID3D11DeviceContext* context);
void ChangeparticlePos();
bool Initbuffer(ID3D11Device* device);
void Loadtexture(ID3D11Device* device,LPCWSTR texture);
};
可以看到,粒子系统类与之前的模型类非常相像只是多了:
- 粒子数据结构,粒子数组指针,粒子最大数量,粒子当前数量(m_particlecountCUR)
- 私有方法:生成粒子,粒子湮灭,更新缓存,改变例子位置(运动),初始化缓存
particleSysclass.cpp
#include "particleSysclass.h" particleSysclass::particleSysclass()
{
m_worldMatrix = XMMatrixIdentity();
} particleSysclass::~particleSysclass()
{
} bool particleSysclass::Initialize(ID3D11Device* device, LPCWSTR texture, int maxcount)
{
m_particlecountMAX = maxcount; Loadtexture(device,texture); Initbuffer(device); m_particlearray = new particle[m_particlecountMAX]; srand((unsigned)time(NULL));
for (int i = ; i < m_particlecountMAX; i++)
{
m_particlearray[i].alive = true;
m_particlearray[i].pos.x = (((float)rand() - (float)rand()) / RAND_MAX) * ;
m_particlearray[i].pos.y = (((float)rand() - (float)rand()) / RAND_MAX) * ;
m_particlearray[i].pos.z = (((float)rand() - (float)rand()) / RAND_MAX) * ; m_particlearray[i].size = 0.05;
} return false;
} void particleSysclass::Shutdown()
{
if (m_particlearray)
{
delete m_particlearray;
}
if (m_samplerstate)
{
m_samplerstate->Release();
}
if (m_constantBuffer)
{
m_constantBuffer->Release();
}
if (m_indexBuffer)
{
m_indexBuffer->Release();
}
if (m_vertexBuffer)
{
m_vertexBuffer->Release();
}
if (m_vertexarray)
{
delete[] m_vertexarray;
}
if (m_texture)
{
m_texture->Release();
}
} void particleSysclass::Emitparticle()
{ } void particleSysclass::Killparticle()
{
} void particleSysclass::Updatebuffer(ID3D11DeviceContext* context)
{
HRESULT hr = S_OK; memset(m_vertexarray, , sizeof(vertex)*m_particlecountMAX*);
for (int i = ; i < m_particlecountMAX; i++)
{
m_vertexarray[i * ].pos.x = m_particlearray[i].pos.x - m_particlearray[i].size;
m_vertexarray[i * ].pos.y = m_particlearray[i].pos.y - m_particlearray[i].size;
m_vertexarray[i * ].pos.z = m_particlearray[i].pos.z;
m_vertexarray[i * ].tex.x = ;
m_vertexarray[i * ].tex.y = ; m_vertexarray[i * + ].pos.x = m_particlearray[i].pos.x - m_particlearray[i].size;
m_vertexarray[i * + ].pos.y = m_particlearray[i].pos.y + m_particlearray[i].size;
m_vertexarray[i * + ].pos.z = m_particlearray[i].pos.z;
m_vertexarray[i * + ].tex.x = ;
m_vertexarray[i * + ].tex.y = ; m_vertexarray[i * + ].pos.x = m_particlearray[i].pos.x + m_particlearray[i].size;
m_vertexarray[i * + ].pos.y = m_particlearray[i].pos.y - m_particlearray[i].size;
m_vertexarray[i * + ].pos.z = m_particlearray[i].pos.z;
m_vertexarray[i * + ].tex.x = ;
m_vertexarray[i * + ].tex.y = ; m_vertexarray[i * + ].pos.x = m_particlearray[i].pos.x - m_particlearray[i].size;
m_vertexarray[i * + ].pos.y = m_particlearray[i].pos.y + m_particlearray[i].size;
m_vertexarray[i * + ].pos.z = m_particlearray[i].pos.z;
m_vertexarray[i * + ].tex.x = ;
m_vertexarray[i * + ].tex.y = ; m_vertexarray[i * + ].pos.x = m_particlearray[i].pos.x + m_particlearray[i].size;
m_vertexarray[i * + ].pos.y = m_particlearray[i].pos.y + m_particlearray[i].size;
m_vertexarray[i * + ].pos.z = m_particlearray[i].pos.z;
m_vertexarray[i * + ].tex.x = ;
m_vertexarray[i * + ].tex.y = ; m_vertexarray[i * + ].pos.x = m_particlearray[i].pos.x + m_particlearray[i].size;
m_vertexarray[i * + ].pos.y = m_particlearray[i].pos.y - m_particlearray[i].size;
m_vertexarray[i * + ].pos.z = m_particlearray[i].pos.z;
m_vertexarray[i * + ].tex.x = ;
m_vertexarray[i * + ].tex.y = ;
} D3D11_MAPPED_SUBRESOURCE mappedResource; hr = context->Map(m_vertexBuffer, , D3D11_MAP_WRITE_DISCARD, , &mappedResource);
if (FAILED(hr))
{
return;
} vertex* verticesPtr = (vertex*)mappedResource.pData; memcpy(verticesPtr, (void*)m_vertexarray, (sizeof(vertex)* m_vertexCount)); context->Unmap(m_vertexBuffer, );
} void particleSysclass::ChangeparticlePos()
{ for (int i = ; i < m_particlecountMAX; i++)
{
static bool flag = true;
if (m_particlearray[i].pos.y < -)
{
flag = true;
}
if (m_particlearray[i].pos.y > )
{
flag = false;
}
if (flag)
{
m_particlearray[i].pos.y += 0.0001;
}
else
{
m_particlearray[i].pos.y -= 0.0001;
}
}
} void particleSysclass::Render(ID3D11DeviceContext* context, XMMATRIX& viewmatrix, XMMATRIX& pro,
ID3D11VertexShader* vertexshader, ID3D11PixelShader* pixelshader)
{ Killparticle(); Emitparticle(); Updatebuffer(context); ChangeparticlePos(); UINT stride = sizeof(vertex);
UINT offset = ;
context->IASetVertexBuffers(, , &m_vertexBuffer, &stride, &offset);
context->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, );
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); context->VSSetShader(vertexshader, NULL, ); D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = S_OK; hr = context->Map(m_constantBuffer, , D3D11_MAP_WRITE_DISCARD, , &mappedResource);
if (FAILED(hr))
{
return;
}
constantBuffer* dataPtr = (constantBuffer*)mappedResource.pData; XMMATRIX worldmatrix = m_worldMatrix;
XMMATRIX promatrix = pro;
dataPtr->world = XMMatrixTranspose(worldmatrix);
dataPtr->view = XMMatrixTranspose(viewmatrix);
dataPtr->pro = XMMatrixTranspose(promatrix); context->Unmap(m_constantBuffer, ); context->VSSetConstantBuffers(, , &m_constantBuffer);
context->PSSetShader(pixelshader, NULL, );
context->PSSetShaderResources(, , &m_texture);
context->PSSetSamplers(, , &m_samplerstate);
context->DrawIndexed(m_vertexCount, , );
} bool particleSysclass::Initbuffer(ID3D11Device* device)
{
m_vertexCount = m_indexCount = m_particlecountMAX * ; m_vertexarray = new vertex[m_vertexCount]; WORD *indices = new WORD[m_indexCount];
for (int i = ; i < m_indexCount; i++)
{
indices[i] = i;
} D3D11_BUFFER_DESC vertexbd, indexbd, constantbd;
D3D11_SUBRESOURCE_DATA vertexdata, indexdata;
HRESULT hr = S_OK; vertexbd.Usage = D3D11_USAGE_DYNAMIC;
vertexbd.ByteWidth = sizeof(vertex)* m_vertexCount;
vertexbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
vertexbd.MiscFlags = ;
vertexbd.StructureByteStride = ; vertexdata.pSysMem = m_vertexarray;
vertexdata.SysMemPitch = ;
vertexdata.SysMemSlicePitch = ; hr = device->CreateBuffer(&vertexbd, &vertexdata, &m_vertexBuffer);
if (FAILED(hr))
{
return false;
} indexbd.Usage = D3D11_USAGE_DEFAULT;
indexbd.ByteWidth = sizeof(WORD)* m_indexCount;
indexbd.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexbd.CPUAccessFlags = ;
indexbd.MiscFlags = ;
indexbd.StructureByteStride = ; indexdata.pSysMem = indices;
indexdata.SysMemPitch = ;
indexdata.SysMemSlicePitch = ; hr = device->CreateBuffer(&indexbd, &indexdata, &m_indexBuffer);
if (FAILED(hr))
{
return false;
} constantbd.Usage = D3D11_USAGE_DYNAMIC;
constantbd.ByteWidth = sizeof(constantBuffer);
constantbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constantbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
constantbd.MiscFlags = ;
constantbd.StructureByteStride = ;
hr = device->CreateBuffer(&constantbd, NULL, &m_constantBuffer);
if (FAILED(hr))
{
return false;
} D3D11_SAMPLER_DESC sampDesc;
ZeroMemory(&sampDesc, sizeof(sampDesc));
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
sampDesc.MinLOD = ;
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
device->CreateSamplerState(&sampDesc, &m_samplerstate); delete[] indices;
indices = ; return false;
} void particleSysclass::Loadtexture(ID3D11Device*device, LPCWSTR texture)
{
D3DX11CreateShaderResourceViewFromFile(device, texture, NULL, NULL, &m_texture, NULL);
}
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图形程序(一):主框架
最近在学习DIRECTX11,在学习过程中编写了一个程序,到现在发现这个程序也有几行代码了,结构还算整齐,就想把这个程序分享出来,其中涉及到了C++程序的架构,windows窗口程序编写,和Direc ...
- C++小项目:directx11图形程序(四):d3dclass
主菜终于来了.这个d3dclass主要做的工作是dx11图形程序的初始化工作,它将创建显示表面交换链,d3d设备,d3d设备上下文,渲染目标表面,深度模板缓存:设置视口,生成投影矩阵. D3D设备:可 ...
- C++小项目:directx11图形程序(九):总结
整篇文章中对于directx11的知识的介绍并不多,我也不知道怎么介绍,也应该说对于directx,它有它自己的部分,比如设备(device),设备上下文(devicecontext),顶点缓存,索引 ...
- C++小项目:directx11图形程序(三):graphicsclass
这是框架的第三层graphicsclass,这个类才真正可以说是整个程序的框架,因为它组织了后面所有的成员. 代码: graphicsclass.h #pragma once #include< ...
- C++小项目:directx11图形程序(七):modelclass
模型类是世界空间中的表示物体的类,那么他的所做的事就是加载模型,移动模型,渲染模型 modelclass.h #pragma once #include <d3d11.h> #includ ...
- C++小项目:directx11图形程序(二):systemclass
先上代码: systemclass.h #pragma once #include"graphicsclass.h" const bool FULLSCREEN = true; c ...
- C++小项目:directx11图形程序(六):cameraclass
cameraclass是一个相机类,它的作用是生成非常重要的观察矩阵.本小节涉及到一点数学知识,相对前面需要只是填充,调用,算是比较有趣的吧. cameraclass.h #pragma once # ...
- C++小项目:directx11图形程序(五):shadersclass
这个类是用来创建着色器并设置输入布局的. 这个类比较特殊,它创建的着色器与Effect文件有关,effect文件是用高级着色语言(hlsl)编写的. shadersclass.h #pragma on ...
- Android小项目之七 应用程序的更新安装
------- 源自梦想.永远是你IT事业的好友.只是勇敢地说出我学到! ---------- 按惯例,写在前面的:可能在学习Android的过程中,大家会和我一样,学习过大量的基础知识,很多的知识点 ...
随机推荐
- linkedin开源的kafka-monitor安装文档
linkedin开源的kafka-monitor安装文档 linkedin 开源的kafka-monitor的安装使用可以参考官方的readme:流程介绍的已经比较清楚,但是还是有一些地方需要修正.让 ...
- spark的standlone模式安装和application 提交
spark的standlone模式安装 安装一个standlone模式的spark集群,这里是最基本的安装,并测试一下如何进行任务提交. require:提前安装好jdk 1.7.0_80 :scal ...
- js多个输入框运算计算结果输出到另一个输入框
<div id="ckjrzy_4_14_15"> <div id="ckjrzy_4_14_17">收益计算器 </div& ...
- PHP设计模式
设计模式总的分为三种,创建型模式.结构性模式.行为型模式 1.创建型模式 创建型模式为根据实际情况来创建对象,创建的模式又分为对象创建模式和类创建模式,对象创建模式会把对象创建的一部分在另一个对象中实 ...
- C# 类型转换
int 转换 string 转换有两种: 一种是隐式, ; string b = a.ToString(); 一种是显示. sting b=Convert.ToString();
- centos各版本信息
CentOS version Architectures RHEL base Kernel CentOS release date RHEL release date Delay (days) 2.1 ...
- Security » Authorization » 通过映射限制身份
Limiting identity by scheme¶ 通过映射限制身份(这部分有好几个概念还不清楚,翻译的有问题) 36 of 39 people found this helpful In so ...
- 0.读书笔记之The major advancements in Deep Learning in 2016
The major advancements in Deep Learning in 2016 地址:https://tryolabs.com/blog/2016/12/06/major-advanc ...
- Hibernate连数据库
1.建数据库,建表(一定要设主码) create database Hibernate create table Students( sno char(10) primary key, sna cha ...
- centos下php安装swoole扩展
官网:http://wiki.swoole.com/wiki/index/prid-1 国内Git镜像:http://git.oschina.net/matyhtf/swoole.git 下载源码后, ...