摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文 名“GPU编程与CG语言之阳春白雪下里巴人”
环境贴图( Environment Mapping, EM )也称为反射贴图( Reflection Mapping ),用于模拟光滑表面对周围场景的映射效果,这项技术由 Blinn 和 Newell 于 1976 在文献【 10 】中提出。
本节中首先说明什么是环境贴图,然后阐述如何使用环境贴图模拟光滑表面对周围场景的映射效果。
环境贴图,顾名思义,在一副图片上展现周围的环境。环境贴图假设进行反射的光源和物体都位于很远的位置,同时反射体不会反射自身。最常被用到的环境贴图是立方体环境贴图,由 Greece 于 1986 年在文献【 11 】中提出。该方法是将相机放置在环境的最中央,然后从上、下、左、右、前、后, 6 个方向拍摄周围环境,最后将这些信息投影到立方体的 6 个面上,所得到的纹理称之为立方体环境贴图。
环境贴图的文件表现形式是一种纹理类型,例如立方体环境贴图在 DirectX 中可以保存为 .dds 格式,也很多开源图形引擎中使用 6 个方向上的二维纹理动态组成环境贴图。
如下 图 30 所示,这是 OGRE 图形引擎中提供的 2 组环境贴图。
除了立方体环境贴图,还有球面贴图、抛物面贴图。不过这两种贴图类型,与立方体环境贴图相比没有明显的优势。有兴趣的同学,可以参阅《实时计算机图形学第 2 版第 5.7.4 节》。
使用环境贴图,是为了模拟光滑表面对周围场景的映射效果。光滑表面对周围场景的映射,是由从场景出发的光线投射到光滑表面上然后被反射到人眼所形成的视觉效果,如 图 31 所示。
我们将这个过程倒退回去,从视点发射一束射线到反射体上的一个点,然后这束射线以这个点为基准进行反射,并根据反射光线的方向向量检索环境图像的颜色。这就是环境贴图算法的基本思想。
环境贴图算法的步骤如下:
1. 首先根据视线方向和法向量计算反射向量;
2. 然后使用反射向量检索环境贴图上的纹理信息;
3. 最后将该纹理信息融合到当像素颜色中。
环境贴图在 Cg 语言中属于 smaplerCUBE 类型变量,标准函数库中的 texCUBE 函数提供依据反射方向向量检索环境贴图的功能。
在代码 12 是使用立方体环境贴图实现环境映射效果的着色程序代码。在顶点着色程序中计算反射光线方向向量,然后传递到片段着色程序中,在片段着色程序中利用该方向检索环境贴图,获取纹理颜色,并进行片段赋值。整个实现过程非常简练。
代码 12 实现环境映射效果的着色代程序
void main_v( float4 position: POSITION,
float4 normal: NORMAL,
out float4 oposition : POSITION,
out float3 R : TEXCOORD1,
uniform float3 eyePosition,
uniform float4x4 modelViewProj,
uniform float4x4 modelToWorld)
{
oposition = mul( modelViewProj, position);
// 计算世界空间中的物体坐标和法向量
float3 positionW = mul( modelToWorld, position).xyz;
float3 normalW = mul( modelToWorld_IT, normal).xyz;
normalW = normalize( normalW);
float3 I = positionW - eyePosition;
// 计算反射光线 R.
R = reflect( I, normalW );
}
void main_f( float3 R : TEXCOORD1,
out float4 color : COLOR,
uniform samplerCUBE environmentMap)
{
color = texCUBE( environmentMap, R);
}
渲染效果如图 32 所示: