简单快速的地形LOD连续变形
2007-05-24 00:13
260 查看
来源:gameres.com 作者:佚名
在地形渲染中为了减轻渲染负担其中一个技术是就LOD,但其带了的一个问题就是会产生地形“跳动”,因为地形的LOD精度发生变化时镶嵌的密度也发生了 变化。要解决这个问题有一个方法就是当高精的模型向底精模型变化时不是突然变化过去的,而是慢慢渐变而来,这样可以极大的减少“跳动”。通过设置适当的渐 变距离可以做到让观察者感觉不到地形的变化。
关于这个问题在一篇文章里面也有介绍:Terrain Geomorphing in the Vertex Shader[1],但是原文介绍的方法过于复杂而且不适合用硬件加速,但是这仍然是一篇学习地形渲染的好文章。下面提出一种更加简单,快速的方法来解决 这个问题。使用这个方法有一个前提条件就是地形块之间的LOD级别相差不能大于1.
解决这个问题最基本的思想就是:对高精度的地形块进行形变来模拟低精度的地形块, 当高精地形和低精地形的形态完全一样时,地形块的LOD才变为低精度的。设置高精度地形块的高度为H1, 低精度的地形块的高度为H2,最后根据渐变距离求出一个插值t[0, 1],最后地形的高度就为H = lerp(H1, H2, t)。
为了加速渲染顶点形变的过程由vs去计算。设置地形的最大LOD级别为5,也就说有4种形变可能:0->1, 1->2, 2->3, 3->4.这样我们可以把四种形变的高度值存到一个float4(yMove)中。
对于如何求取低精度地形的高度值可以这样计算:先求出顶点是属于那一个地形四方面,然后求出其在四方面上的uv坐标,最后用二次线性插值来得到 四方面内任意一点的高度值。比如:一个地形四方面这四个高度值分别为h00, h10, h01, h11.设u为四方面x方向的坐标[0,1], v为四方面y方向的坐标[0,1].那么最后的高度值:
h(u, v) = (1.0f-v) * ((1.0f-u)*h00 + u*h10) + v * ( (1.0f-u)*h01 + u*h11 )
在计算好的形变的高度值后就可以在vs内计算形变高度值了,在计算之前还需要传入两个参数:
float4 MorphStart, MorphInvRange.其中MorphMin表示形变的起始距离,比如(50, 100, 150, 200)
就表示地形在50处开始0->1形变,100处1->2形变, 150处2->3, 依此类推。MorphInvRange是形变距离范围的倒数,比如上例:MoprhInvRange = (1/50, 1/50, 1/50, 1/50)。
在vs中计算高度值的代码如下:
void vsMain( in float3 Pos : POSITION0,
in float4 yMove : POSITION1 )
{
float viewDist = length(Eye - Pos );
float4 moprh = saturate( (viewDist-MorphStart)*MorphInvRange );
Pos.y += dot( yMove, morph );
}
根据每个顶点对眼睛的距离来决定最后的形变值,可以保证只要顶点位置相同最后形变后的位置也一定相同,避开了文献[1]中地形边界接缝等等麻烦 的问题。注意在vs中计算morph为什么要用saturate,是因为顶点缓冲中的Pos.y是最高精度地形的高度值,比如要从1->2级,除了 要加上1->2的形变高度值外,还要加上0->1的高度差值, 而且2->3, 3->4的形变高度值应该为0.上面这个式子正好能满足上面要求的情况。
处理完顶点形变后,还有一个工作要做就是要根据眼睛与地形块的最小距离来求地形块的LOD,设置眼睛与地形块的最小距离为d,那么求地形lod的代码如下:
if ( d < MorphStart.y ) // 0->1
lod = 0;
else if ( d < MorphStart.z ) // 1->2
lod = 1;
else if ( d < MorphStart.w ) // 2->3
lod = 2;
else if ( d < MorphStart.w + 50 ) // 3->4 (50为最后一级形变的距离)
lod = 3;
else
lod = 4;
现在似乎可以做到消除地形“跳动”的现像了,但是有一点还需要注意那就是光照。上面做的工作只是消除了几何形变产生的“跳动”,还有一个产生 “跳动”感觉的是光照颜色,如果你是在vs内计算的顶点光照那么还是会有“跳动”,因为顶点的密度变了光照的效果肯定不一样。要解决这个问题就需要用光照 图来代替顶点光照,但是这样就限制了地形的光照是静态的。如果你还是想要动态的地形光照,那就需要用地形的法向图在ps内动态计算,注意:法向图的边界的 地方要特殊处理。
在地形渲染中为了减轻渲染负担其中一个技术是就LOD,但其带了的一个问题就是会产生地形“跳动”,因为地形的LOD精度发生变化时镶嵌的密度也发生了 变化。要解决这个问题有一个方法就是当高精的模型向底精模型变化时不是突然变化过去的,而是慢慢渐变而来,这样可以极大的减少“跳动”。通过设置适当的渐 变距离可以做到让观察者感觉不到地形的变化。
关于这个问题在一篇文章里面也有介绍:Terrain Geomorphing in the Vertex Shader[1],但是原文介绍的方法过于复杂而且不适合用硬件加速,但是这仍然是一篇学习地形渲染的好文章。下面提出一种更加简单,快速的方法来解决 这个问题。使用这个方法有一个前提条件就是地形块之间的LOD级别相差不能大于1.
解决这个问题最基本的思想就是:对高精度的地形块进行形变来模拟低精度的地形块, 当高精地形和低精地形的形态完全一样时,地形块的LOD才变为低精度的。设置高精度地形块的高度为H1, 低精度的地形块的高度为H2,最后根据渐变距离求出一个插值t[0, 1],最后地形的高度就为H = lerp(H1, H2, t)。
为了加速渲染顶点形变的过程由vs去计算。设置地形的最大LOD级别为5,也就说有4种形变可能:0->1, 1->2, 2->3, 3->4.这样我们可以把四种形变的高度值存到一个float4(yMove)中。
对于如何求取低精度地形的高度值可以这样计算:先求出顶点是属于那一个地形四方面,然后求出其在四方面上的uv坐标,最后用二次线性插值来得到 四方面内任意一点的高度值。比如:一个地形四方面这四个高度值分别为h00, h10, h01, h11.设u为四方面x方向的坐标[0,1], v为四方面y方向的坐标[0,1].那么最后的高度值:
h(u, v) = (1.0f-v) * ((1.0f-u)*h00 + u*h10) + v * ( (1.0f-u)*h01 + u*h11 )
在计算好的形变的高度值后就可以在vs内计算形变高度值了,在计算之前还需要传入两个参数:
float4 MorphStart, MorphInvRange.其中MorphMin表示形变的起始距离,比如(50, 100, 150, 200)
就表示地形在50处开始0->1形变,100处1->2形变, 150处2->3, 依此类推。MorphInvRange是形变距离范围的倒数,比如上例:MoprhInvRange = (1/50, 1/50, 1/50, 1/50)。
在vs中计算高度值的代码如下:
void vsMain( in float3 Pos : POSITION0,
in float4 yMove : POSITION1 )
{
float viewDist = length(Eye - Pos );
float4 moprh = saturate( (viewDist-MorphStart)*MorphInvRange );
Pos.y += dot( yMove, morph );
}
根据每个顶点对眼睛的距离来决定最后的形变值,可以保证只要顶点位置相同最后形变后的位置也一定相同,避开了文献[1]中地形边界接缝等等麻烦 的问题。注意在vs中计算morph为什么要用saturate,是因为顶点缓冲中的Pos.y是最高精度地形的高度值,比如要从1->2级,除了 要加上1->2的形变高度值外,还要加上0->1的高度差值, 而且2->3, 3->4的形变高度值应该为0.上面这个式子正好能满足上面要求的情况。
处理完顶点形变后,还有一个工作要做就是要根据眼睛与地形块的最小距离来求地形块的LOD,设置眼睛与地形块的最小距离为d,那么求地形lod的代码如下:
if ( d < MorphStart.y ) // 0->1
lod = 0;
else if ( d < MorphStart.z ) // 1->2
lod = 1;
else if ( d < MorphStart.w ) // 2->3
lod = 2;
else if ( d < MorphStart.w + 50 ) // 3->4 (50为最后一级形变的距离)
lod = 3;
else
lod = 4;
现在似乎可以做到消除地形“跳动”的现像了,但是有一点还需要注意那就是光照。上面做的工作只是消除了几何形变产生的“跳动”,还有一个产生 “跳动”感觉的是光照颜色,如果你是在vs内计算的顶点光照那么还是会有“跳动”,因为顶点的密度变了光照的效果肯定不一样。要解决这个问题就需要用光照 图来代替顶点光照,但是这样就限制了地形的光照是静态的。如果你还是想要动态的地形光照,那就需要用地形的法向图在ps内动态计算,注意:法向图的边界的 地方要特殊处理。
相关文章推荐
- opencms简单快速建站过程
- HDU 2157 How many ways??(简单线性DP | | 矩阵快速幂)
- 【rzxt】简单几步教你快速更改Win8的字体大小
- 六、内部排序综合(九种)—插入类排序(直接插入、折半插入、希尔排序);交换类排序(冒泡、快速);选择类排序(简单选择、堆排序);二路归并排序;基数排序
- Unreal Engin_画廊制作笔记_001<设计草图,利用BSP快速搭建简单场景>
- ECSHOP忘记管理员密码怎么办?简单快速恢复密码方法 解决方法
- (多核DSP快速入门)1.创建简单的多核DSP项目HelloWorld
- 原码、反码、补码之间的快速转换和简单运算
- 51 NOD 1138 连续整数的和(简单数学公式)
- OpenGLES的简单应用绘图,以及照相机画面变色变形渲染(六)
- 直接插入、冒泡、快速、简单选择、堆、归并排序算法Java语言
- iOS文件(夹)快速简单完成增、删、改、查、写系列文件操作
- Directx11教程(19) 画一个简单的地形
- Thymeleaf 3.0 自定义标签方言属性,简单实例。快速学习!
- DevExpress 汉化(简单、实用、快速)【转】
- Prasely表单校验插件简单使用方法之快速入门
- Gym - 101061B 简单矩阵快速幂
- 快速实现一个简单的bigpipe模型
- 算法#11--用简单的思维理解归并排序和三向切分快速排序