(转)透明光照模型与环境贴图

 
 

第11 章 透明光照模型与环境贴图

Snell 定律与Fresnel 定律
光在真空中的速度c 与在透明介质中的速度v 之比,如公式(11-1)所示,称之为该介质的绝对折射率,简称折射率。光在真空中的折射率等于1,通常我们认为光在空气中的折射率也近视为1。

Snell 定律描述光线从一个介质传播到另一个介质时,入射角、折射角和介质折射率的关系。

需要注意:折射率和下面将要阐述的fresnel 折射系数并不是同样的东西。折射率本质上反映的是光在介质中的运行速度,以及折射方向;而fresnel 折射系数反映的是,光在透明介质表面被折射的光通量的比率。

色散
色散分为正常色散和反常色散,通常我们所说的色散都是指反常色散,即,对光波透明的介质,其折射率随着波长的增加而减小。

Fresnel 定律
fresnel 系数指反射系数
我们用Kr表示fresnel 反射系数,用Kt表示折射系数

schlick 给出了Fresnel 反射系数的一个近似

f为入射角度接近0(入射方向靠近法向量)时的Fresnel 反射系数,V 是指向视点的观察方向,H 为半角向量。观察公式(11-3),可以得出一个结论:随着入射角趋近90,反射系数趋近1,即擦地入射时,所有入射光都被反射。

当入射角度接近0 时的fresnel 反射系数的计算方法:

当入射角度接近0 时的fresnel 折射系数的计算方法为:

综合一下,fresnel 反射系数的计算公式为:

如果想动态的计算fresnel 系数,而又不希望消耗太多的时间,可以采用公式:

环境贴图

环境贴图(Environment Mapping, EM)也称为反射贴图(Reflection Mapping),用于模拟光滑表面对周围场景的映射效果

立方体环境贴图:将相机放置在环境的最中央,然后从上、下、左、右、前、后,6 个方向拍摄周围环境,最后将这些信息投影到立方体的6 个面上,所得到的纹理称之为立方体环境贴图。

从视点发射一束射线到反射体上的一个点,然后这束射线以这个点为基准进行反射,并根据反射光线的方向向量检索环境图像的颜色。这就是环境贴图算法的基本思想。

环境贴图算法的步骤如下:
1. 首先根据视线方向和法向量计算反射向量;
2. 然后使用反射向量检索环境贴图上的纹理信息;
3. 最后将该纹理信息融合到当像素颜色中。

环境贴图在Cg 语言中属于smaplerCUBE 类型变量,标准函数库中的texCUBE 函数提供依据反射方向向量检索环境贴图的功能。

实现环境映射效果的着色代程序

  1. void main_v( float4 position: POSITION,  
  2.   float4 normal: NORMAL,  
  3.   out float4 oposition : POSITION,  
  4.   out float3 R : TEXCOORD1,  
  5.   uniform float3 eyePosition,  
  6.   uniform float4x4 modelViewProj,  
  7.   uniform float4x4 modelToWorld)  
  8. {  
  9.   oposition = mul( modelViewProj, position);  
  10.   //计算世界空间中的物体坐标和法向量  
  11.   float3 positionW = mul( modelToWorld, position).xyz;  
  12.   float3 normalW = mul( modelToWorld_IT, normal).xyz;  
  13.   normalW = normalize( normalW);  
  14.   float3 I = positionW - eyePosition;  
  15.   //计算反射光线R.  
  16.   R = reflect( I, normalW );  
  17. }  
  18. void main_f( float3 R : TEXCOORD1,  
  19.   out float4 color : COLOR,  
  20.   uniform samplerCUBE environmentMap)  
  21. {  
  22.   color = texCUBE( environmentMap, R);  
  23. }  

简单透明光照模型

简单的使用颜色调和的方法,即我们最终所看到的颜色,是物体表面的颜色和背景颜色的叠加。

透明物体位于视点与另一个不透明物体之间,透明物体的不透明度为t,点A 为透明物体上的一点,点光源直接照射到A 点上产生的反射光强为Ia ,视线穿过透明体与另一个物体相交处的光强为Ib,则点A 处的最终可观察的光强为:

简单透明光照模型的着色程序如下所示。依然是首先定义结构体,用来包含输入、输出数据流,然后在顶点着色程序中计算顶点投影坐标,并将顶点模型坐标和法向量坐标传递到片段着色程序中,然后在片段着色程序中计算折射光方向向量,并根据折射光向量检索环境贴图,最后按照公式(11-8)进行颜色合成。Cg 标准函数库中的lerp 函数可以提供颜色合成功能

  1. struct VertexIn  
  2. {  
  3.   float4 position : POSITION;  
  4.   float4 normal : NORMAL;  
  5. };  
  6. struct VertexScreen  
  7. {  
  8.   float4 oPosition : POSITION;  
  9.   float4 objectPos : TEXCOORD0;  
  10.   float4 objectNormal : TEXCOORD1;  
  11. };  
  12.   
  13. void main_v(VertexIn posIn,  
  14.   out VertexScreen posOut,  
  15.   uniform float4x4 modelViewProj)  
  16. {  
  17.   posOut.oPosition = mul(modelViewProj, posIn.position);  
  18.   posOut.objectPos = posIn.position;  
  19.   posOut.objectNormal = posIn.normal;  
  20. }  
  21.   
  22. void main_f( VertexScreen posIn,  
  23.   out float4 color : COLOR,  
  24.   uniform float4x4 worldMatrix,  
  25.   uniform float4x4 worldMatrix_IT,  
  26.   uniform float3 globalAmbient,  
  27.   uniform float3 eyePosition,  
  28.   uniform float3 lightPosition,  
  29.   uniform float3 lightColor,  
  30.   uniform float3 Kd,  
  31.   uniform float3 Ks,  
  32.   uniform float shininess,  
  33.   uniform float etaRatio, //折射系数  
  34.   uniform float transmittance, //透明度  
  35.   uniform samplerCUBE environmentMap //环境贴图  
  36. )  
  37. {  
  38.   float3 worldPos = mul(worldMatrix, posIn.objectPos).xyz;  
  39.   float3 N = mul(worldMatrix_IT, posIn.objectNormal).xyz;  
  40.   N = normalize(N);  
  41.   //计算入射光方向/视线方向/半角向量  
  42.   float3 L = normalize(lightPosition - worldPos);  
  43.   float3 V = normalize(eyePosition - worldPos);  
  44.   float3 H = normalize(L + V);  
  45.   // 计算漫反射分量、镜面反射分量  
  46.   float3 diffuseColor = Kd * globalAmbient+Kd*lightColor*max(dot(N, L), 0);  
  47.   float3 specularColor = Ks * lightColor*pow(max(dot(N, H), 0), shininess);  
  48.   float3 reflectColor = diffuseColor+specularColor;  
  49.   //计算折射光线的方向,注意refract 的输入参数!  
  50.   float3 I = normalize(worldPos - eyePosition);  
  51.   float3 T = refract(I, N, etaRatio);  
  52. //根据折射光线的方向,检索环境贴图上的颜色信息  
  53.   float3 refractedColor = texCUBE(environmentMap, T).xyz;  
  54.   color.xyz = lerp(reflectColor, refractedColor, transmittance);  
  55.   color.w = 1;  
  56. }  

 http://blog.csdn.net/doctorsc/article/details/6288588

原文地址:https://www.cnblogs.com/aminxu/p/4274861.html