译Variance Shadow Maps

发现这个阴影技术几乎没有中文版的详细讲解,姑且完整翻译一遍论文。

 

 

Variance Shadow Maps

WilliamDonnelly   Andrew Lauritzen

Waterloo大学,计算机科学,图形实验室

Winger_w

水平有限,错误指出欢迎指出

QQ:379404629

Figure1:各向异性过滤对比。上:普通shadow map,利用PCF。下:Varianceshadow map利用mipmapping16x的各项异性过滤。

摘要

在实时渲染中,Shadowmaps是一种被广泛采用的阴影技术。此技术的一个主要缺点是,像普通纹理那样采样,会产生严重的锯齿。本文介绍一种新的实时渲染阴影算法——variance shadow maps。不同于传统的shadow map保存一个深度值,我们将保存深度和深度的平方,利用他们可以计算纹理采样区域的方差。利用方差,我们可以计算出一个像素被遮挡的概率上限。我们会看到,这个概率值,非常接近现实的软阴影,并且可以用于实时渲染。我们的算法很容易在GPU上运行,只需额外的存储一点点数据。

引言

Shadow maps [Williams 1987]和阴影体(shadow volumes)[Crow 1977]是两个常见的阴影渲染算法。Shadow maps相对于阴影体有很多优点;例如,他更容易的被执行,对模型复杂度不太敏感,并且没有特殊的几何空间要求。

  不幸的是,就像大多数纹理一样,shadow maps如果过滤不当,会产生显眼的锯齿。现代显卡支持一些过滤方式来减少普通纹理产生的锯齿,他们是:mip mapping和各项异性过滤。这些技术不适用于标准的shadow maps,因为他只会简单的将shadow map中的深度值与周围几个点做线性插值。典型的实时渲染做法是,取当前相邻几个点的深度值,依次比较,将结果取平均值。这种做法的代价是昂贵的,因为显卡没有对此做优化。

  为了有效解决shadow maps的过滤问题,我们注意到标准的shadow map只保存了单独一个点的深度信息。方差shadow maps的每个像素将保存区域深度信息。为了用尽量少的数据来描述这个信息,我们存储两个数据:深度和深度的平方。这样做的主要优点是我们可以用它来近似描述一个区域深度信息。(这句话,有太好翻译,原文如下:One major advantage of this representation is that we canapproximate the average of two distributions by averaging the moments.

  在采样方差shadow map时,我们用这两个数据来计算当前像素所在区域的一个散列值界限。我们会看到,这个界限值会很好的模拟出每个光源投射到任意表面的软阴影。

  因为这两个数据能被插值,我们可以像普通纹理采样那样,基于硬件的支持做一个大范围的过滤来减少锯齿。

相关研究

Williams 介绍了shadow maps这样一个有效的阴影算法。然而,他指出普通的颜色纹理过滤技术不适用于shadow maps

 PCF(Percentage closer filtering)[Reeves et al.1987]提供了一个解决方案。他的实质是将深度信息做多次比较。这需要多次纹理采样才能消除锯齿。

 Deep shadow maps[Lokovic and Veach 2000]保存区域的多个深度值来替代单一点的深度信息。Deep shadow maps很难在显卡上高效运行,有两个原因:每个像素shade需要大量深度数据,同时,求平均值也会消耗额外的时间。

 Opacity shadow maps [Kim and Neumann 2001] 也类似Deep shadow maps存储区域深度信息,不过他通过存储固定数量的信息来实现。这个算法有相对较高的效率。(没研究过这个算法,原文讲的也含糊不清,列出:Opacity shadow maps [Kim and Neumann 2001] encode a

distribution of depths, but use a fixedamount of storage per pixel. Each pixel stores a function just as in deepshadow maps, but instead the function is constructed from its values at a fixedset of points. Thus the algorithm can take advantage of the speed of graphicshardware. The price to pay for this flexibility is extreme quantization ofdepths, so the technique is mostly suitable for rendering of dense volumetric objectssuch as hair and fur.)

  另一种解决shadow map锯齿的方法是改变投影矩阵。他们是adaptive shadow maps[Fernando et al.2001], Perspective shadow maps [Stamminger and Drettakis 2002],Light space perspective shadow maps [Wimmer et al.2004], trapezoidal shadowmaps [Martin and Tan 2004].这些算法与上述算法是互补的,因为他们并没有对投影矩阵做任何要求。

  一些显卡支持shadow maps,比如OpenGL”GL_ARB_Shadow”。但是这个特性并不能做插值或者mipmapping。一些NVIDIA 显卡处理器支持双线性过滤[Everitt et al.2000],但是据我所知,没有显卡支持三线性或者各向异性过滤用在shadowmaps上。

算法概述

在传统的shadowmapping中,我们先在光源处渲染场景,保存距离光源的深度;在variance shadow maps中,我们渲染一个有两个通道的缓冲区,保存深度和深度的平方。虽然常规的shadow map不会利用任何纹理过滤方式来采样深度值,但是在variance shadow map中,我们将得益于此。

  曾经我们对shadow map做了一些过滤处理。包括生成mipmaps [Willliams1983] 或者计算累加区域内的数据(summedarea tables)[Crow 1984]。现在,我们的variance shadow maps同样可以通过模糊处理来柔化阴影。

  我们保存深度和深度的平方到纹理中,这两个信息在采样时就会被过滤。(注:过滤实际上就是一种求平均值)我们将这两个通道的值定义为M1 M2,如下所示:

通过他们我们可以计算出方差:

  方差可以理解为一个描述区域信息的值。我们可以利用方差来计算一个大于某一变量的概率界限。Chebyshev公式做了具体描述。

x为一个在过滤区域中变化的随机深度值,再设t > μ

  上述公式中的P,描述了区域内大于某个值的概率,具体的,如果这个t就是我们需要比较的当前深度值,那么,P就可以理解为处于阴影中的概率。

  虽然,公式5只给出了一个上限,但是,他可以很好的近似描述出软阴影效果。

3.1 平面阴影遮挡

考虑这样的情况,一个平面遮挡物,深度为d1,他投射阴影到另一个平面,此平面的深度为d2(注解:平面深度固定就表面他们是平行的,且垂直于光源视线,他们两个平面深度的插值可认为是mipmap)。假设没有被遮挡时,d1,d2有混合参数pmipmap混合),然后我们可以得到:

通过公式5,我们可以计算出:

  我们可以看到,在这种简单情况下,Chebyshev不等式给出的值就等于我们的过滤参数。

  虽然这是一种很特殊的情况,但是他提供了一个近似值,适用于大多数场景。在一个只有单独阴影遮挡物和接受物的场景中,我们只需少量采样投射物或者接受物的深度,因为他们的误差非常小。这种情况下,公式5并没有提供一个精确值,但是误差已经足够小了。这样,我们可以认为pmax是一个理想的近似值。

具体实现

我们在Geforce6800GT上实现VSM

 Geforce6系列显卡支持16位浮点纹理,我们利用硬件支持的mipmapping和各项异性过滤来实现vsm。我们的实现步骤大致如下:

1.  以光源为视点,渲染一个16位浮点纹理,他保存深度和深度的平方。

2.  如果喜欢的话,我们可以用第二个pass将纹理进行高斯模糊。

3.  OpenGL会自动生成Mipmaps

4.  正常渲染场景。我们读取shadow map中的M1(深度),M2(深度平方)。如果depth< μ(平均深度,即M1),则此像素不在阴影中。否则,我们利用M1M2计算方差,利用公式5pmax来调适光照。

我们还利用32位浮点纹理来保存shadow map。因为我们的硬件还不支持在这个精度上进行过滤,所以,我们在像素shader里进行双线性差值。理论上,我们还可以在shader中进行mipmapping和各项异性过滤;然而,他运行的非常缓慢。

  我们也可以按照以下方法执行一些比较来过滤shadow map。他们基于一张没进过过滤的16位浮点纹理。

1.  简单的利用周围相邻点做深度比较。

2.  取四个相邻点做比较,并进行双线性插值。

3.  将四个相邻点的比较值,用高斯模糊化。

4.  取四点比较,每个点进行双线性插值,然后进行高斯模糊。

结论

Figure2 展示了利用mipmapping时的结果。就像普通纹理那样,mipmapping有效的减少了阴影锯齿。各项异性过滤也可用于vsm,当视角很平时,也能够有效消除锯齿(如figure 1)。

Figure2:无Mipmapping(左) Mipmapping(右)

Figure3:从左到右:1)标准shadowmapping25x5 PCF35x5双线性过滤PCF4VSM利用5x5高斯模糊

Figure4当过滤区域的方差很大时,光照渗透现象将会出现。车的圆形区域(此图实在太模糊,看不清~~~)应该是一个彻底(Solid)的黑影。注意到这来的深度差异很大,所以光照渗透现象很容易看出来

 

 Figure3 展示了利用各种过滤方式的vsm效果对比。可以看出vsm的效果要好很多。

5.1 光照渗透问题(Light Bleeding

我们的pmax在大多数情况下是一个小范围变化的变量。但是他毕竟不是一个精确值。从公式5我们可以看出,方差肯定大于0,无论d为什么值,pmax(d)始终大于0。当方差很小时,pmax将会很快的向0逼近,所以渗透现象不那么显眼。然而,当方差很大时,就像Figure4那样,会很明显的渗透现象。(应该被遮挡显示为阴影的地方,出现了光照)

  实际上,这个问题只会发生在深度变化很大的场景中。除此之外,vsm工作良好。

 

5.2 性能

我们选择了一个单聚光灯场景用作各种shadow map效率的对比,如Figure1所示。因为所有操作都在图片空间中,所有效率与场景的几何复杂度无关。

  VSM我们采用了mipmapping3线性过滤,和16x的各项异性过滤。其他算法的过滤方式不被硬件支持,我们在shader中实现。

  我们在GeForce6800GT上,用一秒渲染的帧数来衡量性能。先看看用不同shadow map支持,渲染到1024x768的颜色缓冲区的效率对比:

再看看都采样512x512shadow map,但是不同的目标缓冲区分辨率的对比:

  我们注意到PCFshadow map的尺寸并不敏感,但是屏幕分辨率对他的影响较大。相比较的,VSM对屏幕分辨的影响和普通shadow map差不多。但是如果用一些预过滤操作,比如VSM3x3的话,屏幕分辨率对vsm的影响还是很大的。

5.3 数字稳定性(Numerical Stability

从计算方差的公式4我们可以看出一些用浮点数运算的隐患。当方差与平均深度相差很小时,容易丢失精度。在实验过程中,我们发现这种错误有时会发生在16位的浮点shadow map上,但从来没出现在32位纹理上。我们希望未来的硬件能够支持32位浮点纹理的mipmapping 已经各项异性过滤。

结论

我们已经介绍完了方差shadowmap,他是一个简单而有效的减少阴影锯齿方案。我们的计算结果基于一个区域内概率上限,他可以很好的模拟出真实的软阴影。最后,我们看到vsm非常适合于现代图形显卡,并比较了他与其他阴影技术之间的性能以及质量差异。

感谢

感谢MichaelMcCool  StefanusDuToit提供的帮助,以及ChrisIacobucci提供的车辆模型。

 

 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值