DirectX11编程4 渲染山地

环境:VS2017  语言:C++

 

总起:

红龙书的第六章Demo练习很多,我们一个个来。

 

工程,X_Jun96大佬建议放到Github上,现在的地址:https://github.com/anguangzhihen/Dx11

 

上一篇的基础来做渲染山地的Demo还是比较轻松的,山地或者水之类的东西实际上就是一个面片,使用顶点构建出面片之后,赋值高低的y坐标基本就完成了。Buffer绑定、Shader和上一章一模一样。

 

渲染山地:

首先来看看效果:

 

似乎比盒子的Demo进步了一大截,但并没有,只是顶点数量变多了,“模型”更加精细了而已。

 

构建面片的工作由GeometryGenerator类的CreateGrid方法完成:

void GeometryGenerator::CreateGrid(float width, float depth, UINT m, UINT n, MeshData& meshData) 
{
	UINT vertexCount = m * n;	// 顶点数量
	UINT faceCount = (m - 1)*(n - 1) * 2;	// 三角数量

	float halfWidth = 0.5f*width;
	float halfDepth = 0.5f*depth;

	// 计算一格的宽高
	float dx = width / (n - 1);
	float dz = depth / (m - 1);

	float du = 1.0f / (n - 1);
	float dv = 1.0f / (m - 1);

	// 创建顶点
	meshData.Vertices.resize(vertexCount);
	for (UINT i = 0; i < m; ++i)
	{
		float z = halfDepth - i * dz;
		for (UINT j = 0; j < n; ++j)
		{
			float x = -halfWidth + j * dx;
			meshData.Vertices[i * n + j].Position = XMFLOAT3(x, 0.0f, z);	// 顶点的位置
			meshData.Vertices[i * n + j].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f);
			meshData.Vertices[i * n + j].TangentU = XMFLOAT3(1.0f, 0.0f, 0.0f);

			// 当前点与00点的xy距离
			meshData.Vertices[i*n + j].TexC.x = j * du;
			meshData.Vertices[i*n + j].TexC.y = i * dv;
		}
	}

	// 创建索引
	meshData.Indices.resize(faceCount * 3);
	UINT k = 0;
	for (UINT i = 0; i < m - 1; ++i)
	{
		for (UINT j = 0; j < n - 1; ++j) 
		{
			// 一个Quad
			meshData.Indices[k] = i * n + j;
			meshData.Indices[k + 1] = i * n + j + 1;
			meshData.Indices[k + 2] = (i + 1) * n + j;

			meshData.Indices[k + 3] = (i + 1) * n + j;
			meshData.Indices[k + 4] = i * n + j + 1;
			meshData.Indices[k + 5] = (i + 1) * n + j + 1;

			k += 6;
		}
	}
}

 

现在一个顶点数据Vertex由Position位置、Normal法线坐标、TangentU切线、TexC纹理坐标组成,该Demo中只用到了Position。

 

而Vertex的集合与索引数据统称为Mesh,这边的数据结构便是MeshData。

 

有了面片的数据,接下来就是赋值高度和添加颜色了:

// HillsDemo::BuildGeometryBuffers方法
GeometryGenerator::MeshData grid;
GeometryGenerator::CreateGrid(160.f, 160.0f, 50, 50, grid);	// 创建160x160大小的格子数为49的Mesh

mGridIndexCount = grid.Indices.size();

// 提取每个顶点
std::vector<Vertex> vertices(grid.Vertices.size());
for (size_t i = 0; i < grid.Vertices.size(); i++)
{
	// 这边只用到Position信息,所以不对其他信息做处理(等到使用光照模型时会使用法线等信息)
	XMFLOAT3 p = grid.Vertices[i].Position;
	p.y = GetHeight(p.x, p.z);	// 赋值高度
	vertices[i].Pos = p;

	// 以不同的颜色表示沙滩、山地、山峰(不同的高度对应不同的颜色)
	if (p.y < -10.f)
	{
		// 沙滩的颜色
		vertices[i].Color = XMFLOAT4(1.0f, 0.96f, 0.62f, 1.0f);
	}
	else if (p.y < 5.0f)
	{
		// 黄绿色
		vertices[i].Color = XMFLOAT4(0.48f, 0.77f, 0.46f, 1.0f);
	}
	else if (p.y < 12.0f)
	{
		// 深黄绿色
		vertices[i].Color = XMFLOAT4(0.1f, 0.48f, 0.19f, 1.0f);
	}
	else if (p.y < 20.0f)
	{
		// 深棕色
		vertices[i].Color = XMFLOAT4(0.45f, 0.39f, 0.34f, 1.0f);
	}
	else
	{
		// 白色
		vertices[i].Color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
	}
}

 

GetHeight的内容如下:

// 根据x、z坐标获取高度
float HillsDemo::GetHeight(float x, float z) const
{
	return 0.3f*(z*sinf(0.1f*x) + x * cosf(0.1f*z));
}

 

如果你愿意的话,可以做一张高度图,读取高度图的信息对y坐标进行赋值。

 

以上就是全部内容了。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值