GPU Gems1 - 9 有效的阴影体渲染

这章全面讲述了用于实时阴影渲染中常见两种流派之一的阴影体(Shadow Volumes)技术,又称模板阴影(Stencil Shadows)技术,重点是得到正确的角度的情形,减少几何图形和填充率的消耗。

简单谈谈阴影生成技术,目前普遍采用的一般有三种:Planar Shadow、Shadow Mapping和Shadow Volume,前者类似投影,计算最简单,缺点只能绘制抛射在平面上的阴影;Shadow mapping利用站在光源处所沿光源法线看去所生成的深度图来检测场景中的体象素是否处于阴影中,缺点是光源与物体位置相对固定、且在极端情况下计算精度差,不太适合精确到象素的动态光阴场合;Shadow Volume是目前最适合精确表现动态光阴场景的技术,适用性最广,其典型的适用范例便是Doom 3,不足在于阴影体积引入了额外的顶点和面,加大了存储和处理强度,同时渲染出的阴影比较硬,如果要实现软阴影,仍需其他技术配合。

说实话,GEM中这篇文章写的挺难懂的,我还是以自己的角度,从网上等资料来理解下阴影体渲染。参考的一些文章链接如下:

https://blog.csdn.net/jxw167/article/details/65435329

https://blog.csdn.net/wang371372/article/details/41086435

阴影体渲染创建一个阴影体积,并仅在其外部的物体上处理照明,我们将使用模板缓冲区作为算法的关键组件, 因此名称 -  Stencil Shadow Volume。阴影体积算法背后的想法是将光线减弱时创建的对象轮廓扩展到一个Volume中,然后使用一些简单的模版操作将该Volume映射到模板缓冲区中。 关键的想法是,当一个对象在Volume内(因此在阴影中)时,Volume前面的多边形会对对象的多边形进行深度测试,并且该Volume后部的多边形将失效相同的测试,或者说不参与测试。
我们将根据称为Depth Fail的方法设置模板操作,人们经常使用更直接的方法称为Depth Pass来实现阴影体积技术,但是其致命缺点是当视点在阴影中时,会导致模板计数错误,而Depth Fail的方法修复了该错误。

我们在左下角有一个灯泡,一个绿色的物体(称为遮挡物体),由于光而投下阴影, 在这个场景中也渲染了三个圆形的对象。 对象B被遮蔽,而A&C不是。 红色箭头限定阴影体积的区域(线的虚线部分不是它的一部分)。

我们首先将实际对象(A,B,C和绿色框)渲染到深度缓冲区中(从相机位置观察的)。 当我们完成后,我们可以获得最接近的像素的深度。 然后我们一个接一个地遍历场景中的对象,并为每个对象创建一个阴影体积。 这里的示例仅显示绿色框的阴影体积,但在完整的应用程序中,我们还将为圆形对象创建Volume,因为它们投射自己的阴影。 阴影体积是通过检测它的轮廓来创建的并将其扩展到无限远。 我们使用以下简单规则将该Volume渲染到模板缓冲区中:

1、如果在渲染阴影体积的背面多边形时深度测试失败,我们会增加模板缓冲区中的值。
2、如果在渲染阴影体积的前面多边形时深度测试失败,我们会减小模板缓冲区中的值。
3、在深度测试通过,模板测试失败情况下,我们什么都不做。

让我们看看使用上述方案的模板缓冲区会发生什么。

物体A:渲染阴影体的背面时深度测试失败(由于A的阻挡),所以模板缓冲值加1.渲染阴影体的前面时深度测试失败(由于A的阻挡),所以模板缓冲值减1,所以最后结果是对于物体A,起模板缓冲中的值为0.

物体B:渲染阴影体的背面时深度测试失败(由于B的阻挡),所以模板缓冲值加1.渲染阴影体的前面时深度测试成功所以最后结果是对于物体B,起模板缓冲中的值为1.

物体C:渲染阴影体的背面时深度测试成功,渲染阴影体的前面时深度测试也成功所以最后结果是对于物体C,起模板缓冲中的值为0.

请注意,到目前为止,我们还没有碰到色彩缓冲区。 当我们完成上述所有的操作后,我们再次使用标准的照明着色器渲染所有的对象,但是这次我们设置模板测试,使得只有模板值为零的像素才会被渲染。 这意味着只有对象A&C才能使其在屏幕上显示出来。
让我们看看如何把这个知识付诸实践。 正如我们前面所说,我们需要渲染当我们扩展遮挡物的轮廓时创建的体积。 我们所需要做的就是将轮廓边缘延伸到一个体积中, 这是通过为每个轮廓边缘从GS发射四(或实际上四角形拓扑中的四个顶点)来完成的。 前两个顶点来自剪影边缘,当我们沿着从光照位置到顶点的向量将边缘顶点延伸到无穷大时,生成其他两个顶点。 通过延伸到无限远,我们确保体积捕获位于阴影路径中的所有物体。 这个四边形如下图所示:
 

 

当我们重复这个从所有轮廓边缘发射四边形的过程时,会创建一个体积。 够了吗? 当然不。 问题是这个体积看起来像一个没有盖子的截锥体。 由于我们的算法依赖于检查体积的前后三角形的深度测试,所以我们可能会遇到一个情况,即从眼睛到像素的矢量可能没有通过正面或背面,如下图这个状况:

解决这个问题的方法是生成一个在两边封闭的体积。 这是通过创建一个正面和后面到体积(上图中的虚线)完成的。 创建前盖非常容易。 面向光的每个三角形都成为前盖的一部分。后盖需要将面向三角形的光的顶点延伸到无限远(沿着从矢量到每个顶点)并反转它们的顺序(否则所得到的三角形将指向体积内)。“无限”一词在这里已经提到过几次,我们现在需要确切地说明这是什么意思。 看看下面的图片:

我们看到的是从上面取出的截头锥体的图片, 灯泡发出一个穿过点p并继续无限远的光线。 换句话说,p扩展到无限远。 显然,在无穷远处,点p的位置是简单的(无穷大,无穷大,无穷大),但是我们不在乎。 我们需要找到一种光栅化阴影体积的三角形的方法,这意味着我们必须在投影平面上投影其顶点。 实际上这个投影平面是近平面。 虽然p沿着光矢量延伸到无穷远,但我们仍然可以在近平面上投射它。 这是通过从原点开始的虚线完成的,并在某处穿过光矢量。 我们要找到Xp,它是该矢量穿过近平面的点的X值。

我们将光矢量上的任何点描述为p + vt,其中v是从光源到点p的向量,t是从0到无穷大的标量。 从上图和三角相似之处可以看出:
 

其中n是近平面的Z值。 随着t到无穷大,化简公式如下所示:

所以这就是我们在近平面上如何找到“无限远”的投影,根据上述我们只需要乘以矢量(Vx,Vy,Vz,0)(其中V是从光源到矢量的点p的向量)来计算通过视图/投影矩阵并应用透视分割、

 

总结一下 Z-fail算法(John Carmack's Reverse)
1. 先关闭光源,将整个scence渲染一遍,获得深度值
2. 关闭深度写,渲染阴影体的背面,深度测试失败则模板值加1
3. 渲染阴影体的正面,深度测试失败则模板值减1
4. 最后模板值不为0的面便处于阴影体中,开启深度写
5. 用模板手法重新渲染一次加光的scence即可,阴影部分不渲染色度
6. 注意,该算法要求阴影体积是闭合的,即需要前后封口
7. 该方法不是没有缺陷的,有可能因为Z-far clip plane过近而导致模板计数错误

 

阴影体渲染要点总结

  • 轮廓检测创建阴影体,封闭的面(但是在GEM这篇文章当时,轮廓检测一般只能运行在cpu中)
  • Z-fail算法模板计数
  • 渲染场景

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246309.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GPU Gems1 - 10 电影级的光照

本章中介绍了一个的简化的uberlight(可理解为“全能光照”)实现,此光照shader根据Ronen Barzel(1997,1999)提出的照明模型编写而成。而该模型的超集已由Pixar动画开发,并应用于《玩具总动员》、《怪物公司》、《海底总动员》等一系…

GPU Gems1 - 11 阴影贴图反走样

这章介绍了如何通过邻近百分比过滤方法(Percentage-Closer Filtering , PCF)有效减少阴影贴图的反走样,并描述了如何实现一个简化版本,并对PCF方法进行了一定改进。关于阴影贴图和PCF技术的一些链接 https://pubweb.eng.utah.edu…

GPU Gems1 - 12 全方位的阴影映射

在这章中,把阴影贴图的思路扩展到正确处理全方位的(点)光源中,其中包括了实现细节,也涉及到基本硬件能力不足时的低效运行策略。 首先,这篇文章也谈到了在实时计算机图形学中产生可见阴影的两个流行方法是…

GPU Gems1 - 13 使用遮挡区间映射产生模糊的阴影(Generating Soft Shadows Using Occlusion Interval Maps)

这章介绍了一种渲染软阴影的技术,称为遮挡区间映射(Occlusion Interval Maps),能够正确地在静态场景中渲染出光源沿着预定路径移动时产生的模糊阴影。之所以叫遮挡区间映射,是因为此算法使用纹理贴图来存储这种光源可见…

粗糙表面的微表面模型——Physically Based Material

关于文章 Microfacet Models for Refraction through Rough Sufaces的一点笔记,欢迎指正。 BSDF BSDF(Bidirectional Sacttering Distribution Function) 描述了光如何在物体表面散射。如果仅仅限制反射或者透射,BSDF经常被称作BRDF或者BTDF,然而BSDF将…

GPU Gems1 - 14 透视阴影贴图(Perspective Shadow Maps: Care and Feeding)

开篇先说,这文章好难懂啊,到现在也没完全弄明白,有大佬的话欢迎指点。这篇大体意思是对Perspective Shadow Maps进行部分优化。GEMS这书这点是真挺蛋疼,很多文章都是对某项技术的优化,那先介绍介绍原来技术嘛&#xff…

GPU Gems1 - 15 逐像素光照的可见性管理

这章讲到了可见性在逐像素渲染光照场景中的作用,也考虑如何使用可见性减少必须渲染的批次数量,从而改善性能。 假设一个非常简单的场景,一个房间,因为房间的不同部位是不同的材质,所以将其分为8个batch,另…

重建世界坐标

1.概论 在屏幕空间做一些操作的时候往往需要从屏幕坐标和深度纹理中重建出相应的世界坐标。 本文会讨论两种重建世界坐标的方法,并详细讲解第二种方法。 使用VP逆矩阵CameraPosInWorld linearDepth * Direction 2.使用VP逆矩阵法 我们知道屏幕坐标是通过Object…

GPU Gems1 - 16 次表面散射的实时近似(Real-Time Approximations to Subsurface Scattering)

这一章,浅墨这篇文章介绍的非常详细,我照扒一遍再稍加一些内容,增加记忆。https://zhuanlan.zhihu.com/p/36499291 【章节概览】 次表面散射(Subsurface Scattering),简称SSS,或3S&#xff0c…

Unity HDRP渲染管线基础指南

HDRP和LWRP简介 Unity2018中引入了可编程渲染管线(Scriptable Render Pipeline,简称SRP),是一种在Unity中通过C#脚本配置和执行渲染的方式。至2018.1版本,Unity中除了默认渲染管线,还提供了轻量级渲染管线…

SSDO AO 图像空间的动态全局光照

本文仅记述SSDO学习笔记! 概述 SSDO Screen-space Direction Occlusion 是对AO的扩充,在AO的基础上,假设没有遮蔽的方向有直接入射光,有遮蔽的方向,可能有间接光的反射。 SSAO理论分析 AO:在计算点的周围…

GPU Gems1 - 17 环境遮挡

环境光遮蔽(Ambient Occlusion)“AO”为Amblent Occlusion的缩写,中文译为环境光遮蔽。在DirectX 10.1 API推出后,Amblent Occlusion升级为SSAO(Screen-Space Ambient Occlusion:屏幕空间环境光遮蔽)&#…

GPU Gems1 - 18 空间BRDF(Spatial BRDFs)

这章主要介绍了空间双向反射分布函数(SBRDF),接着文章讨论了压缩SBRDF表达式,以及由离散光或环境贴图所照明的SBRDF的渲染方法。关于BRDF请参考大佬浅墨的这篇文章https://blog.csdn.net/poem_qianmo/article/details/75943714 S…

浅谈表面反射——波动光学篇

Radiometric Definitions 首先让我们来回忆一下辐射度量学中关于irradiance和radiance的定义: 我们在这里定义光源(source)在x-z平面,因此入射光就可以只用θi\theta_{i}θi​来描述。dAs\mathrm{d}A_{s}dAs​是表面积。定义dΦi\mathrm{d}\Phi_{i}dΦ…

GPU Gems1 - 19 基于图像的光照(Image-Based Lighting)

这篇文章打破了当时立方体贴图环境(Cube-Map Environment)用法的桎梏,深入研究了更多可能的逼真光照效果。文章主要研究了基于图像的光照(Image-Based Lighting,IBL),包括局部化的立方体映射&am…

Polygonal-Light Shading with LTC

概述 如果我们有一个上半球的余弦分布函数(Do)(D_{o})(Do​),并对这个余弦分布函数进行一个矩阵(M)(M)(M)变换,变换为一个新的分布函数(D)(D)(D)。 DMDoD M D_{o}DMDo​ 这就是基本思想:用一个余弦分布函数来拟合出不同的分布函数&#xff…

GPU Gems1 - 20 纹理爆炸(Texture Bombing)

【章节概览】 这章介绍了纹理爆炸(Texture Bombing)和相关的细胞技术,它们能在Shader中增加视觉的丰富性,图像的多样性,并减少大块纹理图案的重复性。 【核心要点】 纹理爆炸(Texture bombing&#xff0…

Catlike Coding网站文章解析 -- 1.Procedural Grid

原文英文版链接https://catlikecoding.com/unity/tutorials/procedural-grid/,里面有每一部分的untiy工程链接,文章内容也更详实。 本章内容: 创建一系列点使用协程实现他们的摆放位置定义一个由三角形组成的平面自动生成法线添加纹理坐标和…

GPU Gems1 - 21 实时辉光(Real-Time Glow)

这章浅墨的文章讲的很细了,这里基本照扒一遍加深印象,原文链接:https://zhuanlan.zhihu.com/p/36499291 【章节概览】 这章讲到2D光照效果中的辉光(Glow)和光晕(Halo),展示了如何通…

Catlike Coding网站文章解析 -- 2.Procedural Grid

本章内容 创建一个闭合的cube mesh给cube添加带弧度平滑的边缘定义法线使用sub-meshes(子mesh)创建一个常规shader合并碰撞体1.合成一个cube 上一章https://mp.csdn.net/postedit/89474068我们已经实现了一个平面mesh。一个cube由6个平面组成&#xff…