这些天都在着手实现一些水面效果,于是还是记录一下历程吧,本Blog不是为此而存在的么。——ZwqXin.com
学期初看了橙书关于反射折射一节,心想我也能尝试一下做水的效果吗,于是就开始动手。但是专业学习上的东西实在太多了,刚起了个头,后面又被时间挤兑着了。看着自己不断地浪费时间,而这东西有点胎死腹中的味道……委实感觉不能让悲剧重演,于是假期来临后马上继续。
本文来源于 ZwqXin (http://www.zwqxin.cn/), 转载请注明
原文地址:http://www.zwqxin.cn/archives/opengl/water-simulation-1.html
DEMO的环境很简单,也是一般尝试水效的朋友必用的天空盒+水池。但是我这人就有点怪,喜欢瞎折腾,于是就不想只是弄个矩形水池来契合矩形水网格,来个特别形状的如何?——譬如五角星形的。网格我可不想弄成怪模样的,毕竟连索引起来也困难,还是矩形网格好。那么,即使我画出五角星形水池,它怎么与矩形网格配合呢?
首先是构造水池。这纯粹是考平面几何的功夫。好吧我还是很菜的,搞了大半天才画出来。把水池作为一个水池类对象看待的话,其属性除了中心位置和绕中心的旋转外,应该还有:角的数目(譬如五角星形是5,六角星形是6,如此),内接圆外接圆半径,池宽比例(池的壁厚由这个比例决定)等等:
- //
- GLuint PoolTex;
- Color PoolColor;
- GLint AngleNum; //池型等分之角数,例如五角型,六角型
- float Radius_inscribe; //池型的内接圆半径
- float Radius_circumscribe; //池型的外接圆半径
- float Height; //池高
- float Width_Scale; //池宽比例
这样通过调节这些属性能改变池的形状,当初放弃建模的想法还是正确的。那么加入水网格之后又如何呢?
可见要得到一个“水池”就需要把五角星外的部分割掉~事实上我们可以利用shader(想不到这么快就上场了),要传入的是形状的角顶点,譬如五角星的五个角的坐标,以及这五个角到水池中心(物理坐标原点)的向量Vi,还有中心到角的距离D[外接圆半径],每个角的角度ANG的COS(ANG)。计算的时候让Y值为0即可。因为暂时程序就用五角星了,所以我也不在shader上扩展,直接把这5 * 2个量传入shader。在像素shader里经过插值的顶点坐标成为“像素坐标”,求得角点坐标与这个像素坐标之间的向量,与传入的Vi分别求内积得到夹角的COS,并与传入的COS(ANG)比较,若前者大,且该“像素坐标”到原点的距离比D小,则证明该像素点在五角星内部……对于此测试不通过的像素discard,最后稍微调整边界等,就能得到如下结果了:
在线框图中可以看到对应的顶点已经被割裂了。这样池水就在水池里面啦~
最后解释一下网格的纹理。很明显这里有张水纹理直接贴上去,但也有其他的——反射和折射。详细的实现思路可参见我的这篇日志:
[Shader快速复习:Reflection And Refraction(反射与折射)]
shader实现是一致的,关键只是我们在程序中构建一个CUBEMAP而已。关于CUBEMAP的创建就不多说了,网路上到处都有,经典的是NVIDIA这篇~ Cube Map OpenGL Tutorial
下篇继续,见 水效果Ⅱ - 涟漪
本文来源于 ZwqXin (http://www.zwqxin.cn/), 转载请注明
原文地址:http://www.zwqxin.cn/archives/opengl/water-simulation-1.html