zoukankan      html  css  js  c++  java
  • GLSL实现Ambient Occlusion 【转】

    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:

     

  • 相关阅读:
    CentOS查看系统信息和资源使用已经升级系统的命令
    192M内存的VPS,安装Centos 6 minimal x86,无法安装node.js
    Linux限制资源使用的方法
    多域名绑定同一IP地址,Node.js来实现
    iOS 百度地图大头针使用
    iOS 从app跳转到Safari、从app打开电话呼叫
    设置cell背景色半透明
    AsyncSocket 使用
    iOS 监听键盘变化
    iOS 7 标签栏控制器进行模态视图跳转后变成透明
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/3806609.html
Copyright © 2011-2022 走看看