我必须对菲涅尔效应进行建模,但我认为结果不正确。我能够计算出反射光线和透射光线。我的代码是用JavaScript编写的。
function shade(objPoint,ray,depth){
color = rgb(0,0,0);
shadowRay = calc_shadowRay(objPoint,light);
if(!inShadow(shadowRay,objPoint))
color = summvv(color,lighting_object(objPoint.closestPoint,objPoint.object,light,ray));
if(depth <= 3){
if(objPoint.object.material.kr > 0.0 && objPoint.object.type == "sphera"){
nHit = normalize(diff(objPoint.closestPoint,objPoint.object.o));
outside = dot(nHit,ray.d) < 0;
bs = prodvs(nHit,bias);
reflectedRay = new Object();
reflectedRay.o =(!outside)? diff(objPoint.closestPoint,bs):summvv(objPoint.closestPoint,bs);
reflectedRay.d = normalize(calc_reflectedRay(ray,nHit));
reflectionColor = trace(reflectedRay,++depth).color;
color = summvv(color, prodvs(reflectionColor,objPoint.object.material.kr));
}
if(objPoint.object.material.kt > 0.0 && objPoint.object.type == "sphera"){
nHit = normalize(diff(objPoint.closestPoint,objPoint.object.o));
outside = dot(nHit,ray.d) < 0;
bs = prodvs(nHit,bias);
fe = fresnel(ray,nHit);
reflectedRay = new Object();
reflectedRay.o = (!outside)? diff(objPoint.closestPoint,bs):summvv(objPoint.closestPoint,bs);
reflectedRay.d = normalize(calc_reflectedRay(ray,nHit));
reflectionColor = trace(reflectedRay,++depth).color;
if(fe < 1){
refractedRay = new Object();
refractedRay.o = (outside)? diff(objPoint.closestPoint,bs):summvv(objPoint.closestPoint,bs);
dirRefraction = calc_refractedRay(ray,nHit);
refractedRay.d = normalize(dirRefraction);
refractionColor = trace(refractedRay,++depth).color;
}
rfl = prodvs(reflectionColor,fe);
rfr = prodvs(refractionColor,1-fe);
finalColor = summvv(rfl,rfr);
color = summvv(color,finalColor);
}
}
计算菲涅尔效应:
function fresnel(_ray,nHit){
cosi = clamp(dot(nHit,_ray.d),-1,1);
etai = 1.0; etat = 1.3;
if(cosi > 0){
temp = etai;
etai = etat;
etat = temp;
}
eta = etai/etat;
sint = eta * Math.sqrt(1 - cosi*cosi);
if(sint >= 1) return 1.0;
else{
cost = Math.sqrt(1 - sint*sint);
cosi = Math.abs(cosi);
Lperp = (etai*cosi - etat*cost)/(etai*cosi + etat*cost);
Lparal = (etat*cosi - etai*cost)/(etat*cosi + etai*cost);
return (Lperp*Lperp + Lparal*Lparal)/2.0;
}
}
计算折射光线是:
function calc_refractedRay(_ray,nHit){
cosi = clamp(dot(nHit,_ray.d),-1,1);
etai = 1.0; etat = 1.3;
if(cosi < 0) cosi = -cosi;
else{
nHit = prodvs(nHit,-1);
temp = etai;
etai = etat;
etat = temp;
}
eta = etai/etat;
cost2 = 1 - eta*eta*(1 - cosi*cosi);
if(cost2 < 0) return;
else return summvv(prodvs(_ray.d,eta) , prodvs(nHit , (eta*cosi - Math.sqrt(cost2))));
}
生成的图像如下:
我无法理解为什么它是正确的。