texturepacker clipmap和geomrtry clipmap的区别

TERRAIN RENDERING TECHNOLOGY BASED ON GEOMETRY CLIPMAP--《Journal of Geodesy and Geodynamics》2013年04期
TERRAIN RENDERING TECHNOLOGY BASED ON GEOMETRY CLIPMAP
Wang Yu;Sun YWang MSong XMilitary Simulation Technology Institute,Aviation University of Air FBase of Flight Training,Aviation University of Air FArmament Department,Aviation University of Air FAeronautics & Astronautics Intelligence Department,Aviation University of Air F
An improved Geometry Clipmap algorithm is presented,in which we increase the number of topographic data scheduling module,reconstruct the organization of the note,and introduce the progressive texture update technology. The experiments show that new algorithm improves the work efficiency and display effect of flight simulation system.
【Fund】:
【CateGory Index】:
supports all the CNKI
only supports the PDF format.
Similar Journals
(C)2006 Tsinghua Tongfang Knowledge Network Technology Co., Ltd.(Beijing)(TTKN) All rights reservedMesh View:简化的Clipmap地形渲染
编辑:www.fx114.net
本篇文章主要介绍了"Mesh View:简化的Clipmap地形渲染",主要涉及到Mesh View:简化的Clipmap地形渲染方面的内容,对于Mesh View:简化的Clipmap地形渲染感兴趣的同学可以参考一下。
Mesh View Terrain Rendering
本文借鉴目前的地形渲染和地形数据管理调度的解决方案,提出一种简单易实现的无限大地形的数据调度和加载方案。
John Camark 的id-tech5 的技术demo中给我们展示了一个无比细致的室外场景,该演示使用了id-software的最新技术,Mega-Texture, Mega Textue严格的来说是一种纹理的调度和管理方案,但是Mega-Texture最早的起源于SGI的Clipmap[参考文献1]技术,而Clipmap技术经过多年的发展,已经被成功移植到GPU上[参考文献2]。该方案是一个非常有效的管理和调度超大规模地形和影像数据的方法。GPU-Base clipmap的基本思想是将高度图以clipmap的方式进行管理,并在cpu端生成14个block的vertex-buffer,这些vertex buffer中只保存(x,y)的坐标,高度z则在vertex shader中通过采样clipmap来获取。生成14个block的原因一方面在于LoD的考虑,另一方面方便进行视锥裁剪。
考察现在DX9.0c/DX10.1/DX11的硬件特性,displacement map早已经绝对的主流配置,这意味着使用GPU的clipmap技术完全已经是具有实用价值的。
上一节中提到的Voxel技术其实可以认为是通过一个规则的Mesh, 该Mesh如下图
&& 红色的线为视锥的区域,绿色的线组成一个网格,计算出这个绿色网格中每一个点的高度值,最终的结果,就是这个地形渲染的一个View。
结合Voxel和Clipmap,我们将DEM保存成R32F格式的float texture,使用一个或者多个任意的Mesh,并把这些Mesh放在以视点为中心的位置,通过这些Mesh上(x,y)的值来对DEM进行采样,生成一个全新的Mesh。只要这些Mesh满足远离中心位置的越稀疏,靠近中心越稠密,就能形成LoD。
数据调度和渲染
&&& 与clipmap算法不同,这里我们采用更简单的方法,除了Clipma Pyramid以外的数据,这些数据的每一块都带有自己的位置和大小信息,各个块之间允许有重叠现象,甚至每个块的大小还可以不一样,这点非常符合卫星遥感图像的需求,遥感图像通常不会严格的重合和无重叠。
&& 根据硬件能力不同,同一个时刻,只保存视点周围3x3,或者 5x5个左右的地形块。这些地形块组成一个地形块缓冲池。根据视点的位置和移动趋势,动态的加载和卸载这个池中的数据。在渲染的时候,vertex shader会判断每一个输入的点,根据缓冲池中的地形块的位置和大小信息,决定从哪一块中进行采样。伪代码如下:
PS_INPUT ( VS_INPUT input ){
&& PS_INPUT output = (PS_INPUT)0;
= float3(.xy , 0.0) +& input.Pos.xyz;
= mul( && , float4( ,1) ) .xyz ;
= 0.0f; float div = 0.0f;
&& for(int
&&& if( PtInRegin([] &) {
&&& &&float
= []. - [].;
&&& & float
= []. - [].;
float _x = . - [].;
&&& & float _y = . - [].;
&&& & float2
= float2( _x / , _y /
&&&&& float _v = DEMTextures[].SampleLevel(DefaultClampSampler, & , 0 ).;
&&&&& if(_v & 0 ){ &&div += 1.0f; &&& += _v; &}
&if(div & 0.0f)&&& output. =
/ div ; //计算高度
&else&& output. = 0.0f;& //该点不落在任何一块地形上,给个默认值
//&.. 其它运算
对于纹理数据,可以用同样的算法,唯一不同之处在于,vertex shader的采样是displacement map,而pixel shader中则是texture map。下图是渲染结果,采用的是一个圆形的Mesh.
本方案的最大优势在于实现简单,对数据的限制比较少,并且能用统一的算法对DEM和影像进行处理和渲染。由于采用的Mesh本身可以不存在裂缝,因此在任何情况下,该算法都不会产生裂缝,另外,因为相对clipmap中的block,我们采用的是mesh,这更符合一般渲染引擎的场景管理算法,在需要把地形系统与其它的模块进行整合的时候将会变得非常的自然。同样的,block的裁剪也可以简单的使用已有的场景管理器对mesh的裁剪算法而不需要专门实现针对地形块的裁剪版本。
优化以及后续工作
我们考虑如何减少纹理数量的问题,我们知道D3D9最多只支持8个纹理, 而一般我们至少要在缓冲池中保存9个以上的纹理,这意味着如果不减少纹理的数量,我们将无法使用d3d9来实现该算法。我们可以考虑动态的将一个大纹理划分为的区域,每一个地形块或者影像块加载的时候都被重采样成该分辨率的,使用LockRect来更新某个区域。一般主流硬件至少都支持分辨率(大部分支持)。采用该方法,只需要一个的纹理,就能满足一个4x4缓冲池的需求。
另外,Direct3D 10支持Texture Array。采用该方法,也能减少纹理个数的使用。
如果地形系统需要支持高级光照,那么如何生成地形的法向量,也是一个需要考虑的问题,我们知道通过对高程的差分运算,可以得到高程的法向量,我们可以在Vertex shader或者geomerty shader中来完成这个动作,不过考虑到法向量需要进行平滑运算,在计算的时候,应该取改点周围的点来进行差分运算,以保证法向量的连续和平滑。
&&& 此外,如何减少纹理采样次数,如何减少dependent vertex fetch的次数,也是一个非常值得优化的地方。
版权声明:本文为博主原创文章,未经博主允许不得转载。
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:使用基于GPU的Geometry Clipmap渲染地形
编辑:www.fx114.net
本篇文章主要介绍了"使用基于GPU的Geometry Clipmap渲染地形",主要涉及到使用基于GPU的Geometry Clipmap渲染地形方面的内容,对于使用基于GPU的Geometry Clipmap渲染地形感兴趣的同学可以参考一下。
使用基于GPU的Geometry Clipmap渲染地形(上)使用基于GPU的Geometry Clipmap渲染地形(Terrain Rendering Using GPU-Based Geometry Clipmaps)(上)
翻译:claymanclayman_.cn仅供个人学习使用,勿用于任何商业用途,转载请注明作者^_^
注:这篇文章翻译的是《GPU Gem2》中第二章的内容,老早就翻译的东西了,但因为翻的不太好,一直放着,找不到原版的PDF文档,截图有些是在网上找的,有些是我自己做的,大家凑活看了,基本和原图还是差不多的。《GPU Gem2》中的内容实在很难,本人水平有限,有错的地方还请大家指正。
&&&&&&&&&&Geometry clipmap是用于渲染地形LOD的新方法。它把地形缓存在一组嵌套的规则网格中,同时在观察点移动时,不断更新这些数据。和之前不规则网格(irregular-mesh)技术相比,规则的网格有很多优点:简洁的数据结构、平滑的视觉效果,稳定的渲染速率,合适的分级(graceful degradation),高效的压缩,以及运行时的细节合成(synthesis)。这里,我们将描述一种通过顶点纹理(vertes texture)实现的几何clipmap。把地形几何体作为图片来处理,几乎所有计算都能通过GPU来完成,从而减少CPU的负担。
1.1 Geometry clipmap简述&&&&&&&& 在大型户外环境中,处理地形数据将会占用大量的储存空间以及渲染带宽。我们已经开发了多种LOD技术来处理地形。但是,大多数技术需要在运行时创建和修改mesh数据(顶点和索引缓冲),而这些操作对当前的图形处理技术(graphics architecture)来说代价是很大的。此外,不规则的网格通常需要使用CPU来处理,而在诸如游戏之类的应用中,CPU本来就不够用了。&&&&&&&& Gemetry clipmap框架中(Losasso and Hoppe 2004)把地形作为一张2D的高度图(elevation image)来处理,并预先把它过滤为一张包含L层的mipmap金字塔。
处理复杂地形时,完整的金字塔可能对内存来说太大了。Geometry clipmap结构对每一层进行窗口大小为n x n的采样并缓存,这和Tanner 1998介绍的texture clipmap方法有些类似。对观察者来说,这些窗口相当于一组嵌套规则的网格。注意,高细节层次所占的空间总是比较粗糙的层次少。这样的目的是保证在屏幕空间,所有三角形都统一大小(the aim is to maintain trangles that are uniformly sized in screen space)。如果clipmap大小为 n = 255, 那么在1024 x 768的分辨率下,每个三角形大约是5个像素。
&&&&&&&& 只有最高的层次(L-1级)渲染为完整的方形网格。其他层次都渲染为空心环,因为空心部分已经由较高层次填充了。&&&&&&&& 当观察者移动时,clipmap窗口也作相应的改变,同时更新数据。为了保证高效的持续更新,以一种环形的方法来访问clipmap每一层的窗口,也就是说使用2D环绕寻址(the clipmap window in each level is accessed toroidally, that is ,with 2D wraparound addressing)。&&&&&&&& 其中,挑战之一就是如何隐藏相邻层次之间的边界,同时,保证一个完美的网格,避免临时的撕裂效果。Geometry clipmap的嵌套网格结构提供了一种简单的解决方案。其中,关键的思想就是每层在靠近外层边界的地方引入一个交换区域(transition region),这样,几何体和纹理都能平滑的通过插值过渡到下一个粗燥级别。使用顶点和像素着色器,可以分别高效的实现这些交换区域。
&&&&&&&& Geometry clipmap的嵌套网格结构同样能实现高效的压缩以及合成。它可以通过对较粗糙的层次的数据进行upsample(提高取样率),预测(prediction)每一层的高度数据。因此,我们只需要储存多余的细节信息并合成到这个预测的信号上就可以了。
1.2 Overview of GPU Implementation&&&&&&&& Geometry cliipmap最初的实现方法把每一层数据当作普通的顶点缓冲。由于当前的GPU缺乏修改顶点缓冲数据的能力,所以这种实现在更新数据和渲染时都需要CPU参与。而这里,我们将使用顶点纹理来实现geometry clipmap。这样做是有益的,因为clipmap 2D的窗口网格数据更适合保存为一张2D纹理,而不是通过人工线形化处理保存为1D的顶点缓冲。由于clipmap包含L层,每一层又包含了n x n的几何采样,我们将把采样的(c,y,z)信息分为两部分:* (x,y)坐标储存为常量顶点数据*Z坐标储存为一个单通道(single-channel)的2D纹理&&高度图(elevation map)。为每层都定义一个n x n的高度图。这些纹理都将在clipmap层次根据观察点变换时更新。&&&&&&&& 由于clipmap的层次是统一的2D网格,(x,y)坐标也是规则的,同时,变换和比例也是常量。因次,我们定义了一组只读的顶点和索引缓冲,用来表示2D&footprints&,同时,在每个层次都重复使用这些footprints。&&&&&&&& 顶点通过把高度图作为顶点纹理来采样,获得高度值。在顶点着色器中访问纹理是DirectX 9 Shader Modle 3.0的新特性,NVIDIA Geforce6 系列的GPU都支持这个功能。把高度数据保存为图片,可以直接使用GPU的光栅管道(rasterization pipeline)来进行处理。对于需要进行合成操作的地方,所有运行时的计算(高度图的upsample,地形细节合成,法线计算,以及渲染)都完全由GPU来执行,这样就可以留出宝贵的CPU资源)。对压缩地形来说,就需要CPU不停的为图形卡解压和更新数据。
1.2.1 数据结构&&&&&&&& 总的来说,主要的数据结构如下。我们预先定义一组顶点和索引缓冲常量,为clipmap的网格(x,y)编码。对0&..L-1中的每一层,分配一张高度图(单通道浮点2D纹理 1-channel floating-point 2D texture)和一张法线图(4通道 8-bit 2D纹理)。以上所有数据结构都保存在显存中。
1.2.2 Clipmap的尺寸&&&&&&&& 由于每层的外边界都必须覆盖在下一个粗糙层次的网格上,网格尺寸n必须是奇数。当纹理尺寸是2的幂时,硬件可以进行优化,所以我们选择n = 2^k-1,保留一行一列作为未使用的纹理。我们的例子中大多数情况下使用n = 255。&&&&&&&& 选择 n = 2^k-1还有一个优点就是较好的层次永远不会位于下一个粗糙层次的中心(the finer level is never exactly centered with respect to its parent next-coarser level)。换句话说,就是对于下一个层次,它在x或y方向总有一个网格单位的偏移,具体偏向那个位置则根据观察点的位置来决定。事实上,当下一个粗糙层次不变时,应该允许较好的层次可以改变,因此,较好的层次有时就必须进行偏移。当然,我们也可以选择n = 2^k+3作为网格尺寸,来达到中心对齐的效果,但是这样仍然需要处理中心偏移的情况,导致最后的结果过于复杂。
1.3.1 有效层(Active Levels )&&&&&&&& 虽然我们为clipmap分配了L层,但是通常只渲染(和更新)一组有效的层次0&&L&-1,L&的值基于观察点的高度来计算。这样做的目的是,当观察点足够高时,clipmap中最好的层次就不必渲染了。特别的,我们把网格范围小于2.5h的层次作为无效层,这里,h表示观察点到地形的垂直距离。由于地形数据都储存在显存中,计算h将导致重新读取最好的有效层高度纹理图采样点数据。这个重新读取的工作将带来一些小小的额外开销,因此,每过几帧检测一次。当然,需要把L&-1层渲染为一个完全的方形而不是空心环。&&&&&&&& Losasso和Hoppe2004描述的方法中,对于在观察者移动时没有完全更新的层进行了裁剪(cropping)。为了简化GPU的实现,我们放弃了这个特性。我们假设每个层是完全更新的,或者完全无效。
1.3.2 顶点和索引缓冲
&&&&&&&& 正如之前所说的,我们把网格的(x,y)值作为顶点数据,同时,z方向的高度值保存为单通道的浮点纹理。为每层的环定义一个单独的顶点缓冲来保存(x,y)数据是一种有效的方法。但是,为了减少内存空间和实现可视区域裁剪,我们把环分为一些小的footprint片。
&&&&&&&& 大部分环都由12个m x m的渲染单元块(block)组成,如图中的灰色区域,这里m = (n + 1) / 4。因为2D网格是规则的,同一个层中的(x,y)都进行同样的变换。此外,不同层次之间也可以使用统一的缩放值。因此,使用一个只读的顶点和索引缓冲,以及一些额外的参数,就可以让vertex shader对每个渲染单元块进行缩放和变换,完成所有渲染 。&&&&&&&& 当clipmap大小为255时,每个规则的渲染单元块包含64x64个顶点。使用顶点缓冲来保存这些三角形带的索引。为了减少储存空间,将使用16位的索引值作为索引缓冲,这样,渲染单元块的m最大值就为255,同时,clipmap中n的最大值为1023。&&&&&&&& 但是12个渲染单元块的大小并不能完全覆盖整个环。我们使用一些小的2D footprint来填充这些裂缝。注意,这些额外区域的大小和渲染单元块相比应该是很小的,就像上图所示的那样。首先,环每条边的中间都有 (n & 1) & ((m -1) x 4) = 2个方格的裂缝,图中黄色部分,可以使用4个m x 3的固定区域来填充他。我们把这些区域编码为一个顶点和索引缓冲,并且对所有层复用这个缓冲。第二,在内层环的两条边界处会产生一个方格大小的裂缝,图中蓝色部分,以满足较好层次中心偏移的效果。这条L形的裂缝可能出现在四个位置(左上,左下,右上,右下),我们将使用4个顶点以及一个索引缓冲来填充这条内部的裂缝,使用对所有层次复用这几个缓冲。&&&&&&&& 此外,还需要在环的外边界渲染一系列退化(degenerate)三角形(图中橙色的部分)。为了避免T-junction效果,这些0区域(zero-area)三角形是必须的。最后,使用4个额外的渲染单元块以及一个L形区域填满整个环。&&&&&&&& 由于每个footprint(x,y)都为局部坐标,所以,不需要32-bit的精度,使用D3DDECLTYPE_SHORT2类型就可以了,这样每个象素只需要4 bit。将来,我们甚至可以在每个m x m大小的小的块内使用顶点索引i来计算这些坐标(x,y),比如(fmod( i , m) , floor (i/m))。
1.3.3 View Frustum Culling&&&&&&&& 我们以块为最小单元在CPU上进行view frustum culling计算。每个块都扩张到[ Zmin, Z max]的范围内,并且在三维空间内由可视平截体进行分割。只有在分割快不为空时,才对它进行渲染。根据观察点的位置,对于90的观察范围来说,可以把渲染负载减少到原来的1/2 ~ 1/3之间,如下图所示。
1.3.4 关于DrawPrimitive调用&&&&&&&& 对于每一层来说,我们余姚调用14次DrawPrimitive(DP)方法:12个块每个一次,为footprint调用一次,为剩下的三角形再调用一次。但是,在视平截体裁减之后,平均每帧只需要渲染12个块中的4个。而对于最好的层来说,则需要多调用5次来填充中间的空间。因此,总的来说,平均每帧需要调用6L+5(当L=11时为71)次DP方法。更进一步,使用Geometry Instancing技术把每个层次中的所有大块作为一个统一的整体调用一次DP,则可以把DP的次数减少到 3L + 2 (35)
&&&&&&(未完待续,下一部分将给出具体的代码实现)
使用基于GPU的Geometry&Clipmap渲染地形(Terrain Rendering Using GPU-Based Geometry Clipmaps)(下)
翻译:claymanclayman_.cn仅供个人学习使用,勿用于任何商业用途,转载请注明作者^_^
1.3.5&Vertex Shader
&&&&&&&&&我们使用同一个vertex shader来渲染之前描述的所有2D footprint。首先,对于给定的footprint坐标(x,y)来说,shader通过简单的缩放和变换来计算它的世界坐标(x,y)。接下来,从顶点纹理中读取高度值z。这里不需要任何过滤器,因为顶点和纹理采样是一一对应的。
&&&&&&&&&为了平滑的过渡,vertex shader将对两个不同层次边界的顶点进行几何混合(blend)。根据顶点(x,y)相对于观察点(Vx,Vy)的位置来计算混合参数alpha。这里:
alpha = max( alphax,alphay):
alphax = clamp(( | x & Vx ) & ( (n-1)/2 & w & 1)) /w , 0, 1)
&&&&&&&&&使用类似的方法计算alphay。
&&&&&&&&&这里,所有的坐标都以clipmap网格范围内[ 0&.n-1]之间的值来表示,w是交换区域的宽度(这里选择了&w= n/10)。我们希望除了交换区域外,alpha值都为0,而在交换区域内,值线形的从0增加到1,当达到外围的层次时值为1。下图的蓝色部分即为交换区域。
&&&&&&&&&对于几何混合来说,我们对同一位置(x,y)在不同层次之间的高度值Zf(较好层次的高度值)和Zc(教粗糙层次的高度值)之间进行线形插值。
Z& = ( 1 & alpha)Zf + alpha * Zc
&&&&&&&&&一般情况下,采样点位于较粗糙网格的边缘,Zc则通过对较粗糙层次边缘两个采样点的均值来计算。我们可以在运行时来完成这一步计算,但这将会导致3次顶点纹理查找(Zf一次,Zc =&(Zc1 + Zc2)/2&两次),而对于现在的显卡来说,读取顶点纹理的代价还是很大的。
&&&&&&&&&因此,我们把计算Zc作为更新clipmap的一部分来实现,把Zf和Zc打包为同一个单通道的浮点纹理(pack both Zf and Zc into the same 1-channel floation-point texture)。我们把Zf作为浮点数的整数部分,而差值Zd = Zc & Zf则保存为小数部分。这个打包的步骤将在pixar shader中upsampling的时候完成(详见1.4.1)。
&&&&&&&&&以下是实现clipmap渲染的vertex shader的部分HLSL代码:
struct OUTPUT
&&&&&&&&&vector pos&&&&&&&&&&&: POSITON;
&&&&&&&&&float2 uv&&&&&&&&&&&&&&: TEXCOORD0; //coordinates for normal-map lookup
&&&&&&&&&float&&z&&&&&&&&&&&&&&&: TEXCOORD1; //coordinates for elevation-map lookup
&&&&&&&&&float alpha&&&&&&&&&&&: TEXCOORD2; //transition blend on normal map
uniform float4 ScaleFactor, FineBlockO
uniform float2 ViewerPos,AlphaOffse,OneOverW
uniform float&&zScaleFactor,zTexScaleF
uniform matrix WorldWiewProjM
uniform sampler ElevationSampler = sampler_state&&&&&&&&&&&&// fine level height sampler
&&&&Texture&&&= (fineLevelTexture);
&&&&MipFilter = N
&&&&MinFilter = P
&&&&MagFilter = P
&&&&AddressU&&= W
&&&&AddressV&&= W
OUTPUT RenderVS(float2 gridPos: TEXCOORD0)
&&&&&&&&&OUTPUT
&&&&&&&&&//convert from grid xy to workld xy coordinates
&&&&&&&&&//ScaleFactor.xy:grid spacing of current level
&&&&&&&&&//ScaleFactor.zw:origin fo current block within world
&&&&&&&&&float2 worldPos = gridPos*ScaleFactor.xy + ScaleFactor.
&&&&&&&&&//compute coordinates for vertex texture
&&&&&&&&&//FineBlockOrig.xy: 1/(w,h) of textrue
&&&&&&&&&//FineBlockOrig.zw: origin of block in texture
&&&&&&&&&float2 uv = gridPos * FineBlockOrig.xy + FineBlockOrig.
&&&&&&&&&//sample the vertex texture
&&&&&&&&&float zf_zd = tex2Dlod(ElevationSampler, float4(uv, 0, 1));&&&&&&&&&float zf_zd = tex2Dlod(ElevationSampler,float4(uv,0,1));
&&&&&&&&&//unpack to obtain zf and zd = (zc-zf)
&&&&&&&&&//zf is elevation value in current(fine) level
&&&&&&&&&//zc is elevation value in coarser level
&&&&&&&&&float zf = floor(zf_zd);
&&&&&&&&&float zd = frac(zf_zd) * 512 - 256; // zd = zc - zf
&&&&&&&&&//computer alpha (transition parameter) and blend elevation
&&&&&&&&&float2 alpha = clamp((abs(worldPos - ViewerPos) - AlphaOffset)* OneOverWidth , 0, 1);
&&&&&&&&&alpha.x = max(alpha.x,alphal.y);
&&&&&&&&&float z = zf + alpha.x *
&&&&&&&&&z = z * ZScaleF
&&&&&&&&&output.uv =
&&&&&&&&&output.z = z * ZtexScaleF
&&&&&&&&&output.alpha = alpha.x;
1.3.6&The Pixar Shader
&&&&&&&&&Pixar shader访问法线图(normal map)并对表面进行着色。我们让法线图的分辨率为几何地形的两倍,因为每个顶点一条法线效果是很模糊的。当更新clipmap时,我们将逐渐计算法线图(详见1.4.3)。
&&&&&&&&&为了平滑的着色过渡,着色器查找当前层次和下一个较粗糙层次的法线值,之后使用vertex shader中计算的alpha值进行混合。一般情况下,这将导致2次纹理查找。因此,我们把两个法线值以(Nx , Ny , Ncx , Ncy)的形式放到一张4通道,每通道8bit的纹理中,这里假设Nz = 1,Ncz = 1。因此在读取之后需要重新归一化(renormalize)。
&&&&&&&&&所上的颜色通过读取一张基于z方向(z-based)的1D纹理贴图来获得。
&&&&&&&&&以下代码是实现clipmap rendering的pixar shader的部分HLSL代码(Upsample和Zcoarser函数详见附件):
//paramters uv,alpha,and z are interpolated form vertex shader.
//Two texture samplers have min amd mag filters set to linear:
//NormalMapSampler: 2D texture containing normal map
//ZBasedColorSampler: 1D texture containing elevation-based color
uniform float3 LightD
//pixar shader for rendering the geometry clipmap
float4 RenderPS(float2 uv&&&&&: TEXCOORD0,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&float z&&&&&&&&&&&&&&&&&&: TEXCOORD1,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&float alpha&&: TEXCOORD2) : COLOR
&&&&&&&&&float4 normal_fc = text2D(NormalMapSampler,uv);
&&&&&&&&&//normal_fc.xy contains normal at current(fine) level
&&&&&&&&&//normal_fc.zw contains normal at coarser level
&&&&&&&&&//blend normals using alpha computed in vertex shader
&&&&&&&&&float3 normal = float3((1-alpha) * normal_fc.xy + alpha * (normal_fc.zw),1);
&&&&&&&&&//unpack coordinates from[0,1] to [-1,1]range,and renormalize
&&&&&&&&&normal = normalize(normal * 2 -1);
&&&&&&&&&//computer simple diffuse lighting
&&&&&&&&&float s = clamp(dot(normal,LightDirection),0,1);
&&&&&&&&&//assign terrain color based on its elevation
&&&&&&&&&return s * tex1D(ZbasedColorSampler,z);
&&&&&&&&&当观察者在场景中移动时,clipmap每层中的窗口都必须进行变换,以保证观察点位于窗口的中央,因此,我们必须有根据的来更新这些窗口。由于观察者的移动是连续的,因此每帧基本上只需要为窗口更新一个L形的区域。另外,对较粗糙的层次来说,相对于观察者移动的距离,它所改变的位置是成指数减少的(the relative motion of the viewer within the windows decreases exponentially at coarser levels),因此,很少需要进行更新。
&&&&&&&&&我们以从粗糙层到较好层的顺序来更新有效的clipmap层。还记得每个clipmap层都储存了两张纹理吗:一张单通道的浮点高度图,一张4通道,每通道8bit的法线图。在更新的过程中,我们通过使用pixel shader进行渲染的方法来对这些纹理区域进行修改。为了避免改变已有的数据,所有的访问操作都是以一种环形(toroidal)的方式来进行,如下图所示:
(红色为进行更新的区域,绿色箭头为观察者移动的方向)
我们使用环绕寻址(wraparound addressing)的方式来定位clipmap窗口在纹理图中的位置。在这种环形的访问方式下,L形的更新区域通常变为一个十字形的区域,如上图所示。通过渲染2个矩形来组成这个渲染区域。需要注意的是如果更新区域跨越了纹理的边界,则有可能需要3到4个矩形。
1.4.1&Upsampling
&&&&&&&&&我们使用一种插值细分(interpolatory subdivison)的方法,通过较混乱的层次来预测较好层次的几何体。这里将使用众所周知的四点插值细分曲线方法的张量积版本,&mask weights取( -1/16, 9/16,9/16,-1/16)(We use the tensor-product version of the well-known four-point subdivision curve interpolant ,which has mask weights ( -1/16, 9/16,9/16,-1/16))。这种upsampling过滤器恰好可以达到我们所希望的C1平滑效果。
&&&&&&&&&根据采样点在网格中的位置(偶数-偶数,偶数-奇数,奇数-偶数,奇数-奇数),选则不同的mask。对一个偶数-偶数的像素来说,只需对纹理进行一次查找,因为采样是通过插值计算得来的;而对一个奇数-奇数的像素来说,则需要对纹理进行4x4次查找;另外的两种情况均需要4次查找。对于CPU来说,可以用一个if块来方便的选择所用的mask值。但是,分支语句对于pixar shader来说代价是很大的。因此,我们总是进行16次纹理查找,另外,通过对一张2x2纹理的查找来选择不同的mask值。
&&&&&&&&&以下是部分upsampling shader的HLSL代码实现:
//residualSampler: 2D texture containing residuals,which can
//be either decompressed data or synthesized noise
//p_uv:coordinates of the grid sample
uniform float2 S
//pixel shader for updating the elevation map
float4 UpsamplePS(float2 p_uv : TEXCOORD0) : COLOR
&&&&&&&&&float2 uv = floor(p_uv);
&&&&&&&&&//the Updample function samples the coarser elevation map
&&&&&&&&&//using a linear interpolatory filter with 4x4 taps
&&&&&&&&&//(depending on the even/odd configuration of location uv,
&&&&&&&&&//it applies 1 of 4 possible masks)
&&&&&&&&&float z_predicted = Upsampler(uv);&&&&&&&&//detail omitted here
&&&&&&&&&//add the residual to get the actual elevation
&&&&&&&&&float residual = tex2D(residualSampler,p_uv * Scale);
&&&&&&&&&float zf = z_predicted +
&&&&&&&&&//zf should always be an integer,since ite gets packed
&&&&&&&&&//into the integer component of the floating-point texture
&&&&&&&&&zf = floor(zf);
&&&&&&&&&//compute zc byu linearlyu interploating the vertices of the
&&&&&&&&&//coarse-grid edge on which the sample p_uv lies
&&&&&&&&&float zc = ZCoarser(uv);
&&&&&&&&&float zd = zc -
&&&&&&&&&//pack the signed difference zd into the fractional componnent
&&&&&&&&&float zf_zd = zd + (zd + 256)/512;
&&&&&&&&&return float4(zf_zd,0,0,0);
1.4.2&Residuals
&&&&&&&&&可以通过解压数据或合成的方法获得residuals值,并把它添加到使用upsampling方法获得的较粗糙的数据中。
&&&&&&&&&对于使用压缩数据的方法,我们通过图片压缩技术来对residuals数据进行编码。我们使用了一种称为PTC的有损(lossy)图片编码方式,因为它支持一种高效的region-of-interest解码(Malvar 2000)。通过CPU来进行解压缩,并且把结果储存为一张residual纹理图。
&&&&&&&&&而对另一种方法来说,我们使用不相关高斯噪声(uncorrelated Gaussian noise)(Fournier et al. 1982)作为residuals值,来合成地形的细节(fractal detail)。GPU读取一小张预先计算好的包含了高斯噪声的2D纹理来完成合成,这个过程执行起来是相当快的。另外,把纹理环绕起来,扩展为一张无限大的高斯噪声纹理,同时,对纹理坐标进行一点点放大,来消除规则的周期效果(we enable texture wrapping to extend the Gausian texture infinitely,and apply a small magnification to the texture coordinates to break the regular periodicity)。跨越不同层次的噪声叠加在一起,因此对地形产生的起伏效果不会显示出任何模式性,如下图所示:
1.4.3&法线图(Normal Map)
&&&&&&&&&着色器使用当前层的高度图来为这一层更新法线图。计算两个grid-aligned的切线的叉积来获得当前法线。此外,还对较粗糙的层次进行一次纹查找,获得它的所有法线值。最后,把(Nx, Ny, Ncx, Ncy)打包为一张4通道的纹理。代码详见附件。
1.5&结果和讨论
&&&&&&&&&我们主要的数据是一张216000 * 93600的美国地形高度图,其水平分辨率为30米,垂直分辨率为1米。进行了100倍以上的压缩之后,只需要355MB的内存就可以容纳它。我们在P4&2.4G,1G内存,NIVIDIA Geforce6800 GT的系统上,以1024 * 768的分辨率对地形进行了渲染。
渲染率:在L=11,网格大小n=255,使用了裁减的情况下,获得了每秒130帧的效果,每秒渲染了6千万三角形。使用顶点纹理查找是系统的瓶颈,在移除了查找之后,渲染率提高到了185frames/sec&(对n=127的情况来说,使用了顶点纹理也可以达到298 frames/sec.)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&Previous Implementation&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&GPU-Based Implementation
Upsampling&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&3ms&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&1.0ms
Decompression(on CPU)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&8ms&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&8ms
Synthesis&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&3ms&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&~0ms
Normal-Map Computation&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&11ms&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&0.6ms
更新率:下表显示了更新过程中每个步骤所需要的时间,这里所统计的时间是最坏情况即每次更新整个层所需的时间。在CPU上完成的解压缩显然是系统的瓶颈。
最终的帧数:对于使用解压方式的地形来说,当观察着移动时,帧数大约在87 frames/sec,对于使用合成方法的来说,则是120 frames/sec。
1.6&总结和改进
&&&&&&&&&我们描述了一个使用GPU实现geometry clipmap的框架。几乎把所有显示几何图形的过程都使用GPU来完成,从而减少CPU的负载。
1.6.1&顶点纹理
&&&&&&&&&Geometry clipmap通过一种非常特别也是受限制的方法来使用vertex texture:实质上每个texels是以光栅扫描(raster-scan)的顺序来访问,和顶点是一种一一对应的关系。因此,我们希望以后的访问机制可以提高渲染效率。
1.6.1&取消法线图
&&&&&&&&&通过访问高度图中四个过滤之后的采样(filtered samplers)点,应该可以直接在pixel shader中计算法线。目前,顶点纹理查找只能使用32-bit的浮点图片,因此不能进行高效的双线形过滤(bilinear filtering).
1.6.3&Memory-free Terrain Synthesis
&&&&&&&&&在GPU上合成地形细节是如此之快,因此我们可以考虑每一帧都重建clipmap层次,从而节省显存。我们分配2张纹理T1和T2,然后在他们之间相互转换。把T1初始化为较粗糙的几何体作为合成过程的种子。首先,通过pixar shader的更新产生源纹理T1,接下来通过upsample和合成,创建一个较好的层次,并把它保存为T2。然后,把T1作为顶点纹理,渲染他所在的clipmap环。之后,交换两张纹理的规则并重复整个过程,直到所有层都完成合成以及渲染。最初的尝试是很有前途的,在L=9的时帧率约59 frames/sec。
&&&&&&& 略
点击这里下载完整的PDF文档和源码^_^
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:}

我要回帖

更多关于 easymovietexture 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信