当前位置: 首页 > news >正文

Direct3D地形绘制基础

高度图

用高度图来描述地形中的丘陵和山谷,高度图其实就是一个数组,该数组每个元素都指定了地形方格中某一个特定顶点的高度值。通常将高度图视为一个矩阵,这样高度图中的元素就与地形栅格中的顶点一一对应。

高度图被保存在磁盘中,通常为其每个元素元素只分配一个字节存储空间,这样高度只能在区间
[0,255]内取值,但在实际应用中为了匹配3D世界的尺度,可能需要对高度值进行比例变换,这样就极可能超出上述区间。基于上述原因,当将高度数据加载到应用程序中时,我们重新分配一个整型或浮点型数组来存储这些高度值。

创建高度图

可由编程序生成、可用图像编辑软件来创建,一旦完成高度图的创建,我们需要将其保存为8位的RAW文件。RAW文件仅连续存储了图像中以字节为单位的每个像素的灰度值。这就使得这类文件的读取操作非常容易。您使用的图像编辑软件可能会询问您是否要为RAW文件增加一个文件头,请选择“否”.

加载RAW文件

RAW文件本质上是一个连续的字节存储块,其中将字节型向量复制到一个整型向量中,我们就可对高度值进行比例变换从而突破0~255的限制,该方法的唯一限制是所要读取的RAW文件中包含的字节数至少要与地形中的顶点总数一样多,所以,如果您要从一个256×256的RAW文件中读取数据,相应地您只能创建一个至多有256×256个顶点的地形。

bool Terrain::ReadRawFile(std::string fileName)
{//RAW文件本质上是一个连续的字节存储块//限制RAW文件尺寸必须>=地形的尺寸,一个128x128的RAW文件只能用于最多128x128的顶点std::vector<BYTE> in(_numVertices);std::ifstream inFile(fileName.c_str(), std::ios_base::binary);if (!inFile)return false;inFile.read((char*)&in[0], in.size());inFile.close();_heightmap.resize(_numVertices);for (int i = 0; i < in.size(); ++i)_heightmap[i] = in[i];return true;
}

创建地形几何信息

可通过指定每行和每列的顶点数以及单元间距(cell spacing)来定义地形的尺寸。这些值将作为Terrain类的构造函数的传入参数。此外,
我们对该类的构造函数还传入了与地形相关的设备指针、一个标识了存储高度图数据的文件的字符串,以及一个用于对高度图中各元素实施比例变换的高度比例因子

顶点的计算

为了计算三角形栅格的各顶点,我们只需自顶点start起,逐行生成每个顶点,保持相邻顶点的行列间隔均为单元间距(cell spacing),直至到达顶点end为止。这样就给出了x和z坐标的定义。y坐标则要查询所加载的高度图数据结构中的相应项。

为了计算纹理坐标,请参考图13.5,该图给出了一个简单的纹理图像,从中我们可以看出与地形中位于(i,j)的顶点相对应的纹理坐标(u,v)可由下述公式计算得到:

其中uCoordIncrementSize=\frac{1}{numCellCols}      vCoordIncrementSize=\frac{1}{numCellRows}

索引的计算

为计算三角形栅格各顶点的索引,我们只需自图13.4的左上角起直至右下角,依次遍历每个方格,
并计算构成每个方格的三角面片的顶点索引。

计算的关键是推导出一个用于求出构成第i行、第j列的方格的两个面片的顶点索引的通用公式。借
助图13.6,我们可自行推导该公式,我们发现,对于处在(i,j)位置的方格

纹理映射

1.加载一个已创建好的纹理文件,然后再用于该纹理数据
2.创建一个“空”纹理,按顺序生成纹理数据,先用D3DXCreateTexture创建一个空纹理,然后再将顶层纹理锁定,自此开始遍历每个纹理元并对其上色。上色的依据是坐标方格所对应的近似高度。思路是:地形中海拔较低的部分上色为沙滩色,中等海拔的部分上色为绿色的丘陵颜色,高海拔的部分上色为雪山的颜色。我们用坐标方格中左上角顶点的高度值近似表示该方格的整体高度

光照

为了给地形添加光照以增强真实感。由于前面已经计算好了地形纹理的颜色,现在我们只需计算地形中各部分在给定光源照射下应如何进行明暗调整的明暗因子(shade factor),不用Direct3D来添加光照而是自己手动计算。这样做主要是基于下述考虑:

  • 手工计算由于无需存储顶点法向量,所以可以节省大量内存。
  • 山于地形是静态的,而且光源一般也不发生移动,所以我们可以预先对光照进行计算,这样就节省了Direct3D实时照亮地形那部分计算时间。
  • 手工计算方式使得我们获得了将相关数学知识付诸实践的机会,并有助于我们加深对基本的光照概念的理解以及熟悉Direct3D中的一些函数

我们在计算地形的明暗时用到的光照技术很基本也很常用,即漫射光光照(diffusing lighting)。给定
一个平行光源,我们用到达光源的方向(该光源发出的平行光的传播方向的反方向)来描述该平行光源。如果一组平行光线自空中沿着方向lightRaysDirection=(0,-1,0)向下照射,则到达光源的方向应与lightRaysDirection相反,即directionToLight=(0,1,0)。注意,光的方向向量应为单位向量。虽然指定光的出射方向好像更符合直觉,但指定到达光源的方向更适合漫射光光照的计算

由图137可见,上述夹角越大,坐标方格的朝向偏离光源就越大,其所接收到的光照就越少。反之,上述夹角越小,坐标方格的朝向偏离光源就越小,

相关文章:

  • scss 实用教程
  • VMware安装CentOS最小化开发环境导引
  • Spring 缓存注解这样用,太香了!
  • 基于8086汽车智能小车控制系统
  • 征服地球极限,中国极地科考与登峰事业的“御寒”之旅
  • 300.最长递增子序列
  • 数据权限-字段权限【实践篇-结合相关业务详细讲解如何实现】(基于若依框架)
  • 关于DDD的贫血模型和充血模型到底是什么区别?
  • JS+CSS随机点名详细介绍复制可用(可自己添加人名)
  • 合肥工业大学计算机网络实验一
  • 力扣21.合并两个有序链表
  • torch.mv
  • os_cfg.h、os_cpu.h和ucos_ii.h
  • 基于SSM的旅游管理系统的设计与实现
  • 租用网站服务器的六大指标
  • 2017年终总结、随想
  • AWS实战 - 利用IAM对S3做访问控制
  • codis proxy处理流程
  • es6(二):字符串的扩展
  • ESLint简单操作
  • isset在php5.6-和php7.0+的一些差异
  • js面向对象
  • learning koa2.x
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • MobX
  • spring-boot List转Page
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • vue 个人积累(使用工具,组件)
  • vue-router 实现分析
  • 初探 Vue 生命周期和钩子函数
  • 仿天猫超市收藏抛物线动画工具库
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 码农张的Bug人生 - 见面之礼
  • 前端攻城师
  • 如何胜任知名企业的商业数据分析师?
  • 设计模式(12)迭代器模式(讲解+应用)
  • 实战|智能家居行业移动应用性能分析
  • 小程序滚动组件,左边导航栏与右边内容联动效果实现
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • #、%和$符号在OGNL表达式中经常出现
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • (1)(1.9) MSP (version 4.2)
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (42)STM32——LCD显示屏实验笔记
  • (C语言)字符分类函数
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (办公)springboot配置aop处理请求.
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (附源码)springboot教学评价 毕业设计 641310
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (三) diretfbrc详解
  • (十六)一篇文章学会Java的常用API
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模