图形学基础|屏幕空间反射(SSR)

图形学基础|屏幕空间反射(SSR)

一、前言

反射效果,是游戏中比较常见且重要的一个效果。

在表现光滑的表面(金属、光滑地面)、水面(湖面、地面积水)等材质时,反射出场景中的其他物体,可以让画面质量有很大提升,丰富真实感。

在这里插入图片描述

在这里插入图片描述

当粗糙度越小,镜面反射的反射波瓣更加狭窄,光照更加高频,精度要求也更高。

在这里插入图片描述

本文将对实现反射效果的一些技术做简单的概述,并着重介绍基于屏幕空间的反射技术

以下是笔者的一些笔记。如有错误,还请见谅。

二、反射技术概述

这里所说的反射,属于间接光照的范畴。

直接光照下的反射是指:光源出发经过物体表面直接反射进入眼睛的光照。

间接光照下的反射是指:当物体的表面比较光滑(如镜面,金属),其表面可以反射周围环境,反射的光线进入人眼。

间接光照下的反射,如果严格计算求解,是相当复杂的:

  1. 需要对表面上的像素在其法线方向做半球积分;
  2. 并且光线经反射会继续地传递下去,直至能量衰减为0;

在实时渲染当中,完整地计算求解间接光照下的反射是很困难的,因此需要通过各种技术手段模拟和近似反射效果。

各种性能友好的反射方法就应运而生,其中包含了以下几种常用的技术方案:

  • 环境贴图反射;
  • IBL反射;
  • 平面反射;
  • 屏幕空间反射;

2.1 环境贴图反射

最简单的模拟反射效果的技术方案是环境贴图反射(CubeMap反射)。

这种技术通过计算反射的向量,采样(Fetch)环境贴图,从而实现反射的效果。

环境贴图

环境贴图CubeMap最简单的情况就是静态的环境,可以通过预先烘焙进行存储,在运行时加载渲染。

如下展示了天空盒的渲染,其中,OpenGL渲染时需要注意CubeMap的方向问题

在这里插入图片描述

并且,环境贴图的存储方式并不局限于CubeMap(立方体),还可以是八面体映射等。

环境映射技术漫谈博文中介绍了四种环境映射技术的原理并分析了它们的优缺点。

反射向量

对环境贴图的采样需要反射向量,

计算反射向量的原理可参考图形学相关数学(反射,折射公式)

在这里插入图片描述

或在HLSL中,直接使用 reflect 函数,入射方向和法向量都为单位向量。

// 注意,V方向是指向相机的方向
// 使用reflect,需要使用反向V
float3 L = reflect(-V, N);

伪代码

模拟天空盒反射的着色器如下:

float4 PS(float2 Tex : TEXCOORD, float4 SVPosition : SV_Position) : SV_Target
{
	float3 N = normalize(v_normal);
    float3 V = normalize(v_camera_position - v_world_position);
    float3 L = reflect(-V, N);
    float3 Color = CubeMap.SampleLevel(LinearSampler, L, 0).xyz;
    return float4(Color,1.0f);
}

2.2 IBL反射

2.1的环境贴图(天空盒)反射并没有考虑到粗糙度,reflect求解的反射向量是完全镜面反射。

在PBR的IBL环境光计算中,考虑到粗糙度,根据表面的粗糙度来计算环境纹理的平均值。

因为它需要获取一个区域的所有像素,所以发射多条光线进行采样计算平均值很慢。

幸运的是,GPU可存储mipmap,mipmap是图像的模糊版本,这也适用于Cubemap。

将预预过滤环境贴图存储在Mipmap中,通过粗糙度映射计算Mipmap等级,我们就可以从立方体贴图获取一个区域的环境纹理平均值了。

实现方面可以参考笔者之前文章中的5.2.2 Prefilter EnvironmentMap

在这里插入图片描述

在实际应用时,会在场景中放置多个Reflection Probe/反射探针

在场景中选择一些关键位置,每个Reflection Probe都以自己所在位置为中心烘焙周围的环境光照。

在渲染场景中的物体时, 选择一个或多个最近的Refelction Probe, 来确定周围的环境光照信息,尽管反射不够精确,但反射足够接近。

在这里插入图片描述

2.3 平面反射(Planar Reflections)

如果我们只关心平面上的反射,有这样一个办法。

在平面上反射的相机的角度渲染场景,将结果存储在纹理中,并在最终渲染过程中使用它。

如果是粗糙的平面,可以对得到的像再次进行模糊等后处理。

在这里插入图片描述

这是昂贵的,因为需要对反射进行整个场景的完整渲染

可参考的实现有:

2.4 屏幕空间反射(Screen Space Reflection)

2.4.1 SSR的基本原理

屏幕空间反射(Screen Space Reflection,SSR),是一个非常著名的基于屏幕空间的技术。

由于镜面反射的波瓣很窄,意味着可以使用少量的光线模拟反射,从而就可以得到不错的效果。

算法本身的原理非常简单:

  1. 对于屏幕空间上的物体的每个像素,根据该像素对应的法线和视线信息,求解出反射向量;
  2. 当前点沿着反射向量在屏幕空间进行步进,判断步进后的坐标深度与深度缓存中存储的物体深度是否相交;
  3. 若相交,取交点处的物体颜色作为最终的反射颜色;

在这里插入图片描述

2.4.2 SSR的优缺点

优点:

  1. 针对任何面都可以实时反射,不需要求平面。
  2. 不需要额外的DrawCall,没有Planar Reflection那种翻倍DC的问题,计算都在GPU,解放CPU。
  3. 只需要额外的后处理Pass处理,无需大规模改动引擎管线,容易集成。
  4. 可以与Reflection Probe等结合使用。

缺点:

  1. 需要全屏深度和全屏法线,延迟渲染管线中是可以免费拿到的!但是前向渲染的话,需要额外渲染一遍DepthNormalMap。
  2. Shader中需要进行RayMarching,对于GPU的负载较大,且步进是有一定步长的,它本身不可能非常精确。
  3. 效果存在自身缺陷,由于只有屏幕可见的物体信息,不在屏幕内的,就完全不会反射。这属于技术本身的瓶颈。

三、SSR(Screen-Space Reflection)实现

3.1 Efficient GPU Screen-Space Ray Tracing

2.4.1中介绍了屏幕空间反射的基本原理:

  • 在屏幕空间进行光线步进(Ray Marching)代替三维空间的光线步进,通过深度缓存判断是否相交。若相交,取交点处的物体颜色作为最终的反射颜色。
3.1.1 2D Raymarching vs 3D Raymarching

问题1:为什么要用屏幕空间的光线步进代替三维空间的光线步进呢

三维空间的光线步进过程如下(以世界空间为例):

  1. 对于着色点 x x x,根据其法线和视角方向,计算得到反射方向 R R R
  2. 以着色点 x x x为起点,沿着反射方向 R R R,每次步进一定距离,得到一个新的点,记作 x i x_i xi x i = x + i ∗ Δ p x_i = x + i * \Delta p xi
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值