news 2026/4/16 13:54:28

【光照】UnityURP[屏幕空间环境光遮蔽SSAO]原理剖析实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【光照】UnityURP[屏幕空间环境光遮蔽SSAO]原理剖析实践

AO(Screen Space Ambient Occlusion,屏幕空间环境光遮蔽)是Unity URP中用于模拟物体间环境光遮蔽效果的技术,通过计算像素周围几何体的遮挡关系增强场景深度感和真实感。

技术发展进程

‌早期阶段‌:传统SSAO算法如Crytek SSAO(2007年)采用半球采样和深度比较,计算开销较大。

‌优化阶段‌:2010年后出现基于屏幕空间法线的改进算法(如HBAO),减少采样噪声。

‌URP集成‌:Unity 2019年将SSAO作为URP核心后处理效果,支持移动端优化实现。

核心原理

‌采样阶段‌:在屏幕空间随机采样当前像素周围的深度值,计算遮挡系数。

‌遮蔽计算‌:通过比较采样点与当前像素的深度差,确定光线被阻挡的概率。

‌模糊处理‌:使用双边滤波消除噪声,保留边缘细节。

URP实现机制

URP通过ScreenSpaceAmbientOcclusion渲染特性实现:

原理示例

像素P的深度值为Dp,法线为Np

在半球范围内随机采样点S(深度Ds)

若(Ds > Dp)则累计遮蔽值

最终遮蔽强度 = 1 - (可见采样点/总采样点)

采样阶段

深度纹理获取‌:

通过_CameraDepthTexture获取屏幕空间深度值,将像素坐标转换为视图空间位置

深度纹理获取原理

在URP中,_CameraDepthTexture通过以下方式生成:

‌深度图来源‌:URP会在渲染不透明物体后通过CopyDepth Pass将场景深度复制到_CameraDepthTexture,若无法直接复制则启用PreDepthPass逐物体渲染深度

‌纹理声明‌:需在Shader中正确定义TEXTURE2D(_CameraDepthTexture)或引用URP内置头文件DeclareDepthTexture.hlsl

‌采样方式‌:使用SAMPLE_TEXTURE2D函数结合屏幕UV坐标获取非线性深度值,需通过Linear01Depth()转换为[0,1]范围的线性深度

像素坐标到视图空间转换流程

‌屏幕坐标计算‌:

hlsl

float2 screenUV = i.positionCS.xy / _ScreenParams.xy; // 归一化到[0,1]范围

‌深度值解码‌:

hlsl

float depth = SAMPLE_TEXTURE2D(_CameraDepthTexture, sampler_CameraDepthTexture, screenUV);

float linearDepth = Linear01Depth(depth, _ZBufferParams); // 转换为线性深度

‌视图空间重建‌:

‌方法一‌:通过摄像机射线插值

hlsl

float3 viewPos = _CameraInvProjectionMatrix * float4(screenUV * 2 - 1, linearDepth * 2 - 1, 1);

viewPos /= viewPos.w; // 透视除法

‌方法二‌:使用URP内置函数

hlsl

float3 viewPos = ComputeViewSpacePosition(screenUV, linearDepth); // 需包含Core.hlsl

‌坐标系统转换‌:

屏幕坐标 → NDC坐标 → 裁剪空间 → 视图空间,需注意不同API的NDC范围差异(OpenGL为[-1,1],DirectX为[0,1])

‌深度值特性‌:

原始深度值为非线性分布(透视投影),Linear01Depth通过_ZBufferParams参数处理平台差异

‌性能优化‌:

移动端建议使用SampleSceneDepth()封装方法,自动处理平台兼容性问题

完整实现可参考URP的ScreenSpaceAmbientOcclusion.hlsl文件,其中包含深度采样和空间转换的标准流程

‌法线重建‌:

利用深度差计算相邻像素的法线向量,形成法线半球采样空间

‌深度差计算‌

对当前像素的上下左右四个相邻像素进行深度采样,计算水平/垂直方向的高度差:

hlsl

float u = rightDepth - leftDepth; // 水平差分

float v = bottomDepth - topDepth; // 垂直差分

该过程通过_CameraDepthTexture获取深度值,并转换为线性深度‌。

‌法线向量生成‌

将深度差转换为向量后叉乘得到法线:

hlsl

Vector3 vec_u = (1, 0, u); // 水平方向向量

Vector3 vec_v = (0, 1, v); // 垂直方向向量

Vector3 normal = cross(vec_u, vec_v); // 叉乘结果

最终法线需归一化处理,确保长度为1。

‌法线半球采样空间‌

以重建的法线为基准,在其半球空间内均匀分布采样点,用于环境光遮蔽计算。该空间满足:

采样方向与法线夹角≤90°(max(0, N·S))

采样点深度差决定遮蔽强度(1-saturate(Ds-Dp)/半径)‌

技术实现细节

‌深度纹理采样‌:需在URP中启用DepthTextureMode.Depth,通过SAMPLE_DEPTH_TEXTURE获取非线性深度‌

‌坐标转换‌:屏幕坐标需通过ComputeScreenPos()转换为NDC坐标,再通过_CameraInvProjectionMatrix还原视图空间位置‌

‌性能优化‌:移动端建议使用SampleSceneDepth()封装方法,避免平台兼容性问题‌

‌随机采样‌:

在法线半球内生成随机向量(如64个采样点),通过旋转噪声纹理避免带状伪影

伪影(Artifacts)的成因

在屏幕空间环境光遮蔽(SSAO)等算法中,‌带状伪影‌(Banding Artifacts)通常表现为采样点分布不均匀导致的明暗条纹。这种伪影主要由以下原因引起:

‌固定采样模式‌:当使用固定网格或规则模式生成采样点时,相邻像素的采样方向过于相似,导致光照计算出现周期性重复‌

‌噪声纹理重复‌:直接使用静态噪声纹理(如Perlin噪声)作为采样方向偏移时,纹理的周期性重复会放大采样点的规律性‌

旋转噪声纹理的解决方案

通过旋转噪声纹理避免伪影的核心原理是‌破坏采样方向的周期性‌,具体实现方式如下:

‌动态旋转噪声‌

为每个像素生成唯一的旋转角度(如基于UV坐标或随机种子)

将噪声纹理的UV坐标与旋转矩阵相乘,使噪声图案在空间上动态变化‌

hlsl

// 示例:基于UV坐标的旋转

float2 rotatedUV = mul(noiseUV, rotationMatrix);

float noiseValue = tex2D(_NoiseTex, rotatedUV);

‌采样点分布优化‌

在法线半球内生成随机向量时,将噪声值作为方向偏移量:

随机向量s = normalize(noiseOffset × baseSampleDirection)

通过旋转噪声纹理,使相邻像素的采样方向差异最大化,避免重复模式‌

‌技术优势‌

‌消除周期性‌:旋转后的噪声纹理在空间上无重复规律,破坏带状伪影的数学基础‌

‌计算高效‌:仅需一次纹理采样和矩阵运算,适合实时渲染‌

实现参考

URP中可通过以下步骤实现:

定义噪声纹理_NoiseTex并设置_NoiseUVScale控制缩放

在片元着色器中计算旋转后的噪声值,用于调整采样方向‌

示例:

对像素P(深度1.0)生成采样点S(随机偏移0.2,0.3),转换后深度为1.15

遮蔽计算阶段

‌深度比较‌:

将采样点投影回屏幕空间,比较采样深度与原深度

若采样深度更近(如S深度0.9 < P深度1.0),累计遮蔽值

深度值还原‌:将采样的非线性深度值通过Linear01Depth()函数转换为线性空间值(范围[0,1])

关键代码:

hlsl

float sampledDepth = Linear01Depth(SAMPLE_TEXTURE2D(_CameraDepthTexture, sampler_CameraDepthTexture, uv), _ZBufferParams);

‌深度差计算‌:比较采样点深度与原像素深度,通常结合采样半径进行归一化处理

判定逻辑:

hlsl

if (sampledDepth < currentDepth)

occlusion += (currentDepth - sampledDepth) / _Radius;

‌边缘处理‌:当采样点超出屏幕边界时,默认按无遮挡处理或使用边缘像素值

在URP管线中,上述流程通过以下步骤完成:

使用ComputeScreenPos()函数生成屏幕坐标

通过SampleSceneDepth()方法采样深度纹理

最终比较采用视图空间Z值而非线性深度,避免透视畸变影响

‌法线权重‌:

根据采样点与法线夹角衰减贡献,排除背面无效采样

公式:

遮蔽因子 = max(0, N·S) * (1-saturate(Ds-Dp)/半径)

法线权重部分(N·S)

‌点积运算‌:N·S表示表面法线向量N与采样方向向量S的点积,用于评估采样点与法线的夹角关系

‌背面剔除‌:max(0, N·S)确保只有法线半球内的采样点(夹角小于90°)产生贡献,排除背面无效采样示例:当N=(0,1,0)且S=(0.3,0.8,0)时,点积结果为0.8,有效权重为0.8

深度差部分(Ds-Dp)

‌深度比较‌:Ds-Dp计算采样点深度与原像素深度的差值,正值表示采样点更近(产生遮挡)

‌归一化处理‌:saturate(Ds-Dp)将差值钳制在[0,1]范围,避免极端值干扰

‌半径归一化‌:除以采样半径_Radius使结果与采样范围无关,保证不同尺度下的一致性

综合计算

‌遮蔽强度‌:1-saturate(Ds-Dp)/半径将深度差转换为可见性系数(0完全遮蔽,1完全可见)

‌最终乘积‌:法线权重与可见性系数相乘,实现物理正确的遮蔽衰减应用场景:当采样点S在法线后方(N·S<0)或未被遮挡(Ds>Dp)时,该点贡献为0

该公式在URP中通过ScreenSpaceAmbientOcclusion.hlsl实现,核心代码段如下:

hlsl

float occlusion = 0;

for (int i = 0; i < _SampleCount; i++) {

float3 sampleDir = normalize(_Samples[i]);

float weight = max(dot(normal, sampleDir), 0);

float depthDiff = (SampleDepth(samplePos) - centerDepth) / _Radius;

occlusion += weight * (1 - saturate(depthDiff));

}

模糊处理阶段

双边滤波‌:结合空间距离和颜色差异保留边缘

水平/垂直两次高斯模糊,权重计算包含深度差阈值

‌降噪优化‌:使用低差异序列采样减少噪声,或通过Temporal AA累积帧数据

实际应用

代码说明:

动态启用URP后处理管线

配置SSAO强度、采样半径等关键参数

支持运行时参数调整

SSAOSetup.cs

using UnityEngine;

using UnityEngine.Rendering.Universal;

public class SSAOSetup : MonoBehaviour {

void Start() {

var urpAsset = GraphicsSettings.renderPipelineAsset

as UniversalRenderPipelineAsset;

// 启用SSAO后处理

urpAsset.GetComponent<UniversalAdditionalCameraData>()

.renderPostProcessing = true;

// 参数配置示例

var ssao = ScriptableObject.CreateInstance<ScreenSpaceAmbientOcclusion>();

ssao.Intensity = 1.2f;

ssao.Radius = 0.3f;

ssao.SampleCount = 16;

}

}

使用建议

‌移动端优化‌:降低SampleCount至8-12,使用Downsample模式。

‌美术控制‌:通过材质参数控制不同区域的遮蔽强度。

‌性能监控‌:在Profiler中观察SSAO.Pass的耗时

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/13 8:41:44

Spotify优化终极方案:三分钟搞定纯净音乐体验

Spotify优化终极方案&#xff1a;三分钟搞定纯净音乐体验 【免费下载链接】SpotX SpotX patcher used for patching the desktop version of Spotify 项目地址: https://gitcode.com/gh_mirrors/sp/SpotX 还在为Spotify的广告烦恼吗&#xff1f;想拥有一个干净整洁的音乐…

作者头像 李华
网站建设 2026/4/13 11:53:25

如何快速搭建私有云盘:ZPan完整使用指南

如何快速搭建私有云盘&#xff1a;ZPan完整使用指南 【免费下载链接】zpan A self-hosted cloud disk base on the cloud storage./ 一个基于云存储的网盘系统&#xff0c;用于自建私人网盘或企业网盘。 项目地址: https://gitcode.com/gh_mirrors/zp/zpan 想要拥有一个…

作者头像 李华
网站建设 2026/4/14 7:58:59

VR存档编辑交互革命:从平面工具到三维空间编辑的认知升级

VR存档编辑交互革命&#xff1a;从平面工具到三维空间编辑的认知升级 【免费下载链接】ER-Save-Editor Elden Ring Save Editor. Compatible with PC and Playstation saves. 项目地址: https://gitcode.com/GitHub_Trending/er/ER-Save-Editor 当你在《艾尔登法环》中反…

作者头像 李华
网站建设 2026/4/15 18:49:56

国产DevSecOps工具崛起:Gitee领航数字化转型安全新纪元

国产DevSecOps工具崛起&#xff1a;Gitee领航数字化转型安全新纪元 市场格局重塑&#xff1a;国产工具迎来黄金发展期 在数字化转型浪潮与网络安全法规的双重驱动下&#xff0c;中国DevSecOps市场正经历前所未有的变革。国际权威咨询机构Gartner最新数据显示&#xff0c;2025年…

作者头像 李华
网站建设 2026/4/16 5:34:39

基于 JuiceFS 构建 AI 推理:多模态复杂 I/O、跨云与多租户支持

着 AI 技术的快速发展&#xff0c;推理服务的需求在市场中不断增长&#xff0c;已成为各行各业广泛关注的关键应用。随着思维链、慢思考等技术的出现&#xff0c;模型的推理能力也在不断的增强。推理能力的实际应用覆盖了更多行业和场景&#xff0c;成为企业部署 AI 基础设施时…

作者头像 李华