先来几个图:
首先需要有一个单位球,球心就放在摄像机处,随时保持。
接下来载入我们的立方体贴图,当然是已经做好的,然后贴到球上,注意关掉ZWRITE和背面裁剪,这样就完成一个静态的环境贴图了。
如果要做动态的,那么需要自己渲染出一个立方体贴图,这时需要将摄像机放到要做反射折射的物体中心,以90度的FOV,绘制所观察到的景物到立方体贴图的每个面上,这样可以保证立方体贴图的无缝连接,自然就需要上下左右地绘制6次,来生成一个实时的立方体贴图。
反射跟做镜面高光时是一个道理,镜面高光是光源发射的光线碰到光滑表面后以一定角度反射进观察者的眼睛,而做环境的反射则是把周围的环境都看做了光源,也就是周围的每个像素都是一个光源,他们发出的光经过反射到达观察者的眼睛。
在做环境的反射时,当然不能把周围所有像素都考虑进来,只需要考虑观察者能看见的像素,这就需要把做镜面反射的过程颠倒过来,从视线向量出发经过物体表面,求出反射向量,然后用反射向量找到环境贴图,也就是立方贴图上的像素,再渲染到物体表面。
光线穿过透明的介质看到后面的物体,由于折射,看到的物体的位置和形状是有偏差的。
折射依靠折射定律,也就是斯涅尔定律。不同介质对光的折射率不同,不同波长的光在同一介质中折射率也不同。
设入射向量为A,入射角为θ1,入射光线所在介质为n1,出射向量为B,出射角为θ2,法向量为N那么
sinθ1/sinθ2=n2/n1
得到A后,也就是视线向量,也就很容易根据折射定律得到出射向量B与法线的夹角的正弦和余弦,但是还没有得到出射向量,由于入射向量,法向量,出射向量是在同一平面上,可以由叉乘的方法确定出平面的两个正交的基向量,这样就可以确定出出射向量了。
具体方法是:
负法向量作为x轴基向量x,垂直向下,AXN得到垂直于平面的向量C,CXN就得到了y轴基向量y。
于是出射向量B=x*cosinθ2+y*sinθ2
最后再使用出射向量到立方体贴图上取到对应像素,再渲染到物体表面就OK。
菲涅耳近似:当角度在光线和表面法线之间角度值接近0度时,反射将衰减(当光线几乎平行于表面时,反射可见性最大。而折射减小甚至消失,当光线垂直于表面时几乎没反射发生。 )
这就像在看水面时,垂直看下去,可以清楚的看到水中的物体,除非水太混了,而当视线与水平面夹角非常小时,将看不到水中物体,而水面变得像镜子一般。
反射和折射的强度通过sinθ1和sinθ2来近似地控制
最后物体表面颜色=sinθ1 * reflection + (1 - sinθ2) * refraction + ambient;
可以看出,公式呈现出了以上现象。ambient是一个调整颜色亮度的参数,因为通常这个计算会导致物体表面颜色变暗。
只求漂亮,不求技术含量