建模中什么是AO?

2021-03-25
7497
0

今天分享一篇AO科普。AO:Ambient Occlusion,环境光遮蔽。主要是描述了表面上的任何一点所接受到的环境光被周围几何体所遮蔽的百分比,因此使得渲染的结果更加富有层次感,对比度更高。如下来自wiki的效果对比:

Unreal | AO那些事

 

在脸上有皱纹的地方给加了阴影细节,整个脸就更加立体和有层次。而且AO可以解决漏光,阴影漂浮等问题,会改善场景中角落,锯齿,裂缝等细小物体阴影不清晰等问题,增强场景的深度和立体感。

 

而我们常说的AO是指写在材质里面的AO贴图,但是材质里面的AO贴图并不会被写入到Gbuffer中,而是会被叠加到lightmap,stationary sky light和reflection capture specular中去,其他的动态间接光比如说ambient cube和movable sky不会对它产生任何影响。所以在引擎里面没有办法直接预览。(通过Buffer Visualization>Material Ambient Occlusion得不到正确的效果)

Unreal | AO那些事

 

而在引擎的预览窗口里面还有另外一个选项Ambient Occlusion。

Unreal | AO那些事

 

可以看到这个Ambient Occlusion是有效果的。

Unreal | AO那些事

 

然而这个AO效果并不是材质贴图里面的AO,而是unreal自带的场景AO,Screen Space Ambient Occlusion,简称SSAO。

 

可以在尝试一下如果把Show>Lighting Features>Screen Space Ambient Occlusion关掉,场景里面就没有AO效果了。

Unreal | AO那些事

 

所以我们现在来叨一下SSAO的原理以及计算方法。

 

SSAO是屏幕空间的AO,也就是不是场景的预处理,是屏幕后期处理,根据OpenGL的算法,要得到SSAO,

 

首先需要解算AO,然后进行blur,最后再通过lighting pass叠加到物体上。

Unreal | AO那些事

 

1计算AO

 

计算AO的方法是根据每个点切线空间的切线法线为中心,画一个半球,然后随机采样半球里面的点,判断如果这些点的深度大于中心点的深度,就说明采样点被遮挡了,反之采样点没有被遮挡。

Unreal | AO那些事

 

图中灰色的圆圈就是被遮挡的采样点,然后再将所有的采样点用采样系数(离中心点越近采样点系数越大)叠加起来,得到的就是最后中心点的遮蔽值。

 

这里贴一个采样算法显得比较专业:

 


std::uniform_real_distributionrandomFloats(0.0, 1.0); // 随机浮点数,范围0.0 - 1.0

std::default_random_engine generator;

std::vectorssaoKernel;

for (GLuint i = 0; i < 64; i)

{

glm::vec3 sample(

randomFloats(generator) * 2.0 - 1.0,

randomFloats(generator) * 2.0 - 1.0,

randomFloats(generator)

);

sample = glm::normalize(sample);

sample *= randomFloats(generator);

GLfloat scale = GLfloat(i) / 64.0;

ssaoKernel.push_back(sample);

}

 

2模糊AO

 

需要对ao进行模糊的原因是上述采样得到的AO效果很噪,所以为了创建一个光滑的环境遮蔽结果,我们需要模糊环境遮蔽纹理。

 

而模糊的办法可以用高斯模糊,或者使用另外一种类似高斯模糊的办法,就是在用中心点与采样点的uv坐标距离,法线和深度关系共同得到采样系数,距离越远采样系数越小,法线和深度的差距越大采样系数也越大。然后再用高斯模糊的办法偏移每一个坐标并且得到平均的结果就是高斯模糊的效果。

 

3混合

 

应用所得的AO值得办法就是将逐片段AO乘到光照环境分量上,得到加了光照的片段着色器。

 

#version 330 core

out vec4 FragColor;

in vec2 TexCoords;

 

uniform sampler2D gPositionDepth;

uniform sampler2D gNormal;

uniform sampler2D gAlbedo;

uniform sampler2D ssao;

 

struct Light {

vec3 Position;

vec3 Color;

 

float Linear;

float Quadratic;

float Radius;

};

uniform Light light;

 

void main()

{

// 从G缓冲中提取数据

vec3 FragPos = texture(gPositionDepth, TexCoords).rgb;

vec3 Normal = texture(gNormal, TexCoords).rgb;

vec3 Diffuse = texture(gAlbedo, TexCoords).rgb;

float AmbientOcclusion = texture(ssao, TexCoords).r;

 

// Blinn-Phong (观察空间中)

vec3 ambient = vec3(0.3 * AmbientOcclusion); // 这里我们加上遮蔽因子

vec3 lighting = ambient;

vec3 viewDir = normalize(-FragPos); // Viewpos 为 (0.0.0),在观察空间中

// 漫反射

vec3 lightDir = normalize(light.Position - FragPos);

vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * light.Color;

// 镜面

vec3 halfwayDir = normalize(lightDir viewDir);

float spec = pow(max(dot(Normal, halfwayDir), 0.0), 8.0);

vec3 specular = light.Color * spec;

// 衰减

float dist = length(light.Position - FragPos);

float attenuation = 1.0 / (1.0 light.Linear * dist light.Quadratic * dist * dist);

diffuse *= attenuation;

specular *= attenuation;

lighting = diffuse specular;

 

FragColor = vec4(lighting, 1.0);

}

 

以上就是SSAO的一个大概解算过程,所以就算不给模型单独添加AO贴图,都可以得到AO效果。而这种SSAO还是会存在一些问题,比如说阴影清晰度和画质不高,所以在与不具备AO特效的场景相比时,图像质量的提升并不大。所以下一节我们研究一下升级版本的HBAO以及最新的HBAO

 

转载声明:本文来源于网络,不作任何商业用途

免责声明:本文内部分内容来自网络,所涉绘画作品及文字版权与著作权归原作者,若有侵权或异议请联系我们处理。
收藏

全部评论

您还没登录

暂无留言,赶紧抢占沙发
绘学霸是国内专业的CG数字艺术设计线上线下学习平台,在绘学霸有2D绘画、3D模型、影视后期、动画、特效等数字艺术培训课程,也有学习资源下载,还有行业社区交流。学习、交流,来绘学霸就对了。
绘学霸iOS端二维码

IOS下载

绘学霸安卓端二维码

安卓下载

绘学霸微信小程序二维码

小程序

版权声明
本网站所有产品设计、功能及展示形式,均已受版权或产权保护,任何公司及个人不得以任何方式复制部分或全部,违者将依法追究责任,特此声明。
热线电话
18026259035
咨询时间:9:00~21:00
在线客服
联系网站客服
客服微信:18026259035
公司地址
中国·广州
广州市海珠区晓港中马路130号之19
绘学霸客户端(权限暂无,用于CG资源与教程交流分享)
开发者:广州王氏软件科技有限公司 | 应用版本:Android:6.0,IOS:5.1 | App隐私政策> | 应用权限 | 更新时间:2020.1.6