【技美百人计划】图形 4.2 SSAO算法 屏幕空间环境光遮蔽(&HBAO)
笔记
SSAO介绍
AO
环境光遮蔽,AmbientOcclusion。一种模拟光线到达物体的能力和粗略的全局方法。
SSAO
屏幕环境光遮蔽,Screen Space Ambient Occlusion, 一种实现环境光遮蔽遮蔽效果的渲染技术。通过获取像素的深度缓冲、法线缓冲来计算实现,来近似的表现物体在间接光下产生的阴影
历史
AO在Siggraph 2002年会由ILM展示
2007年,Crytek将SSAO应用于孤岛危机
原理
- 获取深度、法线缓冲
- 利用深度值,反推每个像素在世界空间中的三维位置
- 利用法线,得到法向半球
- 利用法向半球产生随机向量,计算像素随机后的坐标(多次采样)
- 与采样点的深度进行比较,加权到AO中
- 后期(模糊等)
SSAO算法实现
获取深度、法线缓冲数据
C#
private void Start(){cam = this.GetComponent<Camera>();cam.depthTextureMode = cam.depthTextureMode | DepthTextureMode.DepthNormals;
}
获取相机组件
深度纹理模式设置为 带深度 和 带法线的
Shader
这里的UV是屏幕空间的UV
重建相机空间坐标
具体参考:https://zhuanlan.zhihu.com/p/92315967
构建法向量正交基
tangent其实是半球面上 随机的一个向量(随机的方法参考下文)
AO采样核心
第二步:
_SampleKeneralRadius : 采样半球的半径长度
第三步:
因为都是在观察空间下进行的计算,所以得到randomPos后,乘以投影矩阵,再视图映射即可得到相应的屏幕坐标
rclipPos :即是球面上的点
SSAO优化
1. 随机正交基
应用于求法向半球的正交基时,其第二步生成随机变量。
_ScreenParams.xy 是屏幕的长宽,除以4是为了对应4x4像素的贴图。
因为i.uv 的增量是 1/_ScreenParams.x 或 1/_ScreenParams.y ,noiseUV增量也即 x或y增0.25,也即Noise贴图走一个格子。
2. AO累加平滑优化——范围判断
如果从天空盒的位置产生半球,采样到深度差很大的球体遮挡会产生ao,导致天空的像素上有阴影
加一个深度差绝对值的阈值判断,能够避免采样到深度差太大的无关遮挡
原本:
改成:
3. AO累加平滑优化——自身判断
4. AO累加平滑优化——AO权重
随机点的xy 越靠近的,权重越大
5. 模糊
烘培AO
三维建模软件烘培
烘培AO到纹理
优点:
- 单一物体可控性强(通过单一物体的材质球上的AO纹理贴图),可以控制单一物体的AO的强弱;
- 弥补场景烘焙的细节,整体场景的烘焙(包含AO信息),并不能完全包含单一物体细节上的AO,而通过三维建模软件烘焙到纹理的方式,增加物体的AO细节。
- 不影响其(Unity场景中)静态或者动态。
缺点:
- 操作较其它方式繁琐,需要对模型进行UW处理,再进行烘焙到纹理。
- 不利于整体场景的整合(如3DMax烘焙到纹理,只能选择单一物体,针对整体场景的处理工作量巨大);
- 增加AO纹理贴图,不利于资源优化(后期可通过其它纹理通道整合资源);
- 只有物体本身具有AO信息,获取物体之间的AO信息工作量巨大。
游戏引擎烘培AO
优点:
- 操作简易,整体场景的烘焙,包含AO的选择。
- 不受物体本身的UW影响,Unity通过Generate Lightmap UVs生成模型第二个纹理坐标数据。(TODO!!!不懂)
- 可以生成物体与物体之间的AO信息。
缺点: - 缺少单一物体的细节(可调整参数提高烘焙细节,但换之将增加烘焙纹理数量和尺寸,以及烘焙时间);
- 受物体是否静态影响,动态物体无法进行烘焙而获得AO信息。
SSAO优缺点
优点:
- 不依赖场景的复杂度,其效果质量依赖于最终图片像素大小。
- 实时计算,可用于动态场景。
- 可控性强,灵活性强,操作简单。
缺点: - 性能消耗较之上述2种方式更多,计算非常昂贵。
- AO质量上要比离线渲染烘焙(上述2种)不佳(理论上)。
SSAO性能消耗
主要在两个方面
AO法向半球的随机采样
- For结构代码
- 采样数:64 x 长 x 宽次AO核心计算
- 每个像素需要采样64次屏幕深度值、法线值
双边滤波的多重采样
作业
实现SSAO效果
使用其它AO算法实现进行对比
HBAO原理
全称Horizon-Based Ambient Occlusion,水平基准环境光遮蔽。
将360度分等份,在各个方向上做RayMarching,同时对这些方向加入随机旋转。下图以分4个方向来做
对于其中一个方向。再RayMarching过程中,得到一个最大的horizon angle(水平角)
根据点P及其法线,计算出切面角tangent angle
通过horizon angle 和 tangent angle,计算得出AO。(注意这里角度的范围,是实现的细节)
对其它三个方向相同操作,将AO值加起来平均后,得到最终点P的AO值
HBAO效果实现
核心代码:
fixed4 frag_Ao (v2f i) : SV_Target{//采样获得深度值和法线值float3 viewNormal;float linear01Depth;float4 depthnormal = tex2D(_CameraDepthNormalsTexture,i.uv);DecodeDepthNormal(depthnormal,linear01Depth,viewNormal);//获取像素相机屏幕坐标位置float3 viewPos = reconstructViewPos(i.uv);//获取像素相机屏幕法线,法相z方向相对于相机为负(so 需要乘以-1置反),并处理成单位向量viewNormal = normalize(viewNormal) * float3(1, 1, -1);float deltaAngle = 2.0 * UNITY_PI / _RayAngleStep;// 1/屏幕分辨率宽w , 1/屏幕分辨率高hfloat2 InvScreenWH = _ScreenParams.zw - 1.0;//_RayMarchingRadius 屏幕空间的采样半径float rayMarchingStepSize = _RayMarchingRadius/_RayMarchingStep; //采样核心float ao = 0;for(int j = 1; j <= _RayAngleStep; j++){float uvAngle = deltaAngle * j;float maxHAngle = _AngleBias;//两个叉乘求tangent线 float3 marchingDir = float3(GetRayMarchingDir(uvAngle), 0.0f);float3 temp = cross(marchingDir , viewNormal);float3 tangent = cross(temp, viewNormal);float sinTangentAngle = length(tangent.z)/length(tangent);sinTangentAngle *= tangent.z > 0.0f ? 1.0f : -1.0f;for(int k = 1; k < _RayMarchingStep; k++){float2 deltaUV = round( marchingDir * rayMarchingStepSize * k) * InvScreenWH;float2 stepUV = i.uv + deltaUV ;float3 pointPos = reconstructViewPos(stepUV);float3 diffPos = pointPos - viewPos;float exist = (diffPos.z < -0.04 ? 1.0 : 0.0);//差值z需小于0,并且加一点bias//这个漏了,明显错误,想了好久float sinHAngle = length(diffPos.z)/length(diffPos) * exist;if(sinHAngle > maxHAngle){maxHAngle = sinHAngle;}}if(maxHAngle > _AngleBias){ao += maxHAngle - sinTangentAngle;}}ao = ao / _RayAngleStep;float4 color;color = max(0.0, 1 - ao * _AOStrength);color.a = 1;return color;}
补充函数
inline float2 RotateDirections(float2 dir, float2 rot)
{return float2(dir.x * rot.x - dir.y * rot.y,dir.x * rot.y + dir.y * rot.x);
}inline float2 GetRayMarchingDir(float angle)
{float sinValue, cosValue;sincos(angle, sinValue, cosValue);return RotateDirections(float2(cosValue, sinValue), float2(1.0, 0));
}float3 reconstructViewPos(float2 uv)
{float3x3 proj = (float3x3)unity_CameraProjection;float2 p11_22 = float2(unity_CameraProjection._11, unity_CameraProjection._22);float2 p13_31 = float2(unity_CameraProjection._13, unity_CameraProjection._22);float depth;float3 viewNormal;float4 cdn = tex2D(_CameraDepthNormalsTexture, uv);DecodeDepthNormal(cdn, depth, viewNormal);depth *= _ProjectionParams.z;return float3((uv * 2.0 - 1.0 - p13_31) / p11_22 * (depth), depth);
}
对比HBAO、SSAO
- HBAO性能是有较大提升的,更适用于移动端。HBAO采样数大量减少,如果一个像素采样4个方向,4个RayMarching的话,也即16个采样点。而SSAO 要64个采样点,相当于4倍。其实可以理解为HBAO的通过角度的大小,节约了一部分的采样点。
- 效果上看,HBAO近处的细节相比于SSAO,是会差一截的。原因是步进(RayMarching)是基于屏幕的,越近,像素点之间的信息就越少。
HBAO优化
1. 基础阈值
当sin(H)大于一个bias时,才有ao
2. 非连续问题
只有在半球区域内的遮挡才有效,与避免从天空盒采样到遮挡同理。
在代码中,加入阈值判断,可以看出远处墙体的阴影少了。
3. 衰减
离像素点越远的采样点,影响应该越小
使用公式:W(r)= 1 - r²
Per-Sample Attenuation: 逐采样衰减。考虑阈值内的各个采样点,分别乘以权重给出贡献。
加入了衰减后,可以发现阴影的扩散变小了,更紧凑了。
其它AO
GTAO,Bent Normal,AAO,TSSAO,VXAO,UE4的Distance Filed Ambient Occlusion
参考资料
https://www.bilibili.com/video/BV16q4y1U7S3?p=2
https://developer.download.nvidia.cn/presentations/2008/SIGGRAPH/HBAO_SIG08b.pdf
https://blog.csdn.net/puppet_master/article/details/82929708
【技美百人计划】图形 4.2 SSAO算法 屏幕空间环境光遮蔽(&HBAO)相关推荐
- 【TA-霜狼_may-《百人计划》】图形4.2 SSAO算法 屏幕空间环境光遮蔽
[TA-霜狼_may-<百人计划>]图形4.2 SSAO算法 屏幕空间环境光遮蔽 @[TOC]([TA-霜狼_may-<百人计划>]图形4.2 SSAO算法 屏幕空间环境光遮蔽 ...
- 图形 4.2 SSAO算法 屏幕空间环境光遮蔽
链接: SSAO算法 屏幕空间环境光遮蔽思维导图. SSAO算法 屏幕空间环境光遮蔽 SSAO介绍 什么是AO SSAO原理详解 SSAO介绍 SSAO原理 计算近似AO SSAO算法实现 比较与分析 ...
- 技美 百人计划 (图形)1.1渲染流程
技美 百人计划 (图形) 图形 1.1 渲染流水管线2.1数学基础 很早之前就有关注百人计划这个系列的课程,也跟着看到了2.几的教学但是一直没有写笔记,最近看到百人计划已经快更新完毕了,决定从头看一遍 ...
- 技美 百人计划 2.1色彩空间
技美 百人计划 2.1色彩空间 2.1色彩空间 色彩发送器 色彩的认知 光源是出生点,光源发射出光线,光线通过直射反射折射等路径最终进入人眼.但人眼接收到光线后,人眼的细胞产生了一系列化学反应,由此把 ...
- 【技美百人计划】图形 4.4 抗锯齿概论
笔记 锯齿是怎么产生的 左图:想要的效果 右图:表现的效果 抗锯齿分类 ● 前向渲染: SSAA.MSAA.CSAA.RGSS等 ● 延迟渲染: FXAA.MLAA.SMAA等 ● 时域上的抗锯齿: ...
- 【技美百人计划】图形 4.5 Dof景深基础
笔记 景深原理 ● 指相机对焦点前后相对清晰的成像范围,是一段三维空间. ● 针对相机成像产生的概念,肉眼也有类似的效果 景深遇到的问题 因为是基于深度图的实现,如果是半透明物体,则没有深度,要如何解 ...
- 【技美百人计划】图形 4.3 实时阴影介绍
笔记 先讲两个概念 软阴影.硬阴影 硬阴影: ● 应用于点光源 ● 对于每一个像素,只需要检查该像素和光源之间是否有遮挡物存在即可,因此这种和像素一对一的可见性函数结果可以如同表面颜色一样,被存储在一 ...
- 【技美百人计划】美术 1.1.3 角色设计精要
笔记 角色设计流程 设计流程: 角色设计流程: 确定角色关键词 ● 了解角色并找到那些让角色独一无二的关键词 ● 如这些角色的重要标识:世界观.背景.能力.职业.性格.喜好 EXP 小美: 设计之初: ...
- 【技美百人计划】美术 1.1 美术理论基础
笔记 光影 光影:物体呈现在人们眼前的时候,不同的受光面其明暗变化以及物体的影子 黑白灰 & 明暗五调子 黑白灰: 受光面为亮形成白,背光面为暗形成黑,其他的过渡为灰色 明暗五调子: ● 高光 ...
最新文章
- 【Design pattern】设计模式思路总结(二)
- php可以做ios程序吗,php写的可以在本机发送iOS push程序
- Android App“加固”
- PHP的getimagesize获取图像信息
- SUBSTRING的用法问题
- matlab 最小二乘法拟合_计量与论文串讲:最小二乘法
- python字符串系列
- cmake编译cocos2d-x报错
- (转)淘淘商城系列——内容分类管理
- oracle dba开头的表,oracle中以dba_、user_、v$_、all_、session_、index_开头的常用表和视图...
- Xcode 12 引用缺失包:libstdc++.tbd libstdc++.6.tbd libstdc++.6.0.9.tbd 等
- Java应用程序和java小程序的区别_Java中的应用程序和小程序之间有什么区别?
- hrbust 哈理工oj 1921 三原色(改进版)【集合相关问题】
- AutoDWG DWG 转换 PDF 控制组件-ActiveX
- 刘强东不是一个人,互联网寒冬真的来了
- 实验三|Python 企业营运能力分析
- 明日直播| NLPCC workshop百度架构师带你快速上手飞桨NLP
- 解决video更多选项按钮点击无反应以及操控video标签的控制按钮
- SpringBoot 下载打包图片
- 入门学习MNIST手写数字识别
热门文章
- 黑马程序员pink老师前端h5(html5)+css3(16)P94-P104伪类选择器上并集选择器子选择器后代选择器emmet语法生成标签快速格式化代码复合选择器简介
- px、em、rem单位间的区别
- 百度自动驾驶巴士开启收费运营
- Caused by: java.lang.IllegalArgumentException报错
- C++——求平均数、求和函数
- Node.js+Protractor+vscode搭建测试环境(1)
- io多路复用的原理和实现_IO多路复用机制详解
- 没文档也要扒源码让 ShardingSphere 支持 openGauss SCRAM 前端认证
- 这些优秀的 Spring Cloud 开源软件,你知道的有几个?
- robomongo 连不上mongodb 权限问题