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:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2011-06-24 std::set用法(转)
2011-06-24 STL中map用法详解(转)