4.2 SSAO算法 屏幕空间环境光遮蔽

2023-10-31 16:20

本文主要是介绍4.2 SSAO算法 屏幕空间环境光遮蔽,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、SSAO介绍

AO

环境光遮蔽,全程Ambient Occlustion,是计算机图形学中的一种着色和渲染技术,模拟光线到达物体能力的粗略的全局方法,描述光线到达物体表面的能力。

SSAO

屏幕空间环境光遮蔽,全程 Screen Space Ambient Occlusion,一种用于计算机图形中实时实现近似环境光遮蔽效果的渲染技术。通过获取像素的深度缓冲、法线缓冲来计算实现,来金丝的表现物体在间接光下产生的阴影。

SSAO历史

AO这项技术最早是在Siggraph 2002年会上由ILM(工业光魔)的技术主管Hayden Landis所展示,当时就被叫做Ambient Occlusion。

2007年,Crytek公司发布了一款叫做屏幕空间环境光遮蔽(Screen-Space Ambient Occlusion, SSAO)的技术,并用在了他们的看家作孤岛危机上。


二、SSAO原理

  • 计算深度、法线缓冲
  • 深度->像素坐标
  • 法线->法向半球随机向量
  • 计算像素随机后的坐标(多次采样)
  • 获取随机后深度并比较
  • 判断加权AO
  • 后期(模糊等)

样本缓冲

  • 深度缓冲
    • 深度缓冲中的depth值用于当前视点下场景的每一个像素距离相机距离的一个粗略表达,用于重构像素相机空间中的坐标(Z),来劲死重构该视点下的三维场景。
  • 法线缓冲
    • 相机空间中的法线信息,用于重构每个像素的“法线-切线-副切线”构成的坐标轴,用于法线半球中的采样随机向量(随机向量用于判断、描述该像素的AO强度)。

法向半球

  • 黑色表示我们需要计算的样本
  • 蓝色向量表示样本的法向量
  • 白色灰色为采样点(很明显,采样点的多少影响最后的渲染效果),其中灰色表示被遮挡采样点(深度大于周围),据此判断最终AO的强度。
  • 右图表示法向球形采样(后背抛弃),原因是该方式采样导致凭证的墙面也会显得灰蒙蒙的,因为和心中一般的样本都会在墙这个几何体上。


三、SSAO算法实现

Buffer

  • 获取深度&法线缓冲数据
  • C#部分
  • Shader部分
  • UnityCG.cginc

如果是延迟渲染这一步可以省略,G-Buffer中可以直接拿到

中间相机空间坐标

  • 重建方法
    • 参考链接:Unity从深度缓冲重建世界空间位置 - 知乎
    • 本例实现使用其中的“NDC空间中重构”方法得到样本在相机空间中的向量,乘以深度值得到样本的坐标。
  • 从NDC空间重建
    • 1.计算样本屏幕坐标(利用Unity内置的函数)
    • 2.转化至NDC空间中
    • 3.计算相机空间,从中到远屏幕的方向(内置变量_ProjectionParams.z存放相机远平面值far)
    • 4.矩阵变换至相机空间中的样本相对相机的方向
    • 5.重构相机空间的样本坐标(在像素着色器中)
    • 在相机空间中通过样本的相对相机方向以及深度,来拟合重构坐标

构建法向量正交基

  • 设置法向量
  • 生成随机向量(用于构建的正交基随机,而非所有样本计算的到的正交基一致),先归一化
  • 求出切向量,再利用函数cross叉积求副切线向量

AO采样核心

  • 传入给定的随机采样向量,并通过法向量正交基转化至法线半球中的向量。

  • 获取随机坐标点。
  • 转换至屏幕空间坐标

  • 计算随机向量转化至屏幕空间后对应的深度值,并判断累加AO


四、SSAO效果改进

随机正交基(增加随机性)

  • 为了不使求得的法向半球的正交基一致,我们引入随机向量,已求得不用想象的切向量。
  • 利用uv采样一张Noise贴图(如下图4x4像素的Noise贴图,可选择其他尺寸),或者随机向量。
  • 并在C#中传入噪声贴图。

AO累加平滑优化

范围判定(模型边界)

  • 样本采样,可能会采集到的深度差非常大的随机点,会导致边界出现AO,如下图
  • 加入样本深度和随机点的深度值判定(效果如下图)

自身判定

如果随机点深度值和自身一样或者非常接近(可能会导致虽然在同一平面,也会出现AO),如下图

判断深度值的大小时,增加一个变量,来改善问题

AO权重

AO深度判断,非0即1,比较生硬,为其增加一权重,如下图

本例中的权重为:发现半球中随机采样后的点x、y(切线平面)距离样本的距离为参考

模糊

采用基于法线的双边滤波原理(Bilateral Filtering)


五、对比模型烘焙AO

烘焙方式

  • 三维建模软件烘焙AO方式
    • 通过三维建模软件(如3DMax),设定好渲染参数,对模型(单一选择模型实体),烘焙AO到纹理。
  • 游戏引擎烘焙AO方式(Unity3D Lighting)
    • 通过Unity的Lighting功能(主菜单/Window/Rendering/Lighting Settings)进行整体场景的烘焙,AO信息包含于此。

建模软件烘焙优缺点

  • 优点
    1. 单一物体可控性强(通过单一物体的材质球上的AO纹理贴图),可以控制单一物体的AO的强弱;
    2. 弥补场景烘焙的细节,整体场景的烘焙(包含AO信息),并不能完全包含单一物体细节上的AO,而通 过三维建模软件烘焙到纹理的方式,增加物体的AO细节;
    3. 不影响其(Unity场景中)静态或者动态;
  • 缺点
    1. 操作较其他方式繁琐,需要对模型进行UV处理,再进行烘焙到纹理;
    2. 不利于整体场景的整合(如3DMax烘焙到纹理,只能选择单一物体,针对整体场景的处理工作量巨大);
    3. 增加AO纹理贴图,不利于资源优化(后期可通过其他纹理通道利用整合资源);
    4. 只有物体本身具有AO信息,获取物体之间的AO信息工作量巨大(不是不可能)。

Unity烘焙优缺点

  • 优点
    1. 操作简易,整体场景的烘焙,包含AO的选择;
    2. 不受物体本身的UW影响,Unity通过Generate Lightmap UVs生成模型第二个纹理坐标数据;
    3. 可生成场景中物体与物体之间的AO信息;
  • 缺点
    1. 缺少单一物体的细节(可调整参数提高烘焙细节,但换之将增加烘焙纹理数量和尺寸,以及烘焙时间);
    2. 受物体是否静态影响,动态物体无法进行烘焙,获得AO信息。

SSAO优缺点

  • 优点
    1. 不依赖场景的复杂度,其效果质量依赖于最终图片像素大小;
    2. 实时计算,可用于动态场景;
    3. 可控性强,灵活性强,操作简单;
  • 缺点
    1. 性能消耗较之上述2种方式更多,计算非常昂贵;
    2. AO质量上要比较离线式烘焙(上述2种)不佳(理论上)。

六、SSAO性能消耗

AO核心采样消耗说明

AO法向半球的随机采样

双边滤波的多重采样

本例SSAO算法中,主要核心为计算AO随机法向半球的采样点,并加以半段计算AO权值。

  1. 利用For结构代码进行半球堆积向量的采样,If、For等对于GPU计算性能上不友好

  2. 采样数的数量(上图的_SmpleKernelCount,针对For循环的次数),过低的采样数得不到好的结果;以64为例,1334*750的分辨率,每个像素计算循环64次,合计1334*750*64次AO核心计算。
  3. 循环体重采样,同样以64为例,每个像素计算需要采样64次来求得屏幕深度值法线值。

滤波采样消耗说明

本例采用的是双边滤波(Bilateral Filter),为保证不被模糊,采样基于法线的双边滤波。

  1. C#后期脚本中,Blit两次(横向和纵向),合计调用两次滤波渲染Pass;

  2. 单一滤波渲染Pass中,多重采样,包括7次主纹理的采样和7次屏幕像素的法线信息的采用,屏幕中每个像素合计14次纹理采样。

这篇关于4.2 SSAO算法 屏幕空间环境光遮蔽的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/316601

相关文章

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.

Python+PyQt5实现多屏幕协同播放功能

《Python+PyQt5实现多屏幕协同播放功能》在现代会议展示、数字广告、展览展示等场景中,多屏幕协同播放已成为刚需,下面我们就来看看如何利用Python和PyQt5开发一套功能强大的跨屏播控系统吧... 目录一、项目概述:突破传统播放限制二、核心技术解析2.1 多屏管理机制2.2 播放引擎设计2.3 专

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Python实战之屏幕录制功能的实现

《Python实战之屏幕录制功能的实现》屏幕录制,即屏幕捕获,是指将计算机屏幕上的活动记录下来,生成视频文件,本文主要为大家介绍了如何使用Python实现这一功能,希望对大家有所帮助... 目录屏幕录制原理图像捕获音频捕获编码压缩输出保存完整的屏幕录制工具高级功能实时预览增加水印多平台支持屏幕录制原理屏幕

查看Oracle数据库中UNDO表空间的使用情况(最新推荐)

《查看Oracle数据库中UNDO表空间的使用情况(最新推荐)》Oracle数据库中查看UNDO表空间使用情况的4种方法:DBA_TABLESPACES和DBA_DATA_FILES提供基本信息,V$... 目录1. 通过 DBjavascriptA_TABLESPACES 和 DBA_DATA_FILES

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为