8.10 地形纹理演示程序

在本例中,我们要为地形和水体添加纹理。首先,我们要在地形上平铺一幅草地纹理。 由于地形网格很大,如果我们直接拉伸纹理,那么每个三角形只能得到很少的几个纹理元素。换句话说,这里无法为表面提供足够高的纹理分辨率;我们会受到倍增问题的影响。所以,我们要在地面网格上平铺草地纹理,进而获得较高的分辨率。其次,我们要通过一个时间函数对水体纹理进行平移,使水体显得更真实一些。图8.15是该演示程序的屏幕截图。

图8.15
图8.15 地形纹理演示程序的屏幕截图。

8.10.1 生成网格纹理坐标

图8.16是一个建立在xz平面上的m×n网格以及一个在规范化纹理空间[0,1]2中的对应网格。可以看到,xz平面上的第ij个网格顶点的纹理坐标对应于纹理空间中的第ij个网格顶点的坐标。第ij个顶点对应的纹理空间坐标为:

uij = j ∙ ∆u

vij = i ∙ ∆v

其中,∆u = 1/(n-1) ,∆v = 1/(m-1) 。

图8.16
图8.16 空间中的网格顶点vij的纹理坐标等于uv空间中的第ij个网格顶点Tij的坐标。

因此,我们可以使用如下代码为地面网格生成纹理坐标:

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);

			// 在网格上拉伸纹理
			meshData.Vertices[i*n+j].TexC.x = j*du;
			meshData.Vertices[i*n+j].TexC.y = i*dv;
		}
	}
 
    …
}

8.10.2 纹理平铺

前面提到,我们希望在地形网格上平铺一幅草地纹理。但是,目前计算出来的纹理坐标是在单位区间[0,1]2中的,无法产生平铺。所以,我们要指定重复寻址模式并通过一个纹理变换矩阵将纹理坐标扩大5倍。这样,纹理坐标会被映射到[0,5]2区间内,使纹理在地形网格表面平铺5×5次:

XMMATRIX grassTexScale = XMMatrixScaling(5.0f, 5.0f, 0.0f);
XMStoreFloat4x4(&mGrassTexTransform, grassTexScale);
…
Effects::BasicFX->SetTexTransform(XMLoadFloat4x4(&mGrassTexTransform));
…
activeTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
md3dImmediateContext->DrawIndexed(mLandIndexCount, 0, 0);

8.10.3 纹理动画

我们要通过一个位于UpdateScene方法中的时间函数在纹理空间中平移纹理坐标,使水体纹理在网格上移动。我们为每帧提供一个很小的位移量,以得到一个平滑动画。我们同时使用无缝纹理和重复寻址模式,以使纹理坐标在平移时不出现间断。下面的代码示范了如何为水体纹理计算位移量,并生成和设定水体的纹理矩阵:

// 平铺水面纹理
XMMATRIX wavesScale = XMMatrixScaling(5.0f, 5.0f, 0.0f);

// 根据时间平移纹理
mWaterTexOffset.y += 0.05f*dt;
mWaterTexOffset.x += 0.1f*dt;	
XMMATRIX wavesOffset = XMMatrixTranslation(mWaterTexOffset.x, mWaterTexOffset.y, 0.0f);

// 组合缩放和平移
XMStoreFloat4x4(&mWaterTexTransform, wavesScale*wavesOffset);
…
Effects::BasicFX->SetTexTransform(XMLoadFloat4x4(&mWaterTexTransform));
…
activeTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
文件下载(已下载 677 次)

发布时间:2014/8/9 下午3:54:32  阅读次数:4730

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号