4.5 反射
4.5.1静态立方体贴图
反射如果水面不需要反射所有东西,可以使用预生成的立方贴图计算反射的颜色。立方贴图是一种可以硬件加速的纹理贴图(其他还有sphere mapping 和 dual paraboloid mapping),可以把它看出一个六个面都有图片的普通立方体,这些图片都是从立方体中心拍摄的照片,它们显示了从周围环境向对应方向观察的景象,图4-17是一个立方体贴图的例子:
如图4-18所示,立方体贴图的六个面由三个坐标轴命名:x、 y、z和负x、 y、z 方向:
如果有了立方贴图和水的反射面,我们就可以计算从水面上的点指向反射物体的向量,使用这个三维向量(如图中红色箭头所示)可以确定从立方体中心出发的对应纹理坐标的位置,这个向量指向立方体上的一个点,而这个点具有与反射物体相同的颜色。为每个点计算全局光照要花费长得多的时间, 但这个计算有效率得多,并可以使用硬件加速满足实时渲染的需要。使用立方贴图还有一个优点是:立方体的有些面相机是不可见的,但即使有些点在相机背后也能反射。另一方面,如果你想反射动态环境(比如移动的物体),立方贴图没必要一定要预渲染。使用这个技术,天空盒可以很容易地反射在水面,但要渲染水面上移动的船需要另一种方式。另外在立方贴图边缘会有错误,这很难避免。图片来自于:
http://www.cescg.org/CESCG-2002/GSchroecker/node14.html
和
http://www.modwiki.net/wiki/Cube_maps
4.5.2动态立方贴图
要反射动态环境需要更新立方贴图。因为立方贴图是每个面上六张图片的集合,所以要创建动态立方贴图需要依次绘制这些纹理。我们需要渲染场景6次,每次一个面,设置相机使它匹配对应每个面的视点。改变相机位置不难,但视场(FOV)需要调整到相同尺寸,正方形图片在场景中都是相同的,因为水面相对比环境大,不同的物体需要以相同的方向反射到水面的不同位置,这意味着仅有一个立方贴图不足以模拟水面的实时反射,每帧创建多个立方贴图代价昂贵,所以对今天的显卡来说,动态立方贴图不是一个好的选择。
虽然相当复杂,但还是有几个解决方案的。如在Half Life 2中,从水面的不同位置使用多个动态立方贴图,而反射的数据是从已经存储的变量中插值得到的。要能实现实时渲染,可以每秒只生成几次立方贴图。
4.5.3将反射渲染到纹理
在第二章的数学知识中我介绍了如何获取水面上每个点的反射颜色,最关键的地方就是在水面的对称位置创建一个虚拟视点,并将场景渲染到一个纹理中用于后面的反射贴图。这意味着在渲染最终图片前需要添加一个预渲染过程,在这个过程中,相机位置和视向量是水面的镜像,能被水面反射的每个物体是从虚拟视点的纹理中获得的,让我们再次看一下图4-19:
要获得预期效果,应先计算B点位置,要做到这点,我们必须知道相机离开水面的距离即图中的k。如果水面是水平的,这个距离要减去水面高度以获得高度坐标,A点和B点的其他坐标是相同的。为了避免出错,在渲染到纹理前应先移去水下的物体。当最终图片生成后,这个纹理就可以作为反射贴图了,反射的颜色可以简单地通过相机和水面上对应点的向量采样得到,水的形状也可采用同样的思路得到。要获得更好的效果需要进行微调,例如在水面上调整高度或微调B点的位置。
参考可见:
http://developer.nvidia.com/object/cube_map_ogl_tutorial.html
http://www.mpinf.mpg.de/departments/irg3/ws0405/cg/rcomp/09/doc/aufgaben.pdf
http://forums.xna.com/thread/7619.aspx
发布时间:2009/4/22 下午4:24:03 阅读次数:6592