地形水波紋理示例Demo
1. 地形水波紋理示例Demo介紹
在本例中,我們要為地形和水體添加紋理。首先,我們要在地形上平鋪一幅草地紋理。 由于地形網格很大,如果我們直接拉伸紋理,那麼每個三角形隻能得到很少的幾個紋理元素。換句話說,這裡無法為表面提供足夠高的紋理分辨率;我們會受到倍增問題的影響。是以,我們要在地面網格上平鋪草地紋理,進而獲得較高的分辨率。其次,我們要通過一個時間函數對水體紋理進行平移,使水體顯得更真實一些。
2. 生成網格紋理坐标
圖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) 。
(空間中的網格頂點vij的紋理坐标等于uv空間中的第ij個網格頂點Tij的坐标。)
是以,我們可以使用如下代碼為地面網格生成紋理坐标:
void GeometryGenerator::CreateGrid(float width, float depth, UINT m, UINT n, MeshData& meshData)
{
UINT vertexCount = m*n;
UINT faceCount = (m-)*(n-)*;
//
// 建立頂點
//
float halfWidth = *width;
float halfDepth = *depth;
float dx = width / (n-);
float dz = depth / (m-);
float du = / (n-);
float dv = / (m-);
meshData.Vertices.resize(vertexCount);
for(UINT i = ; i < m; ++i)
{
float z = halfDepth - i*dz;
for(UINT j = ; j < n; ++j)
{
float x = -halfWidth + j*dx;
meshData.Vertices[i*n+j].Position = XMFLOAT3(x, , z);
meshData.Vertices[i*n+j].Normal = XMFLOAT3(, , );
meshData.Vertices[i*n+j].TangentU = XMFLOAT3(, , );
// 在網格上拉伸紋理
meshData.Vertices[i*n+j].TexC.x = j*du;
meshData.Vertices[i*n+j].TexC.y = i*dv;
}
}
…
}
3. 紋理平鋪
前面提到,我們希望在地形網格上平鋪一幅草地紋理。但是,目前計算出來的紋理坐标是在機關區間[0,1]2中的,無法産生平鋪。是以,我們要指定重複尋址模式并通過一個紋理變換矩陣将紋理坐标擴大5倍。這樣,紋理坐标會被映射到[0,5]2區間内,使紋理在地形網格表面平鋪5×5次:
XMMATRIX grassTexScale = XMMatrixScaling(f, f, f);
XMStoreFloat4x4(&mGrassTexTransform, grassTexScale);
…
Effects::BasicFX->SetTexTransform(XMLoadFloat4x4(&mGrassTexTransform));
…
activeTech->GetPassByIndex(p)->Apply(, md3dImmediateContext);
md3dImmediateContext->DrawIndexed(mLandIndexCount, , );
4. 紋理動畫
我們要通過一個位于UpdateScene方法中的時間函數在紋理空間中平移紋理坐标,使水體紋理在網格上移動。我們為每幀提供一個很小的位移量,以得到一個平滑動畫。我們同時使用無縫紋理和重複尋址模式,以使紋理坐标在平移時不出現間斷。下面的代碼示範了如何為水體紋理計算位移量,并生成和設定水體的紋理矩陣:
// 平鋪水面紋理
XMMATRIX wavesScale = XMMatrixScaling(, , );
// 根據時間平移紋理
mWaterTexOffset.y += *dt;
mWaterTexOffset.x += *dt;
XMMATRIX wavesOffset = XMMatrixTranslation(mWaterTexOffset.x, mWaterTexOffset.y, );
// 組合縮放和平移
XMStoreFloat4x4(&mWaterTexTransform, wavesScale*wavesOffset);
…
Effects::BasicFX->SetTexTransform(XMLoadFloat4x4(&mWaterTexTransform));
…
activeTech->GetPassByIndex(p)->Apply(, md3dImmediateContext);
5. 程式運作結果截圖
項目完整源代碼請到DirectX11 龍書官網下載下傳。