Global Illumination_Voxel Ambient Occlusion (VXAO)

我们首先来回顾一下 VXGI(实时体素全局照明技术),这一渲染技术可以为动态/静态场景产生具有良好遮挡、逼真全局光照,而且无需预处理。VXGI 允许渲染引擎计算多次反射间接漫反射和镜面反射光照,使用着色器中的锥体追踪算法(Cone Tracing)来满足特殊需求,例如折射材料或光照贴图等计算,并且还可以根据体素数据计算环境遮挡效果

一、VXAO简介

因此我们本部分主要来看一下VXAO技术:环境遮挡模式,或我们称之为 VXAO算法。

其原理很简单:在VXGI实现中移除光照部分,只保留了遮挡部分。显然,它相较于传统的VXGI算法占用的资源要少得多,且根据相关参数设置,计算一帧的 VXAO 可以比计算完整的全局照明解决方案快 2~10 倍。同时,VXAO 比 HBAO+ 慢 3~4 倍,但是其结果却比 HBAO+ 好很多。

下边放一张,VXAO的效果图:

在这里插入图片描述
再看一张SSAO的:

在这里插入图片描述

再来一张NOAO的:

在这里插入图片描述
效果看图就能知道算法差距了。

另附一个场景体素表示如下:
在这里插入图片描述

二、VXAO算法优势

如果您使用过屏幕空间环境光遮挡算法,你一定知道其算法的一些缺陷如下:

  • 前景物体后面的暗光晕或缺乏遮挡;
  • 靠近屏幕边界的渲染结果不稳定;
  • 局部性,这意味着表面周围只有很小的体积对 AO 有贡献;
  • 模糊,需要做对应的滤波处理(性能消耗大)。

而 VXAO 没有这些问题,因为它基于不同的原则。它不依赖于屏幕空间数据,而是从场景的世界空间体素表示中收集信息,该场景覆盖了像素点周围的大片区域。某些对象是否对相对于视角不可见便变的并不重要了,它可以在其他物体的后面,甚至在观察者的后面, 只要会对着色点产生空间影响的物体都会导致环境遮挡。
因为 VXAO 使用体素锥体追踪,所以设定的追踪距离会对该算法产生影响,但此因素并不像屏幕空间算法中那样耗费性能。

且 VXAO 结果非常稳定。当物体靠近或远离时,遮蔽数据都会发生一些变化,但它们并不太明显。这种变化的原因是当一个物体移开时,它的体素表示变得更粗糙,这意味着更大的误差。最终,当对象在体素覆盖区域之外时,VXAO 无法为它们计算任何遮挡。在这种情况下,计算出的 AO 缓冲区的 alpha 通道将包含一个零,表示应使用回退解决方案。从 1(完全置信度)到 0(我们一无所知)有一个平滑的过渡,因此可以在没有明显边界的情况下混合回退解决方案。

此外 VXAO 处理动态场景的效果也很好。大多数体素数据可以在帧之间保留,除非有很多移动的物体或相机快速移动。即使没有体素数据可以保存,再次依赖于GPU的场景体素化也不会耗性能。官方给出的数据为:在GeForce GTX 980上,可以在大约 3-5 毫秒内完成具有几百万个三角形的典型高细节游戏场景的体素化。

总体而言,VXAO 算法主要分为三步:

  1. 体素化:是通过将三角形网格渲染为 3D 纹理来执行的,因此,其性能在很大程度上取决于三角形的总数、这些三角形的大小以及渲染它们所需的绘制调用次数。
  2. 体素后处理:包括了清除、过滤和下采样体素等通道,其性能取决于体素化过程中产生的体素总数。典型的后处理时间为 0.5 – 1.5 ms。
  3. 锥体追踪:是在屏幕像素点上进行的,所以它的性能取决于屏幕分辨率、着色率和1080p分辨率的锥体追踪通道。

2.1 遮蔽类型

你知道Cone Tracing的原理话,那你肯定会明白存在以下两种遮蔽类型:

  • 体素遮蔽

在这里插入图片描述

为了在锥体追踪步骤中生成准确的结果,需要遮挡体素,否则,被认为具有很少或没有传出辐射度的体素化几何体将有助于间接照明计算。

经典的阴影映射或类似技术可用于计算体素遮挡。体素的位置投影在光线空间中,投影点的深度与阴影贴图中存储的深度进行比较,以确定体素是否被遮挡。

在这里插入图片描述

建议还在体积上使用光线投射来计算遮挡。可以使用体素化过程产生的任何体积,因为该算法只需要确定体素是否存在于某个位置。为了确定体素的遮挡,从体素的位置向光的方向追踪光线,对体积进行采样以确定在光线的位置是否存在体素,如果此条件为真,则体素被遮挡。

在这里插入图片描述

如果需要处理软阴影的效果,那么在找到体素后不停止光线处理,软阴影可以用单个光线累积一个值 k ,且在每次发生碰撞后除以可追踪的距离,即 v = v + (1 - v )k / t,其中 1-v 表示积累完成后的遮挡值。

这种技术利用了以下原理:从光的角度来看,穿过体素化几何体边界的光线的碰撞次数通常会更高。

在这里插入图片描述
在这里插入图片描述

  • 环境光遮蔽

环境光遮蔽可以使用用于漫反射的锥体来近似,以提高效率。如下图所示:

在这里插入图片描述

三、算法实现

对于算法实现的话,就很简单了:只需要在做Cone Tracing计算时,额外记录漫反射的全锥体中存在的体素数量作为遮蔽控制因素即可。

对于环境光遮蔽项 occlusion ,我们只累积遮挡值 anisoSample.a ,在每一步中,累积值乘以加权函数 1/ (1.0f + falloff * diameter) ,其中 diameter 是圆锥体的当前半径和 falloff 用户定义的值,该值控制 加权函数 沿跟踪距离衰减的速度。在每个锥形追踪步骤中,环境光遮蔽项更新为:

occlusion += ((1.0f - occlusion) * anisoSample.a) / (1.0f + falloff * diameter);

vec4 TraceCone(vec3 position, vec3 normal, vec3 direction, float aperture, bool traceOcclusion)
{
    uvec3 visibleFace;
    visibleFace.x = (direction.x < 0.0) ? 0 : 1;
    visibleFace.y = (direction.y < 0.0) ? 2 : 3;
    visibleFace.z = (direction.z < 0.0) ? 4 : 5;
    traceOcclusion = traceOcclusion && aoAlpha < 1.0f;

    float voxelWorldSize = 2.0 /  (voxelScale * volumeDimension);

    vec3 weight = direction * direction;

    float dst = voxelWorldSize;
    vec3 startPosition = position + normal * dst;

    vec4 coneSample = vec4(0.0f);
    float occlusion = 0.0f;
    float maxDistance = maxTracingDistanceGlobal * (1.0f / voxelScale);
    float falloff = 0.5f * aoFalloff * voxelScale;

    float enter = 0.0; float leave = 0.0;

    if(!IntersectRayWithWorldAABB(position, direction, enter, leave))
    {
        coneSample.a = 1.0f;
    }

    while(coneSample.a < 1.0f && dst <= maxDistance)
    {
        vec3 conePosition = startPosition + direction * dst;
        // 基于直径的锥体膨胀和相应的mip级别  
        float diameter = 2.0f * aperture * dst;
        float mipLevel = log2(diameter / voxelWorldSize);

        vec3 coord = WorldToVoxel(conePosition);
        
        vec4 anisoSample = AnistropicSample(coord, weight, visibleFace, mipLevel);

        coneSample += (1.0f - coneSample.a) * anisoSample;

        if(traceOcclusion && occlusion < 1.0)
        {
        	//环境光遮蔽算法
            occlusion += ((1.0f - occlusion) * anisoSample.a) / (1.0f + falloff * diameter);
        }

        dst += diameter * samplingFactor;
    }

    return vec4(coneSample.rgb, occlusion);
}

具体可见VXAO效果如下:
在这里插入图片描述

而SSAO效果如下:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值