http://blog.csdn.net/a3070173/archive/2008/11/04/3221181.aspx
相信使用OpenGl或DirectX3D的朋友都知道到固定功能管线在光照处理主要由环境光,散射光和镜面光构成,这样一个光照处理模型在被光 的地方将以统一的环境光进行着色,导致一种不自然的不真实效果.本文介绍的Ambient Occlusion方法将使用不当预计算的方式离线的生成模型的AO图,并在片元着色器中将对此AO图进行采样的结果与环境光和散射光效果进行相乘以适当 削弱环境光和散射光的强度,以增加模型的真实感.
那么什么是AO图呢?AO图其实是Ambient Occlusion纹理图的简称,其包含了模型各顶点的AO因子(即削弱因子).关于此削弱因子是如何计算的请参考http://www.ozone3d.net/tutorials/ambient_occlusion.php.这里只介绍效果的具体实现.
 由于这个效果主要在GLSL着色器上进行实现所以以下贴出的Ambient Occlusion着色器代码. 
 顶点着色器: 
uniform float g_fScale; 
varying vec2 g_vec2TexCoord0; 
varying vec3 g_vec3Normal; 
varying vec3 g_vec3Vertex; 
void main() 
{ 
 g_vec2TexCoord0 = vec2(gl_MultiTexCoord0.s, 1.0 - gl_MultiTexCoord0.t); 
 g_vec3Normal = vec3(gl_Normal); 
    g_vec3Vertex = vec3(gl_Vertex); 
    gl_Position = ftransform(); 
} 
 片元着色器: 
const vec3 g_vec3AmbientResult = vec3(0.2, 0.2, 0.2); 
const vec3 g_vec3DiffuseResult = vec3(0.64, 0.64, 0.64); 
const vec3 g_vec3SpecularResult = vec3(1.0, 1.0, 1.0); 
const float g_fShininess = 100.0; 
uniform vec3 g_vec3CameraPositinInModel; // 模型空间照相机位置 
uniform vec3 g_vec3LightPositionInModel; // 模型空间光源位置 
uniform sampler2D g_AmbientOcclusion;
uniform bool g_bUseAmbientGene; // 是否使用Ambient Occlusion的标志
varying vec2 g_vec2TexCoord0; 
varying vec3 g_vec3Normal; 
varying vec3 g_vec3Vertex; 
void main() 
{ 
 // 采样Ambient Occlusion因子 
 float fAmbientGene = texture2D(g_AmbientOcclusion, g_vec2TexCoord0).r; 
 // 计算散射因子 
 vec3 L = normalize(g_vec3LightPositionInModel - g_vec3Vertex); 
 vec3 N = normalize(g_vec3Normal); 
 float fDiffuseGene = max(dot(N, L), 0.0); 
 // 计算镜面光因子 
 float fSpecularGene = 0.0; 
 if (fDiffuseGene > 0.0) 
 { 
  vec3 V = normalize(g_vec3CameraPositinInModel - g_vec3Vertex); 
  vec3 H = normalize(L + V); 
  fSpecularGene = pow(max(dot(N, H), 0.0), g_fShininess); 
 } 
 // 计算最终颜色      
 if (g_bUseAmbientGene) 
 { 
  // Ambient Occlusion只影响环境和散射选项 
  gl_FragColor = vec4(fAmbientGene*(g_vec3AmbientResult +  
      fDiffuseGene*g_vec3DiffuseResult) + 
      fSpecularGene*g_vec3SpecularResult, 
      1.0); 
 } 
 else 
 { 
  gl_FragColor = vec4(g_vec3AmbientResult +  
      fDiffuseGene*g_vec3DiffuseResult + 
      fSpecularGene*g_vec3SpecularResult, 
      1.0); 
 } 
} 
 在整个着色过程中唯一需要注意的是由于AO图是上下颠倒的,所以带计算纹理坐标时需要将t坐标被1.0f相减. 
 Demo效果图: 
 不启动Ambient Occlusion: 

 
 启动Ambient Occlusion:
 
GLSL实现Ambient Occlusion 【转】,布布扣,bubuko.com
原文地址:http://www.cnblogs.com/mazhenyu/p/3806609.html