DirectX11编程5 渲染动态顶点

环境:VS2017  语言:C++

 

总起:

第六章剩下的Demo差别不是很大,基本没什么新的知识点,不过我都将其实现了,今天就专门针对Waves这个Demo说一些特别的东西。

 

工程在此:https://github.com/anguangzhihen/Dx11

 

如果遇到工程不能运行的情况,请留言,我会尽快查明原因。

 

Waves Deme

该Demo主要是实现了一个动态的顶点变化,以模拟出水波的效果。

 

如果有一些Shader基础的同学,可能会想到Shader中有顶点动画,没错,跟这个类似,但是Shader中的顶点动画是在Shader中处理的,而这边的动态顶点渲染是CPU处理好再传到GPU中的。

 

我们先来看一下效果:

 

因为我们还没有学习光影,所以使用的是线框模式,不然估计很难看清。

 

所以我们先来说一下线框模式的设置:

// 申明光栅化阶段状态变量
ID3D11RasterizerState* mWireframeRS;

// 初始化,创建光栅化阶段的描述
D3D11_RASTERIZER_DESC wireframeDesc;
ZeroMemory(&wireframeDesc, sizeof(D3D11_RASTERIZER_DESC));
wireframeDesc.FillMode = D3D11_FILL_WIREFRAME;
wireframeDesc.CullMode = D3D11_CULL_BACK;
wireframeDesc.FrontCounterClockwise = false;
wireframeDesc.DepthClipEnable = true;

// 创建线框模式
HR(md3dDevice->CreateRasterizerState(&wireframeDesc, &mWireframeRS));

// 设置为线框模式,该方法需要在每帧ClearRT之后执行
md3dImmediateContext->RSSetState(mWireframeRS);

 

通常来说Dx是一个状态机,它会随着我们设置的状态的变化而变化。

 

ID3D11RasterizerState便是代表了在光栅化阶段的一个状态机集合。

 

D3D11_RASTERIZER_DESC便是这个状态的描述,以下是描述中各个参数的含义:

FillMode 填充模式,可以选择D3D11_FILL_WIREFRAME线框模式、D3D11_FILL_SOLID实体模式,默认为实体模式。线框模式就是文章一开始给出的效果。

 

CullMode 剪裁模式:

1. D3D11_CULL_NONE 禁用剪裁;

2. D3D11_CULL_BACK 剪裁背面的三角形(默认);

3. D3D11_CULL_FRONT 剪裁正面的三角形。

 

FrontCounterClockwise bool形,false为顺时针可见(默认),true为逆时针。

 

DepthClipEnable 是否启用深度剪裁。

 

了解了线框模式之后,我们来了解一下如何做到顶点动态移动(这里用到了一个Waves类用来计算当前顶点的位置,具体实现请参见代码,这边不展开叙述)。

 

首先是创建顶点缓存:

// 创建CPU可写的缓存
D3D11_BUFFER_DESC vbd;
ZeroMemory(&vbd, sizeof(vbd));
vbd.Usage = D3D11_USAGE_DYNAMIC;	// 指定缓存为动态的
vbd.ByteWidth = sizeof(Vertex) * mWaves.VertexCount();
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;	// 指定CPU可写
HR(md3dDevice->CreateBuffer(&vbd, 0, &mWaveVB));

 

接着是在Update中动态设置顶点:

// 每0.25秒更新产生一次波纹
static float t_base = 0.0f;
if ((mTimer.TotalTime() - t_base) >= 0.25f)
{
	t_base += 0.25f;
	DWORD i = 5 + rand() % 190;
	DWORD j = 5 + rand() % 190;
	float r = MathHelper::RandF(1.0f, 2.0f);
	mWaves.Disturb(i, j, r);
}

// 每帧更新Wave
mWaves.Update(dt);

// 创建mappedData用以设置顶点信息
D3D11_MAPPED_SUBRESOURCE mappedData;
HR(md3dImmediateContext->Map(mWaveVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedData));

// 更新顶点信息
Vertex* v = reinterpret_cast<Vertex*>(mappedData.pData);
UINT length = mWaves.VertexCount();
for (UINT i = 0; i < length; i++)
{
	v[i].Pos = mWaves[i];
	v[i].Color = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
}

// 将新的顶点信息进行设置
md3dImmediateContext->Unmap(mWaveVB, 0);

 

接下来说一下ID3D11DeviceContext::Map函数中参数的含义:

pResource 我们想要访问的资源,可以是Dx11的buffer或者图片等。

 

Subresource 子资源的编号。

 

MapType 通用标志位:

1. D3D11_MAP_WRITE_DISCARD, 告诉硬件舍弃当前的内存,返回一块新的内存,以防止继续渲染老的顶点数据;

2. D3D11_MAP_WRITE_NO_OVERWRITE, 告诉硬件我们只写入没有初始化的数据。

 

pMappedResource 返回的一个D3D11_MAPPED_SUBRESOURCE指针,用于读写内存。

 

使用返回出来的指针更新顶点之后,一定要用ID3D11DeviceContext::Unmap来更新顶点数据。

 

最后再强调一下,这种方式在CPU和GPU之间互相传传递了数据,所以效率比较低,如果能使用顶点Shader、几何Shader等GPU的方式实现动态效果的话,尽量使用GPU的方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值