VOXEL 技术在即时渲染地形中的应用


  VOXEL 技术其实是一种很简单的技术,但它对于即时渲染地形确实又是一种十分有效的技术。写这篇文字的目的有两个,一方面是为大家介绍这个古老的技术,另一方面更重要的是希望大家看了本文能多有启发,从而发展出更多简单实用的好技术。就我自己的感觉而言,创作游戏程序,更多时候就是在寻找一种更简单而又更有效的方法。让一切不可能变为可能,这便是游戏程序设计之魅力所在。

  BTW,本来去年就想写这篇文字的,居然能够拖到了今天,看来我的懒惰毛病是发作得非常厉害的了。算了,闲话休提,还是让我们现在就一起踏上有趣的 VOXEL 技术之旅吧!

  VOXEL 技术出现得相当早,据 James Sharman 自称他在 95 年时就想出了这种方法。而 NOVALOGIC 则是这种技术的忠实拥护者,从早期的 COMMANCHE 到最近的 DELTA FORCE 和 DELTA FORCE II,都一直使用 VOXEL 技术来搭建图形引擎的核心。

  VOXEL 技术的思想其实很简单,它不是用的现在很流行的多边形方法来描述地形,而是用的一种线性插值的办法来形成自然连续的起伏地形。如果只用一句话来描述就是由近及远地依次画出对应的地形轮廓线,同时记录屏幕投影的高度坐标值,以供画下一条轮廓线时比较,从而只画后面新露出来的部分。

  根据这种想法,我们首先必须要考虑的就是如何来表示地形,以及如何去求取并绘制出每条地形轮廓线。

  通常,在使用 VOXEL 技术时,我们会建立一个二维数组来记录地面上均匀分布的各点高度。比如 HEIGHT[3,4] = 100 就表示在位置 [3,4] 处的地面高度为 100,习惯上,通常的高度取值在 0 到 255 之间。

  有了这个数组以后,下一步我们便依次开始求取并绘制出每条地形轮廓线。

  在上图中,V 表示观察者所处的位置,L1 和 L2 分别表示的是前后裁减范围,红色线段所表示的就是我们要绘制的地形轮廓线。

  对于任何一条红色线段来说,知道了观察者的位置、观察方向和观察夹角,以及到观察者的距离这几个条件以后,代入三角公式就可以很容易地计算出这条红色线段的两个端点位置。

  现在我们有了这条红色线段的两个端点位置,下面就可以开始绘制地形轮廓线了。

  首先我们从离观察者最近的一条红色线段开始,假设两个端点的位置是 (X1, Y1) 和 (X2, Y2),而实际的屏幕显示宽度为 W。

  接下来我们把这条红色线段按等分取 W 个点,这些点就是我们绘制时用的采样点。

  然后我们便该依次求取出每个采样点上的地面高度。在求这些采样点上的地面高度时,我们通常使用线性插值的方法。

  比如有一点 N,它的位置是 (X, Y),其中 X=Xa+Xb,Y=Ya+Yb,Xa 和 Ya 是 X 和 Y 的整数部分,Xb 和 Yb 是 X 和 Y 的小数部分。按照线性插值,此处的地面高度应该是:

  HN=(H(Xa,Ya)*(1-Xb)+H(Xa+1,Ya)*Xb)*(1-Yb)+(H(Xa,Ya+1)*(1-Xb)+H(Xa+1,Ya+1)*Xb)*Yb

  如此这样,我们就求出了该采样点上的地面高度。然后,我们把这个地面高度按线段到观察者的距离进行坐标变换,最后得到该点对屏幕投影产生的纵坐标值,同时,该点对屏幕投影产生的横坐标值直接由它在这 W 个点中的排列位置得到,比如说第一个点的横坐标值就是 0,第二个点的横坐标值就是 1,第三个点的横坐标值就是 2 等等……。

  为了正确地处理每一点的前后空间关系,我们将为每列保留一个最高纵坐标值。在实际显示地形轮廓线的每一点时,我们需要把每点的纵坐标值同该列的这个最高纵坐标值进行比较,并在超过此值时覆盖这个最高纵坐标值。由于我们目前是画的是最近的一条地形轮廓线,所以不需要考虑是否被更近的地形轮廓线所挡住,直接判断每点纵坐标值是否在屏幕以内就可以了,如果是的话则直接修改该列的最高纵坐标值为此纵坐标值,否则让该列的最高纵坐标值为最低。

  接下来在由近及远依次显示除了最近的一条之外的其它地形轮廓线时,我们通过对每列的最高纵坐标值进行这种比较和更新,就可以跳过那些被遮盖住的部分,从而达到正确显示的目的。

  一般地,在选取地形轮廓线时,越远的地形轮廓线可以选得越稀疏,由于透视的原因,这样不会产生明显的失真,而计算量可以减少很多。

  到了这一步,剩下的工作已经不多了。觉得光是这样的地形轮廓线太简单了不是?想要看到更真实的地形吗?那么就让我们开始关于地表蒙皮的话题吧!

  在 VOXEL 技术中,地表蒙皮是一件非常简单的事情,实际上就是用许多短竖线去填充地形轮廓线之间的空缺。

  图五给出的是一种最简单的情况,只做了一些非常简单的对亮度的处理。在这种情况下,使用的是地形轮廓线之间填充按照亮度插值生成的短竖线的方法。理解了这种方法就不难去理解其它更复杂的方法了。

  首先,我们必须求出地形轮廓线上每点(准确说应该是指的像素)的亮度,使用我们前面求每点高度时类似的办法,这个问题将不难解决,但我们还得先建立一个同高度二维数组 HEIGHT[x, y] 对应的亮度二维数组 BRIGHT[x, y]。

  亮度的计算有很多种办法,这里介绍一种按坡度来求取亮度的简单方法:

  BRIGHT[x][y] = 128+(HEIGHT[x+1][y+1]-HEIGHT[x][y])*4;
  if(BRIGHT[x][y]<0) BRIGHT[x][y]=0;
  if(BRIGHT[x][y]>255) BRIGHT[x][y]=255;

  求出了地形轮廓线上某点的亮度以后,剩下的工作就是填充一条按照亮度插值生成的短竖线。

  为了达到这个目的,我们在显示一条地形轮廓线时,除了会记录该列的最高纵坐标值外,还要记录产生最高纵坐标值的那一点的亮度值。这样当我们在画从第二条开始的地形轮廓线时,一旦发现当前采样点的纵坐标值超过了该列的最高纵坐标值,就按照从记录中最高纵坐标值对应的亮度值到当前采样点的亮度的顺序画一条亮度渐变的短竖线。这条竖线的起点就是记录中的最高纵坐标值,终点是当前采样点的纵坐标值。然后把该列的最高纵坐标值置为当前采样点的纵坐标值,并记录下最后的亮度值,即当前采样点的亮度值。

  如此一来,亮度值地表就被我们轻松实现了。

  下一步,为了获得更真实的效果,我们将开始考虑如何实现对地表的纹理映射。

  在此要声明一句,对于纹理映射这个概念,我不想在这里详细解释,否则本文会变得太长且内容过于分散。所以以下便假设读者已经熟悉了 3D 中的纹理映射这个概念。如果你确实不知道的话就说一声,我回头再单独写成文字便是。

  James Sharman 在他的文章中曾经提出了一种方法,就是按高度渐变来产生地表纹理映射。他首先为各个不同高度的地面建立一系列的纹理如下:

  有了这一系列的纹理,我们接着在做地形绘制时,便按照每点的实际高度和以前面提到的 Xb、Yb 作为 U、V 坐标来选取对应的纹理进行映射。得到的结果如下图所示:

  其中相邻两条地形轮廓线之间的填充是对 U、V 坐标使用线性插值方法得到的。为了让大家能更好地看清这个过程,请参考下图:

  现在对这种先计算出若干地形轮廓线然后再用线性插值方法填充的思想应该理解得非常清楚了吧。

  不过,在 DELTA FORCE 这样的游戏中,使用的是另外一种方式。在这种方式中,先把整个地图做成一张巨大的纹理,然后在映射时,是只按照位置来进行纹理映射而不考虑高度。这种方式可以得到更逼真的细节,但同时也要求更多的内存。另外,在 DELTA FORCE 中,阴影是直接做在纹理上的,而不是实时计算得到的,这样有利于提高效率。

  说到这里无意抬头望了望天,发现时候已经不早了,太阳都快出来了,是该准备去休息的时辰了。虽然还有千言万语,但瞌睡来了确实挡都挡不住,所以只好溜去睡觉,言有未尽之处,大家莫怪……zzZ

VOXEL 技术在即时渲染地形中的应用 by 樊一鹏相关推荐

  1. VOXEL 技术在即时渲染地形中的应用

    VOXEL 技术其实是一种很简单的技术,但它对于即时渲染地形确实又是一种十分有效的技术.写这篇文字的目的有两个,一方面是为大家介绍这个古老的技术,另一方面更重要的是希望大家看了本文能多有启发,从而发展 ...

  2. 孤岛危机 教程:使用Voxel技术创建地形

    看到Enforcer兄也不打算继续发了,我也蛮动摇,不过已经答应的东西还是要写完,这种技术性教程的确没什么人看,说实话我自己都看的有点累,还得边看边实践,否则很难理解,所以大家有需要的就来看吧,能有一 ...

  3. 通过SignalR技术整合即时通讯(IM)在.NET敏捷开发框架中落地

    1.引言 即时通讯(IM)是RDIFramework.NET敏捷开发框架全新提供的一个基于Web的即时通讯.内部聊天沟通的工具.界面美观大方对于框架内部进行消息的沟通非常方便.基于RDIFramewo ...

  4. BIM技术在装饰装修工程中的应用

    摘     要 BIM技术中包含了强大的建模.渲染及动画技术功能,该技术可以将建筑进行更加通俗化与直观的三维描述,从而使装饰装修设计人员能够明确地设计项目利用BIM技术在最短时间内完成设计效果设计及修 ...

  5. 即时战略游戏中如何协调对象移动

    作者:Dave C. Pottinger 翻译改写:lzc 在图论中人们研究了通过怎样的计算才能找到一条从A点到B点的通路,以图论本身来说这已经解决了从A到B的问题,剩下的只是从A沿着找到的路线移动到 ...

  6. 即时战略游戏中如何协调对象移动(转帖)

    即时战略游戏中如何协调对象移动 http://www.lihuasoft.net/news/list.php?frmid=97 作者:Dave C. Pottinger 在图论中人们研究了通过怎样的计 ...

  7. 技术分析| 即时通讯和实时通讯的区别

    即时通讯(IM)和实时通讯是一套网络通讯系统,其本质都是对信息进行转发.最大的不同点是对信息传递的时间规定.二者的区别可以从以下几个方面: 一.场景 常见的即时通讯 场景包括文字聊天.语音消息发送.文 ...

  8. [转载]WorldWind实时确定、更新、初始化和渲染地形和纹理数据

    WorldWind实时确定.更新.初始化和渲染地形和纹理数据 原文链接: http://www.cnblogs.com/rainbow70626/p/5597267.html 当用户点击WorldWi ...

  9. 各Rendering Path技术以及其在Unity中的实现

    Rendering Path其实指的就是渲染场景中光照的方式.由于场景中的光源可能很多,甚至是动态的光源.所以怎么在速度和效果上达到一个最好的结果确实很困难.以当今的显卡发展为契机,人们才衍生出了这么 ...

最新文章

  1. C 盘FAT32变为 RAW 格式
  2. 成功解FileNotFoundError: [Errno 2] No such file or directory: './data\\mnist\\train-images-idx3-ubyte'
  3. 类加载器ClassLoader的角色
  4. Win32ASM学习[3]:局部变量
  5. Spring Boot2.0+中,自定义配置类扩展springMVC的功能
  6. 宝藏新品牌成长白皮书:新品牌心智与营销增长方法论
  7. java实现电子面单pdf生成_福利!使用Aspose.Words在Java中将Word格式转换为PDF完整指南...
  8. VS2010 安装OpenCV2.4.0教程
  9. 【PFC】PFC测试指令
  10. Comsol With Matlab启动失败解决
  11. Linux(一):概述及环境搭建
  12. php中exec的用法,php exec用法详解
  13. 5G 几年了,高铁信号怎么还是这么差?
  14. 【配电网重构】基于粒子群算法实现最小化功率损耗的配电网重构附matlab代码
  15. Python 给图片加文字,加图片水印
  16. R语言入门(15)_读取文件(read)
  17. 基于单片机的心率体温血压系统设计(#0494)
  18. 鱼眼图像校正(球面等距投影模型)
  19. word中英文单词间距过大——换行或断字加横杠
  20. 【阿里云云计算工程师ACP认证】1.云服务器ECS

热门文章

  1. 《乞力马扎罗山的雪》——海明威
  2. [已解决]用wget下载GES DISC数据遇到unable to establish SSL connection的问题
  3. ISO27701个人隐私信息安全管理体系 认证经验
  4. 了解“新基建”、读罢IDC报告后,还请查收来自浪潮的硬核实力!
  5. C语言-两个单链表的合并
  6. 课程向:深度学习与人类语言处理 ——李宏毅,2020 (P10)
  7. 当mysql遇到爱疯emoji表情
  8. 一个小工具——随机产生汽车车牌号的Java实现
  9. Windows服务安装异常:System.Security.SecurityException: 未找到源,但未能搜索某些或全部事件日志。不可 访问的日志: Security
  10. CPU外频、FSB前端总线和内存频率的关系