人气 294

[游戏程序] Using Vertex Texture Displacement for Realistic Water Render [复制链接]

九艺网 2017-3-10 17:02:14

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
此教程版权原作者所有,仅供个人学习使用,请勿转载,勿用于任何商业用途。
由于本人水平有限,难免出错,不清楚的地方请大家以原著为准。也欢迎大家和我多多交流。
翻译:clayman
Blog:http://blog.csdn.net/soilwork
[email protected]
使用Branching避免不需要的计算
即使优化了纹理拾取方式,渲染水面时的纹理拾取次数还是很高,将严重影响性能。虽然我们能减少需要渲染的顶点数量,但这会影响视觉效果,并且带来锯齿。
由于我们渲染了大片的水面,因此有些三角形有可能一直延伸到了屏幕之外。但即使是这些三角形,顶点程序仍然对他们进行了渲染,浪费了宝贵的计算资源。如果我们渲染时跳过那些摄像机视见体(frustum)之外的三角形,则可以节省许多计算量。
由于顶点程序同一时刻只能处理一个顶点,无法访问拓扑信息,因此,我们只能在顶点层次进行优化,而无法在三角形层次优化。虽然,当三角形中的某些顶点被挑过了,而其他顶点没有时,可能出会一些问题。但是在实践中,我们发现,如果三角形以及顶点纹理置换的位置足够小时,这种效果就不太明显。
下面的伪代码描述了这个思想:
float4 ClipPos = mul ( ModelViewProj, INP)
float3 b0 = abs(ClipPos.xyz) < (ClipPos.www * C0 + C 1) ;
if ( all (b0))
{
// vertex belongs to visible triangle,
//perform texture sampling and displace vertex accordingly
}
这段伪代码里,我们使用裁减空间的顶点纹理来判断当前顶点是否在视见体之内,之后,对于所需要的顶点,再进行余下复杂的计算操作。
这里C0和C1是特殊的裁减常量,控制了三角形延伸出摄像机视见体多少距离将会触发裁减。这样,就能避免由于裁减了那些顶点在视见体外,但三角形还在视见体内的顶点,而导致的问题。出于效率的考虑,我们的“裁剪”视见体只需比摄像机视见体稍微宽一点就可以了,以保证延屏幕边缘有一定的“安全区域(guard-band)”。因为我们的水体表面镶嵌良好,同时顶点纹理置换也很合理,所以这个简单的方法在实践中效果很好。
使用渲染到纹理(Using Render-to-Texture)
可以先使用一个单独的pass,把多张高度图混合为一张浮点纹理,从而进一步提高程序的速度。这样就不必在vertex shader中多次执行昂贵的拾取操作。此外,使用高度压缩的16-bit浮点纹理格式储存原来的高度图。另外,使用3D纹理,我们还可以储存一系列的高度图动画序列帧(a sequence of animated height maps),让水面动画更加平滑。
使用这种优化,需要把渲染循环分为两个pass:
1. 用一个单独的pixel shader把多张高度图混合为一张32-bit的浮点纹理。这张纹理中的象素元对应了放射状mesh中的顶点。
2. 使用前面描述的方法,置换顶点位置。
Back Sides of Waves
由于在pixar shader中进行的光照计算假设水面是平坦(flat),因此在某些特定的情况下,这种近似会导致一些问题。
如下图所示,即使背对着观察者的波纹,也会被看到,而实际上,这些波应该是不可见的。这种效果将会对波峰较亮部分产生影响。
d124a51bf905c2af9a46c551054e9d17.jpg

为了减轻这种效果,需要对用于光照计算的法线进行调整,让它朝观察者的方向“倾斜(tileing)”一点,这样,他们就会靠近波纹的前面。 可以在源码中找到具体代码。以下是使用本章所介绍的技术,渲染的一张水面效果图。
f49626e2c1e20e1d51be616305cba17d.jpg

1.2.5 渲染局部波纹扰动(Rendering Local Perturbations)
有时候,需要渲染由于物体漂浮或者落入水中,所引起的局部波纹扰动。特别是对游戏来说,这是很有用的,我们通常需要产生爆炸效果,船航行时的轨迹,等等。对基于高度图的水面模型来说,很难引入物理上正确的扰动实现方法,我们将讨论一种简单的方法。
形变模型分析(Analytical Deformation Model)
实现局部波纹的扰动,最简单的方法就是根据分析结果,再次改变置换之后的顶点位置,在vertex shader中把重新计算的顶点位置和置换之后的位置进行加和。例如,对于爆炸效果来说,可以使用以下公式:
42e726592cc16b490f2f94c57954ad00.jpg

这里,r表示水平面上的点到爆炸中心的距离,b是抽样常量(decimation constant)。I0、w和k的值则根据给定的爆炸参数来确定。
至于渲染,同样可以使用前面渲染水面时,所用的放射状网格,但网格的中心必须是爆炸点。
动态置换贴图(Dynamic Displacement Mapping)
另一种选择是,把局部产生的偏移值直接渲染到顶点纹理中,实际上就是在GPU上实现通用编程(general-purose programming on the GPU)(GPGPU)的方法。使用这种方法,先在第一个pass中产生一张顶点纹理,随后的pass中用它来进行实际渲染。对高度图进行过滤,在pixel shader中,再把所有波形加和到一起,可以大大减少vertex shader的工作量。
为了计算偏移值,可以使用上面提到的分析模型,也可以使用一钟细胞自动机(cellular-automata)的方法,逐帧展开(evolving)局部偏移。沿着一定的方向对纹理进行模糊处理,还可以实现风吹过水面的效果。
但是,对于大小为1km,分辨率为50cm的水面来说,意味着纹理尺寸为2048x2048,这将给纹理内存和shader的执行速度都带来极大压力。此外,想要快速改变观察点也很成问题。
然而,我们仍然鼓励读者去尝试一下这些方法。
泡沫生成(Foam Generation)
在波涛汹涌的水面上,我们可以生成一些泡沫来进一步增加真实感。最简单的方法就是对于高度超过值H0的顶点,使用一张预处理过的泡沫纹理进行混合。根据以下公式来计算泡沫的透明度:
c4d74a30fa876514649c1b5da0651609.jpg

Hmax表示可能出现泡沫的最高位置,H0为基准高度,H表示当前高度。
泡沫纹理可以是动态的,以表现泡沫的生成和消失。这些动画纹理序列可以由艺术家手动创建,也可以用纹理生成。
1.3 结论

~~~~~~~~~~~~~~~~~~~·全文完~~~~~~~~~~~~~~~~~~~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

QQ|手机版|小黑屋|九艺游戏动画论坛 ( 津ICP备2022000452号-1 )

GMT+8, 2024-4-20 11:54 , Processed in 0.103865 second(s), 26 queries .

Powered by Discuz! X3.4  © 2001-2017 Discuz Team.