water Caustics

  水下环境的模拟在现阶段的计算能力下,Jos Stam(https://www.opengl.org/archives/resources/code/samples/mjktips/caustics/) 提出的方法是预先计算多张caustics图,根据时间选取不同的图片,然后与水下模型进行混合。在underWater.c中,

glEnable(GL_BLEND); 

glBlendFunc(GL_ZERO, GL_SRC_COLOR);

上面这两行代表绘制时与现有模型进行颜色混合。

GLfloat sPlane[4] = { 0.05, 0.03, 0.0, 0.0 };

GLfloat tPlane[4] = { 0.0, 0.03, 0.05, 0.0 };

glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);

glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);

glTexGenfv(GL_S, GL_OBJECT_PLANE, sPlane);

glTexGenfv(GL_T, GL_OBJECT_PLANE, tPlane);

glEnable(GL_TEXTURE_GEN_S);

glEnable(GL_TEXTURE_GEN_T);

glEnable(GL_TEXTURE_2D);

代表着caustics纹理坐标的计算,可以看到sPlane和tPlane的Y值并不为0,首先我们设置Y0时cube的效果,这时候cube的竖直面没有ripple效果,这是因为纹理坐标在Y值没有偏移时,X,Z一致值取得的caustics纹理坐标完全一样。左图是Y值为0的情况,右图是Y值不为0的情况。

                                                                  

 

  在GpuGem中,文章用一种简单的构造折射向量的方式来计算纹理的映射,用来映射的纹理就是 sun map,方法分为三步:

1.构造入射向量。

2.根据波当前处理的顶点位置和顶点法线来计算折射向量。

3.根据折射向量来计算映射的纹理坐标。

在计算光照折射效果之前,需要利用波公式来构建波,这里所用的wave function 如下:

下面就是该函数的实现部分:

float func(float x,float z)
{
float y=0;float factor=1;
float d=sqrt(x*x+z*z);
d=d/40;
if (d>1.5) d=1.5;
if (d<0) d=0;
for (int i=0;i){y-=    (factor)*VTXSIZE*d*cos(((float)timer*SPEED)+(1/factor)*x*z*WAVESIZE)+(factor)*VTXSIZE*d*cos(((float)timer*SPEED)+(1/factor)*(x*z)*WAVESIZE) ;//y-=factor*VTXSIZE*d*noise((float)(x*(1/factor))/5,SPEED*timer,(float)z*(1/factor)/5);factor=factor/1.7;        }return y;
}

而在波纹理的构造过程中,主要使用下面的公式进行纹理坐标的计算。

 

double plane::testline(point r,point vec,point &pres)
// return value is distance along the line to the collision point
{
// a*x +b*y+c*z+d =0为平面构造公式,r为波的顶点坐标,vec为顶点的法线,该方法主要
//是求pres,也就是平面与顶点和法线构造的直线相交点。
double fres;
double t;//fres = |vec|*|n|cos(Q) 
fres=vec*n;
pres=r;
if ((fres)!=0){
// r到平面的距离公式= |a*r.x + b*r.y+c*r.z +d|/(sqrt(a*a+b*b+c*c)) = |n*r+d|
// cos(Q) = (nr+d)/t = fres/(|vec|*|n|)t=-(n*r + d)/fres;
//pres相交点。pres=r+vec*t;}
// hack... arreglar
else t=0;
return t;
}

 最后计算的是折射光线的效果,原始的snell’s law计算方法不太适用于计算机计算,Foley等在1996提出了下面一个便于计算的公式。

其中n代表面的法线方向,E为入射向量, h 1/ h 2  是折射率,计算的函数如下。

void sample_caustic(float xi,float zi,float &u,float &v)
// here's the main stuff for the caustic
{
point p(xi,0,zi);p.y=func(xi,zi);
point q(xi+QUADSIZE,0,zi);q.y=func(xi+1,zi);
point r(xi,0,zi+QUADSIZE);r.y=func(xi,zi+1);point e1=q-p; point e2=r-p;    point n=e1^e2;    // the normal above the sampling point 
u=0; v=0;
for (int i=0;i){float alpha=6.28*(float)i/numrays;float rad=(float)i/numrays;float xf=rad*cos(alpha)/2.0;float zf=rad*sin(alpha)/2.0;//构造入射向量point incident(xf,1,zf);float c=incident*n;float sq=1+(IOR*IOR*(c*c-1));if (sq>0) sq=sqrt(sq); else sq=0;//折射向量的计算。point transmitted=incident*IOR + n*(IOR*c-sq);transmitted.normalize();u+=transmitted.x;v+=transmitted.z;}
u=4*(u/numrays) + 0.5;
v=4*(v/numrays) + 0.5;    
}

  最后比较几张wave function 中octaves参数从1到3的情况。

转载于:https://www.cnblogs.com/VanHu/p/4901558.html


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部