|
基于LOD的大规模真实感室外场景实时渲染技术的初步研究 part II&III(5) 测试用的高度图,大小为2049×2049. 使用双色模式渲染。用来演示生成的三角形扇,三角形扇的中心红色,周围的点为白色。中心为蓝色的三角形扇表示这个地方达到了全分辨率。 C=25,C2=2.5. 三角形数量6529。视野距离600。FPS=167 C=50,C2=5.0.三角形数量11192。视野距离600。FPS=138 C=25,C2=2.5. 三角形数量2174。视野距离600。FPS=237。网格着色模式 C=50,C2=5.0. 三角形数量13221。视野距离600。FPS=124。网格着色模式 表6.1:4097×4097地图的渲染结果。 用的高度图 C=35,C2=3.5.三角形数量10877。视野距离6000。FPS=137 本算法的速度基本上只和C,C2有关,图6.1为这两个因子和速度、三角形数量之间的关系。图中的测试数据中C=35恒定,C2从2.5到10.0。由于这两个由图可见,速度和三角形的数量和C×C2大致是先线性关系。 图6.1 三角形数量,FPS和C×C2之间的关系。红线为FPS值,绿线为三角形数量 在选择4097×4097的地图时,算法运行速度上没有任何的变化,因为需要渲染的地形区域仅限于视见体内部。当选择8193×8193的地图时候,由于内存缺页引起的丢帧就比较严重,如果在Windows98下就基本不能运行。 第三部分:真实感场景的生成技术。 第七章:天空体和镜头眩光 第八章:公告板技术 第九章:地表的细节 第十章:景深处理 第十一章:运动模糊 第四部分:结论和展望 附录 A:地形数据的生成 B:参考文献
第三部分 真实感场景的生成技术 引 言 一个室外场景渲染引擎必须要具有真实感的渲染能力,这些能力包括让地形表面有更多的细节、渲染地表植被等,甚至各种天气效果。所有的这些都能让场景看起来更加的自然,更加的逼真。在下面的几章中,本文将实现其中几种主要的项。 第七章:天空体和镜头眩光 1.天空体:如果一个室外场景中看不到天空是不可想象的。蓝天白云的天空能让视野中的变的清朗。而布满了乌云的天空则能让场景看起来更加的压抑。通常天空体的实现有圆形的和盒状的。圆形的天空体有很多的优点,但是比较复杂,尤其是映射纹理的时候。盒状的天空体则非常的简单,它的主要缺点是离天空边缘近的时候天空会有非常明显的变形。关于天空体几何模型的生成很多文章都有介绍,如[参考文献33]就是一篇很好的天空体制作教程。 图7.1圆形天空体示意图。左边为半球状天空体,右边弧顶状天空体。图片来自[参考文献33] 天空体最难的是纹理的生成,当然你可以找一张天空的照片,但是这样天空是静态的。其次是用算法动态生成天空的纹理,生成这种纹理的算法通常是使用Perlin Noise。关于生成天空的精彩文章在http://freespace.virgin.net/hugo.elias可以找到。这种方法生成的云彩真实性非常的好,但是致命的缺点生成大纹理的时候速度不够快,虽然能达到一定的实时性,但是应用到整个引擎中的时候,速度就非常的慢。最后的方法是用天空的视频文件做纹理,这种方法虽然速度还不是十分的快,但是它比用Perlin Noise生成纹理的速度还是要快的多。(本文的演示程序附带了一个演示视频纹理的程序,它使用DirectShow来播放视频文件,将播放结果作为纹理映射到几何体上。) 2.镜头眩光:稍微有一点摄影经验的人都知道,当我们把摄影机的镜头对准发光物体的时候,会有光晕现象产生,这种光晕也称为镜头眩光。光晕的大小和镜头有关。当我们在场景中放置一个太阳的时候,如果实现了这种光晕现象会有很惊人的效果。 太阳的模拟非常的简单。只要在场景的特定位置放置一个圆形物体就可以了。镜头光晕则需要一些额外的处理。首先我们来看一个眩光体的位置的。如图7.2所示。 图7.2镜头眩光示意图,左图为用Photoshop生成的效果图,右图为其组成部分示意图。 镜头光晕由一系列的光环组成,所有的光环排列在一条直线上。这条直线由发光物体位置和屏幕中心确定。这些光环的形状则有多中方式,通常用一张放射线状的图用来作为发光物体的光芒,另外的则用不同厚度的环状图像。 我们组合这些光环的时候需要使用Alpha Blending功能把这些光环叠加起来自然的融合到场景中去。通常我们采用的Alpha Blending公式为 所有的光环都是作为二维物体绘制到场景中去的。因此,发光物体在屏幕上的位置需要通过自己计算得到,在计算发光物体在屏幕上的位置的同时我们还可以得到这个位置的Z-Buffer的信息来判断是否能看到发光物体,当发光物体不可见的时候,光晕自然也不可见。下图为一个用上面算法生成的镜头光晕的例子。 图7.3,镜头光晕示意图,左图为独立效果,右图为组合到场景中后的效果图。图片来自本文的Demo 最后必须注意的是,眩光体必须在场景中所有的物体都绘制完毕后才绘制。 第八章:公告板技术 公告板(Billboard)是一种始终朝着观察者的一个物体。通常它是一个多边形。室外场景中通常有一些物体,比如说树木,柱子一类的物体,要么是细节非常的多以至无法用模型来表示,要么是从任何一个方向都一样(如柱子)。我们就简单的把这些物体用一个多边形加纹理映射来近似的表示。 用Billboard来表示树木非常的有效,著名的模拟驾驶游戏Need for Speed 5中的树木就是用这种技术实现的。我们所看到的树木其实只是一个矩形,如图8.1所示,矩形可以绕着一根轴旋转,使矩形始终对着观察者。因此无论你从哪一个角度去看,你都只能看到矩形的正面,而不会看到扁的一面。 图8.1Billboard模拟树木的示意图 除此之外,Billboard通常还用在粒子系统之中,因为3D场景中的粒子要始终正对着观察者。这种应用的典型例子就是Quake III和Unreal中绚丽的子弹光焰。 Billboard的实现关键在两个地方,其一是纹理贴图的模式,对于像绘制树木这一类形状不规则的物体,通常是采用透明贴图的模式,在OpenGL/Direct3D里我们可以采用Alpha test的功能。对于想粒子系统则一般采用Alpha Blending的功能。第二个关键的地方就是如何让多边形的一个面始终朝着观察者,如图8.2所示。 图8.2Billboard旋转角度的计算,其中红的箭头为摄影机的朝向,蓝色的箭头为Billboard原来的朝向,z为转动的中心轴 我们只要把多边形旋转一个角度r就可以了。角度r的大小可以用如下的公式去计算: 。转动的中心轴则可以通过如下公式计算: 。 第九章:地表的细节 地表细节涉及的方面非常的多,主要的有如下的方面:地面纹理,地面阴影(亮度图)。 1. 地面纹理 由于室外的场景比较大,通常需要一个很大的纹理来表达地面的细节信息。但是太大的地表纹理一来要占用很大的纹理内存,二来图形卡也不一定能支持。 解决这个问题的方法通常有两种,一是把大纹理分割成小的单位,动态加载需要的纹理(这种技术也称为Texture Tiling,详见[参考文献24])。另一种方法是采用多遍纹理映射(Multi-Stage Texture mapping),它用一个较大一点纹理来表达地形的大概特征,然后再用一个小的纹理来和第一个地形调制(Texture blending)再一起,第二个纹理通常采用循环贴图(即贴图的u,v坐标大于1)。不同的细节纹理可以表达不同的地貌。 相比之下,第二种方法更加的简单,效果也更好,唯一需要注意的是不同细节纹理过渡的地方。要事先混合好过渡处的纹理,不然在不同的细节纹理过渡处的地貌变化会非常的生硬,十分的难看。 图9.1细节纹理示意图,左图为没有使用细节纹理,右图为使用了细节纹理。图片来自本文的Demo 2亮度图 在一个3维场景中增加光照和阴影效果可以更加提高场景的真实程度。 光照的计算需要为各个三角形指定法向量,动态计算法向量速度太慢,事先计算好法向量则需要大量的额外存储空间,而且在LOD算法中存储法向量也不是一件容易的事情。另一个问题是阴影问题,实时阴影的生成一直是图形学中的一个难点。何况在室外大场景下,实时动态生成的阴影基本是不可能的。 解决以上两个问题的一个折中方法是使用亮度图,然后把亮度图和地面的纹理进行调制,得到最终的地面纹理图,这种方法在运行时刻不需要额外的计算,也不需要额外的存储空间。 计算亮度图的时候,我们需要给场景指定一个光源的位置,这个位置通常是镜头光晕的发光体(太阳)的位置。一个点的亮度由所有共享这顶点的三角形决定。其中任何一个三角形的亮度计算如下图: 图9.2。亮度图的计算,其中r 为三角形法向量和光线方向的夹角 根据常识,只有朝着光源的面才会被照亮。假设全场景的环境光的强度为Ie,则这个如图9.2中三角形的亮度I由下面的算法决定: if cos (r) > 0 I = cos (r) × (1 – Ie) + Ie; Else I = Ie; 阴影的计算则如下图所示: 图9.3,阴影的示意图,其中A点在阴影区内,B直接被照亮 确定一个顶点是否在阴影区内的时候,我们需要逐个检查这个顶点和光源之间的顶点,验证是否由顶点挡住了光源的光线,如图9.3,很明显光源的光线不能直接照到A,所以A在阴影区内。如果一个点在阴影区内,则它的亮度就直接等于环境光的亮度Ie。否则它的亮度由图9.2导出的算法决定。 最后我们还需要把计算得到的亮度图和纹理调制到一起,本文采用最简单的方式,就是把亮度值(0-1.0)乘纹理图上对应点的各个颜色的分量即可。 第十章:景深处理 通常使用计算机渲染得到的图像都非常的犀利,不管远的还是近的的物体看上去都是很清晰。但是事实并不是这样的,离观察者远的东西看上去会显得模糊一些,而不是处于两只眼睛观察的焦点上的物体也会模糊一些。 实现第二现象的方法在[参考文献24]的4.2和9.2节由详细介绍,而且实现这种效果也不是十分的必要,对渲染速度的影响也很大。这里就不作介绍。至于第一种现象,最简单有效的方法就是使用雾。关于雾的详细内容在几乎所有的OpenGL,Direct3D的书籍上都有介绍。 雾的计算方程通常有三种,本文推荐采用的公式为 。使用了雾效果的另外一个好处就是可以把远处的(位于视见体外部的)三角形裁剪掉也不至于产生“跳出”现象,因为远处的景物已经完全成为雾的颜色。它能提供一种无限远视野的假象。下图是使用了雾效果和没有使用雾效果的图例。 图10.1左图为开启了雾效果,右图为关闭了雾效果。图片来自本文的Demo 第十一章:运动模糊 运动模糊一种动态的效果,它是由于摄影机的底片的曝光需要一定时间,如果在曝光过程种场景发生改变,就会在底片上产生模糊效果,这种效果称为运动模糊。运动模糊现象在电影、摄影上非常的常见。 运动模糊在运动的场景中非常重要,你会发现如果缺少了运动模糊会带来严重的失真,看一下没有采用运动模糊的计算机动画,你会发现物体快速移动时,画面缺乏连贯性和真实感。在前面提到过的模拟驾驶游戏Need for Speed中,地面在赛车高速运动的时候就会变的模糊,给人一种扑面而来的感觉。 图11.1运动模糊示意图。图片来自[参考文献19] 实现运动模糊的方法在[参考文献19]里有详细的介绍,在这篇文章里作者采用了时间过采样的方式来实现运动模糊,这是一种精确的运动模糊的实现方式,通常这种方法要使用“累积缓存”(Accumulation Buffer)来实现,关于累积缓存的使用方法在OpenGL,Direct3D的书籍中均可以找到。一般情况下,我们只要累积3到5次就可以达到比较理想的运动效果了,但是这种有一个很大的缺点就是严重降低运行速度,当我们进行n次累积的时候,运行速度就是没有进行运动模糊时的1/n。这样的代价在一个游戏程序里是不能被接受的。 作为一种其次的解决方案,我们可以把先前的渲染结果保存起来,然后按一定的比例削弱以后混合到当前的渲染结果中去。假设当前的渲染结果为P1,先前的帧为 P2,最后得到的当前帧为P。混合的公式如下:P=(1-f)×P1+f×P2。其中f为模糊因子,f越大,运动模糊越明显。这种方法只需要渲染一次场景,对运行速度影响不是很大。下面给出这种方法在OpenGL下的实现步骤: 1. 首先建立一个足够大的纹理, 2. 渲染场景到帧缓冲区中。 3. 把保存先前帧内容的纹理设置为当前纹理。 4. 绘制一个和视口一样大的矩形,把这个矩形按上面给出的公式和步骤3中渲染结果混合在一起。 5. 把混合结果拷贝到纹理对象中(glCopySubTexImage)。 6. 重复步骤2-5绘制下一帧。 由于有些OpenGL的驱动不支持直接渲染到纹理的操作,因此用OpenGL实现起来比较麻烦而且速度受到的影响也比较大一些。在Direct3D中可以通过直接改变渲染目标来把场景渲染到纹理中,在速度上受到的影响要小一些,在实现上也要简单一些,但是基本原理还是相同的,这里不再赘述。下图是一个使用了这种方法的例子。 图11.2运动模糊。图片来自本文的Demo 第四部分:结论和展望 本文已经基本上实现了一个室外3D游戏引擎的渲染核心部分。虽然提供的算法不是十分的精确,但是速度非常的快,用本文算法实现的Demo可以在当前流行的个人电脑上非常流畅的运行。加上本文第三部分的技术后,画面质量得到很大幅度的提升。下图为本文的演示程序的屏幕截图。所有的效果都已经开启。 但是急待解决的问题还很多,主要有以下几个: 1. 内存管理 本文采用的内存数据结构虽然在一定的程度上考虑了内存缺页的问题,但是效果不是很好。由于地图是作为一个二维数组加载的,采用的是线性结构。数据的冗余比较大。可以考虑采用链式的数据结构来改善。 2. 几何形变。 3. 无限重复地图 一个地图再大也有一定的限度,当前许多的主流游戏采用的都是地图循环的方式,即沿着一个方向走到地图的边缘以后会返回到开始的地方,观察者永远也走不到地图的尽头。 4. 水面的模拟 室外的场景中水的存在是很正常的,比如说湖面,小河等。水面应该倒影四周的场景,绘制倒影一般借助于模板缓冲区绘制两次场景,但是这对于室外大场景的开销非常大而且实现也很困难。我们需要一种更加有效的模拟水面的方法。 5. 各种天气效果 本文只是简单的实现了天空体,真实的自然界中还有很多现象,比如下雨,闪电,下雪,刮风等。加上这些天气效果会使场景看上去更加的多变。 第五部分:附录 A地形数据的生成 生成地形数据的方法主要有两种: 一是使用使称为Perlin Noise的随机函数来生成高低起伏不平地形。Perlin Noise用来生成地形特别有效,关于这种方法在[参考文献14]里有详细的介绍。 第二种方法是分形,通常也叫Diamond—Square算法。这种方法则在用来生成几座山的时比较有效。关于这种算法可以在www.fractal3d.com上找到详细的介绍。 B参考文献和资源 参考文献 [1]. XiaoHong Bao and Renato Pajarola LOD-based Clustering Techniques for Optimizing Large-scale Terrain Storage and Visualization” Department of Information & Computer Science University of California .Irvine. [2]. Stefan R?ttger , Wolfgang Heidrich and Philipp Slusalleck,Hans-Peter Seidel Real-Time Generation of Continuous Levels of Detail for Height Fields University Erlangen-Nürnberg [3] P Lindstrom and V.Pascucci Visualization of Large Terrains Made Easy Lawrence Livermore National Laboratory August 7, 2001 [4] P.Lindstrom and V.Pascucci Terrain Simplification Simplified: A General Framework for View-Dependent Out-of-Core Lawrence Livermore National Laboratory May 8, 2002 [5] P.Lindstrom , David Koller , William Ribarsky, Larry F. Hodges, Nick Faust and Gregory A. Turner Real-Time, Continuous Level of Detail Rendering of Height Fields In SIGGRAPH 96 Conference Proceedings, pp. 109-118, Aug 1996. [6] Reinhard Klein and Andreas Schilling Efficient Multi-resolution Models for progressive Terrain Rendering [7] Mark Duchaineau, Murray Wolinski, David E. Sigeti, Mark C. Miller, Charles Aldrich and Mark B. Mineev-Weinstein. ROAMing Terrain: Real-time, Optimally Adapting Meshes. Proceedings of the Conference on Visualization '97, pp. 81-88, Oct 1997 [8] Thatcher Ulrich Continuous LOD Terrain Meshing Using Adaptive Quad-trees www. Gamasutra.com [9] Luis Sempé, Terrain Rendering using Heightmaps March 2002, http://www.sphergames.com/ [10] Renato Pajarola, ETH Zürich Large Scale Terrain Visualization Using The Restricted Quadtree Triangulation [11] 王宏武 董士海 《一个视点相关的动态多分辨率地形模型》 北京大学计算机图形研究所 [12] Hugues Hoppe Smooth View-Dependent Level-of-Detail Control and its Application to Terrain Rendering Microsoft Research [13] Louis Castle, Jonathan Lanier and James McNeill Real-time continuous level of detail (LOD) for PCS and Consoles Technical Presentation GDC 2000 [14] Hugo Perlin Noise [15] 中国游戏开发者网络 《BillBoard 技术详解》 [16] 中国游戏开发者网络 《BillBoard》 [17] 中国游戏开发者网络 《基于视锥包含的不可见物体消除算法》 [18] 中国游戏开发者网络 《OpenGL的渲染成纹理技术》(OpenGL Render-to-Texture) [19] 中国游戏开发者网络 《运动模糊》(Motion Blur 原文见Hugo的主页) [20] Michael Tanczos The Art of Modeling Lens Flares http://www.gamedev.net/ [21] Alan Gordie Lens Flare Tutorial http://www.gamedev.net/ [22]Jackie Neider ,Tom Davis and Mason Woo 《OpenGL编程权威指南》(OpenGL Programming Guide) OpenGL ARB Addsion-Weslly [23]《OpenGL 超级宝典》人民邮电出版社 [24] Tom McReynolds Programming with OpenGL: Advanced Rendering SGI SIGGRAPH `97 Course [25] Microsoft DirectX SDK Document [26] Mesa Lib 4.03 Source Code [27] Microsoft MSDN –OpenGL section [28] OpenGL Specification (version 1.1 ,version 1.2,version 1.3 version 1.4) [29]《计算机图形学算法基础》机械工业出版社 [30] 孙家广等 《计算机图形学》 清华大学出版社 [31] 清华大学远程教育 《计算机图形学》 第4章 第7节 《实时真实感图形学技术》 [32] Bryan Turner (Dreams Woo翻译)《ROAM实时动态LOD地形渲染》 [33] Luis R. Sempé, Sky Demo http://www.spheregames.com/ 资源 NeHe's OpenGL Tutorials Nehe.gamedev.net FlipCode www.flipcode.com GameTutorials: http://www.gametutorials.net/ nVidia: Developer.nvidia.com OpenGL: www.opengl.org/ Mesa: www.mesa3d.org DirectX: www.microsoft.com/directX/ GameDev: www.gamedev.net 中国游戏开发者:Mays.soage.com 中国游戏资源网:www.gameres.com
|