webgl水面的实现,最简单的方法就是通过贴图置换,顶点的计算可通过简单的正弦曲线公式计算,但效果不是狠逼真,于是有了另一种的实现方法:基于opengl着色器语言,编写shader程序,使用frameBuffer离屏不停的切换多个program,最终绘制出一张纹理图,使用该纹理图进行屏幕绘制,对于光在水面的折射和反射利用texture进行map映射,r通道的值的大小用于计算法向量和波的高度,方便计算折射反射光方向向量,最终显示的颜色是漫反射颜色和环境光反射颜色通过菲涅尔公式做线性插值。然后通过线与面求交判断光线是否投射到水面上。由于重点是shader的实现,所以接下来着重减少shader的实现,效果示例请访问水面demo。
- wave.glsl渲染水花和波浪。
如下是为了渲染出波浪效果,当然麻烦的话还可直接用一张水面波texture绘制。
void createRipple(inout vec4 info){
float dy=swing*len/2.;
float lineWidth=lineWidth;
vec2 endP=startP+vec2(len, dy+lineWidth);
if (coord.x>=startP.x&&coord.x<=endP.x&&coord.y>=startP.y&&coord.y<=endP.y){
float r=sin(startAngle+(coord.x-startP.x)/len*PI*period)*dy+startP.y;
lineWidth-=(1.-(r-startP.y))*lineWidth;//两端宽度随cos曲线变小
if ((coord.y<r||coord.y>r+lineWidth)){
//把coord坐标限制到曲面上
if (info.r==0.){
discard;
}
} else {
r=cos(</