(转)水面渲染小结

转自:http://blog.csdn.net/soilwork/article/details/1548490

水面渲染小结

本文版权归我所有,仅供个人学习使用,请勿转载,勿用于任何商业用途。
由于本人水平有限,难免出错,欢迎大家和我交流。
作者:clayman
Blog:http://blog.csdn.net/soilwork
[email protected]

从几何模型上来看,水面其实和地面是一样的,可以看做普通的均匀网格,不同点在于地形中,顶点高度是固定的,而水面是动态的。此外,对于水面来说,还有许多特殊的光学效果。为了更好的描述渲染效果,下面借用了《Water Effect》一文中的部分图片。

一.           水面动画

当然,第一步就是让水面运动起来。对均匀网格来说,需要计算出每个顶点的位置和法线。实际上,如果仅模拟比较平静的水面,甚至只需计算法线就行了,这也是目前游戏中常见的做法。

仅使用法线来模拟水面的好处是可以极大的简化几何模型,最简单的情况下,一个网格就能代表整个水面,你甚至不必担心如何处理LOD计算。它的实现思想就是bump mapping,区别在于这里我们使用动态的normal map。可以实时计算出每条法线的位置,也可以从预先处理好的normal map中获得这些信息。显然,适用后者计算量可以减少很多。在Farcry中,水面实际上只使用了一张normal map,在vertex shader中,对纹理坐标进行不同的缩放和偏移,从而获得动态水面。对这种方法来说,normal map质量的好坏对最终效果有很大影响。下面的代码显示了通过混合三层不同的波来模拟水面的情况:

bumpCoord1 = texCoord + time*0.02;

bumpCoord2 = texCoord * 2.0f + time * 0.02;

bumpCoord3 = texCoord / 2.0f + time * 0.01;

half3 vBumpTexA = tex2D(tex0, bumpCoord1).xyz;

half3 vBumpTexB = tex2D(tex0, bumpCoord2).xyz;

half3 vBumpTexC = tex2D(tex0, bumpCoord3).xyz;

half3 vBumpTex = normalize(2.0 * (vBumpTexA.xyz + vBumpTexB.xyz+vBumpTexC.xyz) - 3.0);

上述方法最大的缺点就是对于起伏较大的水面来说,就无能为力了,由于仅仅使用法线来表示水面起伏,因此,当近距离观察时,可以看到水面实际是静止的。为了进一步增加真实性,让顶点真正运动起来是必须的。如何来计算水面运动呢?简单来说,可以把水面运动看作一系列正弦或余弦波的叠加。根据不同的时间和顶点坐标位置,计算出当前顶点的高度。然而,实践中我们却更偏向于适用Gerstner Wave。以下是3D Gerstner Wave的3D波动方程,注意这里的x是一个矢量x(x,z),代表顶点的坐标位置,w为角速度,k为波矢量,k为波数,x0为顶点的初始位置。

从数学角度来看,Gerstner Wave并不比普通的正余弦波动方程复杂,但他的波形却更像水波。对于正余弦波来说,波峰和波谷波的弧度都是均匀的,而实际上水波的波峰要尖一些,波峰则要圆滑。注意上述方程中对给定顶点x0来说,不同时刻,水平位置也是不同的,因此可以正确模拟出这种效果。多个Gerstner Wave相互叠加,就能模拟出相当不错的水面。有了水面高度,进一步对方程求导,就能计算出法线。

有时,你也许需要渲染电影级真实度的水面,那么这种简单波形叠加的方法也许就有些力不从心。可以适用FFT来模拟更真实的水面,它使用了统计波的模型(statistical wave model),通过快速傅立叶(FFT)变换求值。基本的思想是创建一个类似海面的,具有相同频谱的波形域,然后通过傅立叶变换转换到空间域。因此,水体表面实际上就是由许多由风产生的正弦波线性叠加而成。以下是所使用的波形方程:

公式中,h表示t时刻在网格位置 处的水面高度。 表示波矢(wave vector), 的计算公式如下

空间谱(spatial spectrum) 通过过滤复数形式的白噪声(complex white noise)获得:

对FFT生成水面的细节超出了本文讨论范围,但总的来说和Gerstner Wave是类似的,只不过方程更复杂而已。

还值得一提的是用shader mode3中的vertex texture技术,可以把以上两种计算高度的方法放到程序的预处理阶段,运行时直接使用计算好的水面高度图,这样可以大大提高效率。

(混合多个Gerstner wave得到的水面)

 水面颜色

计算水面颜色的方法很多,这里介绍一种简单高效的方法。假设水的颜色只与水面高度和观察着角度有关,那么可以这样计算颜色:

half facing = saturate(dot( eyeVect,normal));

half3 waterColor = lerp(shallowWaterColor,deepWaterColor,facing);

下面是添加了水面颜色的渲染效果:

三. Bump Mapping

仅仅靠的第一部分所说的方法来计算水面顶点位置和法线还不够,它们受到网格间距精度限制,只能模拟波长较长的波。这样的水面太过于平和,而显得不够真实。因此,需要添加Bump Mapping来增加细节和高频波浪。这里可以使用的第一部分仅仅使用normal map模拟水纹的方式,来获得动态bump mapping效果。注意转换到tangent space下进行光照计算。

 反射和折射

反射和折射的思想都一样,以水面为裁减平面,分别把场景渲染为折射和反射帖图,然后投影到水面上。在渲染反射帖图时,需要以水平面为参考面,把摄像机镜像翻转到水面之下。投影纹理时,这里需要用到顶点位置作为参数,来动态调整纹理坐标,反映出水波的流动效果。下图是添加了反射帖图的水面:

五. 菲捏尔效果(Fresnel term

对水面来说,当观察者和水面的角度越小时,反射效果越明显,角度越大时,折射效果越明显,称为菲捏尔效果。所以需要更具观察者的角度来计算反射,折射帖图,以及水面颜色的混合方式。物理上正确的菲捏尔向计算比较复杂,通常使用近似的计算方法就可以了:

fastFresnel = r + ( 1-r ) * pow ( 1.0 – dot ( viewDir, normal ), 5.0);

这里,空气到水面的反射系数约为0.02037。

最终水面颜色为

finalColor = waterColor + reflectionColor * fastFresnel + reftractionColor *  ( 1 – fastFresnel );

六.参考

《Deep-Water Animation and Rendering》

《Simulating Ocean Water》

《Animation and Display of Water》

《Effective Water Simulation form Physical Models》

《Using Vertex Texture Displacement for Realistic Water Rendering》

《Animation and Rendering of Underwater God Rays》

《An Efficient Method for Rendering Underwater Optical Effects Using Graphics Hardware》

《Interactive Animation of Ocean Waves》

《Generic Refraction Simulation》

《Water Effect》

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-08 22:27:48

(转)水面渲染小结的相关文章

Using Vertex Texture Displacement for Realistic Water Rendering

http://blog.csdn.net/soilwork/article/details/709869 Using Vertex Texture Displacement for Realistic Water Rendering(上) 分类: GPU程序设计2006-04-24 14:57 3466人阅读 评论(1) 收藏 举报 floatshader网格fftparameters游戏 最近在研究水面渲染,眼看马上要毕业交论文了,还什么都没有弄,大意了---.Tessendorf  2001

nVIDIA SDK White Paper ----Vertex Texture Fetch Water

http://blog.csdn.net/soilwork/article/details/713842 nVIDIA SDK White Paper ----Vertex Texture Fetch Water 分类: GPU程序设计2006-05-09 04:48 3439人阅读 评论(2) 收藏 举报 shader网格fp数学计算算法blog nVIDIA SDK White Paper Vertex Texture Fetch Water 作者:Jeremy Zelsnack 本文版权归

开源游戏引擎哪家强?八款知名引擎资料够你忙

摘要:游戏引擎是指一些已编写好的可编辑电脑游戏系统或者一些交互式实时图像应用程序的核心组件.本文介绍了几款常见的开源游戏引擎,并附上相关资料. 游戏引擎是指一些已编写好的可编辑电脑游戏系统或者一些交互式实时图像应用程序的核心组件.这些系统为游戏设计者提供各种编写游戏所需的各种工具,其目的在于让游戏设计者能容易和快速地做出游戏程式而不用由零开始.以下介绍了几款常见的开源游戏引擎: OGRE OGRE是一个三维(3D)图形渲染引擎.它是面向对象的,并且高效,抽象化了不同的API和平台,这样可以以场景

随便聊聊水面效果的2D实现(一)

0. 引子 一直想随便写写自己关于水面效果2D实现的一些了解,可惜各种原因一直拖沓,幸而近来有些事情终算告一段落,自己也有了一些闲暇时间,于是便有了这篇东西 :) 1. 概述 关于水面效果的实现方法,google一下非常之多,目前的很多游戏也有非常好的呈现,其中最令我印象深刻的当数<Crysis>~ 自己由于工作原因接触过一段时间的CryEngine,对于Crysis的水面渲染有一点点的了解,当然其中细节非常复杂,但就基本原理来讲,就是将整块水面细分成适当粒度的三角面,然后通过动态改变各个三角

unity渲染层级关系小结

http://blog.csdn.net/meegomeego/article/details/42060389 最近连续遇到了几个绘制图像之间相互遮挡关系不正确的问题,网上查找的信息比较凌乱,所以这里就把自己解决问题中总结的经验记录下来. Unity中的渲染顺序自上而下大致分为三层. 最高层为Camera层,可以在Camera的depth那里设置,设置之后,图形的渲染顺序就是先绘制depth低的相机下的物体,再绘制depth高的相机下的物体,也就是说,depth高的相机会覆盖depth低的相机

探究光栅图像学之水纹渲染与折射滤镜

其实是寒假复习高数时摸索出来的一些小玩意了,一直想整理一下过程,今天就在这里做些简单的讨论吧. 我们经常可以看到一些模拟水纹特效的图像处理程序,在惊叹其效果的同时想必也曾试图解释它们的实现原理吧.我在网上看过一些相关的讨论或博文,从中也获得了不少的启发.今天呢,就在这篇随笔里简洁介绍下我对水纹渲染算法的思考与实现吧. 在图像上模拟水纹产生的折射,乍一看的确让人有种望而生畏的感觉,毕竟水纹这东西看上去就是繁杂而凌乱的,更何况要去分析每一处的光线折射呢?当然,为使得这个看似复杂的问题得以解决我们首先

[转]Asp.Net MVC使用HtmlHelper渲染,并传递FormCollection参数的陷阱

http://www.cnblogs.com/errorif/archive/2012/02/13/2349902.html 在Asp.Net MVC 1.0编程中,我们经常遇见这样的场景,在新建一个对象时候,通过HtmlHelper的方式在View模型中渲染Html控件,当填写完相关内容后,通过Form把需要新建的内容Post回View对应Controller的Action(例如:Create),指定的Action可以通过接受FormCollection参数.值参数或者某个类的实例参数(比如:

排序算法小结

排序算法经过了很长时间的演变,产生了很多种不同的方法.对于初学者来说,对它们进行整理便于理解记忆显得很重要.每种算法都有它特定的使用场合,很难通用.因此,我们很有必要对所有常见的排序算法进行归纳. 我不喜欢死记硬背,我更偏向于弄清来龙去脉,理解性地记忆.比如下面这张图,我们将围绕这张图来思考几个问题. 上面的这张图来自一个PPT.它概括了数据结构中的所有常见的排序算法.现在有以下几个问题: 1.每个算法的思想是什么?     2.每个算法的稳定性怎样?时间复杂度是多少?     3.在什么情况下

有关于OpenGL、OpenGL ES、WebGL的小结

转自原文 有关于OpenGL.OpenGL ES.WebGL的小结 一.   OpenGL简介 OpenGL(全写Open Graphics Library)是个定义了一个跨编程语言.跨平台的编程接口的规格,它用于三维图西象(二维的亦可).OpenGL是个专业的图形程序接口,是一个功能强大,调用方便的底层图形库. 关于其他的介绍我就不说了.这边我说一下有OpenGL的资源网站: OpenGL官网:http://www.opengl.org/resources/libraries/glut/ Ne