博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DirectX11 地形水波纹理示例Demo
阅读量:4089 次
发布时间:2019-05-25

本文共 2461 字,大约阅读时间需要 8 分钟。

地形水波纹理示例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-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;        }    }    …}

3. 纹理平铺

前面提到,我们希望在地形网格上平铺一幅草地纹理。但是,目前计算出来的纹理坐标是在单位区间[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);

4. 纹理动画

我们要通过一个位于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);

5. 程序运行结果截图

项目完整源代码请到DirectX11 龙书官网下载。

这里写图片描述

这里写图片描述

你可能感兴趣的文章
数据库事务
查看>>
JavaScript基础1:JavaScript 错误 - Throw、Try 和 Catch
查看>>
SQL基础总结——20150730
查看>>
SQL join
查看>>
JavaScript实现页面无刷新让时间走动
查看>>
CSS实例:Tab选项卡效果
查看>>
前端设计之特效表单
查看>>
前端设计之CSS布局:上中下三栏自适应高度CSS布局
查看>>
Java的时间操作玩法实例若干
查看>>
JavaScript:时间日期格式验证大全
查看>>
pinyin4j:拼音与汉字的转换实例
查看>>
XML工具代码:SAX从String字符串XML内获取指定节点或属性的值
查看>>
时间日期:获取两个日期相差几天
查看>>
责任链模式 Chain of Responsibility
查看>>
高并发与大数据解决方案概述
查看>>
解决SimpleDateFormat线程安全问题NumberFormatException: multiple points
查看>>
MySQL数据库存储引擎简介
查看>>
处理Maven本地仓库.lastUpdated文件
查看>>
Kafka | 请求是怎么被处理的?
查看>>
Java并发编程1-线程池
查看>>