屏幕空间的阴影映射技术个人理解

首先我们来了解一下阴影的形成原理:

当一个光源发射的一条光线遇到一个不透明的物体时,这条光线就不可以再继续照亮其他物体(不考虑光线反射),这个物体就会向他旁边的物体投射阴影

而在实时渲染中,我们常用到一种名为Shadow map的技术,unity采用的就是这种技术

在Unity中,这个技术的实现是通过将摄像机位置与光源位置重合(光源空间),然后按照正常的渲染流程渲染出深度图来作为阴影映射纹理。但是需要注意的是,与正常渲染不同的是,由于我们只需要深度图信息,而正常的渲染流程会多出不必要的光照模型计算(Base Pass +Addition Pass),我们会采用一个额外的pass专门处理这项工作——LightMode标签下的ShadowCaster被选中后的pass。这个Pass的渲染目标只有深度纹理。

Unity首先把摄像机放置在光源的位置上,然后调用这个Pass,通过对定点进行变换后得到光源空间下的位置,然后据此输出深度信息到阴影映射纹理



再来说一说Unity中使用的不同于传统的阴影采样技术——屏幕空间的阴影映射技术

个人理解如下:

  1. 首先得到屏幕空间的深度图(摄像机视角下的深度信息),在延迟渲染中已经存在,在前向渲染中需要把场景渲染一遍,得到深度图
  2. 然后将摄像机与光源重合(光源空间)下通过那个特有的pass通道渲染出阴影映射纹理(其实也是一张深度图)
  3. 将屏幕空间下的深度图变换到光源空间,与阴影映射纹理进行比较,若前者深度更大(深度越大越不可见),则说明该区域虽然可见,但出于此光源的阴影中。
  4. 通过比较后得到一张包含了阴影信息的屏幕空间阴影图,通过这张图对阴影进行采样,就可以得到最后的阴影效果了。


对于比较的过程,我是这样理解的:
如图,在屏幕空间下有A,B两点可见,渲染出深度图后,假设B点的深度为x,通过B点的位置(屏幕空间——>世界空间——>光源空间)得到对应光源空间下B点的深度信息,假设为y。由图可以轻易地看出在光源空间下B点是不可见的,也就是说y>x(具体的比较方法可能并非如此,但这样说便于理解)。此时我们就可以知道B是处于该光源的阴影中了。

这个过程概括来说就是把每一个像素根据它在摄像机深度纹理中的深度值得到世界空间坐标,再把它的坐标从世界空间转换到光源空间中,和光源的ShadowMap里面的深度值对比,如果大于ShadowMap中的深度距离,那么就说明光源无法照到,在阴影内。

更为详细准确的解释参考:Unity5.X中屏幕空间阴影投射技术(Screenspace ShadowMap)如何产生阴影图?...

第一次写博客,希望以后可以坚持下去!

原文地址:https://www.cnblogs.com/MayoHa/p/12248592.html

时间: 2024-11-02 00:29:04

屏幕空间的阴影映射技术个人理解的相关文章

[OpenGL] shadow mapping(实时阴影映射)

source:原文地址 code:点击可以直接下载源代码 1978年,Lance Williams在其发表的论文<Casting curved shadows on curved surfaces>中提出了Shadow mapping算法,从那以后,该算法在离线渲染和实时渲染两个领域都得到了广泛的应用.皮尔斯动画工作室的Renderman渲染器.以及一些知名电影如<玩具总动员>都使用了shadow mapping技术. 在众多图形应用的阴影技术中,shadow mapping只是产

Unity3d 屏幕空间人体皮肤知觉渲染&amp;次表面散射Screen-Space Perceptual Rendering &amp; Subsurface Scattering of Human Skin

之前的人皮渲染相关 前篇1:unity3d Human skin real time rendering 真实模拟人皮实时渲染 前篇2:unity3d Human skin real time rendering plus 真实模拟人皮实时渲染 plus篇 SSS:Unity3d shader之次表面散射(Subsurface Scattering) PBR:Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF Screen-Space P

阴影映射(Shadow Map)的研究(二)

阴影映射(Shadow Map)的研究(二) 上一篇文章介绍了我对Z缓存的较为详细的研究.这里之所以对Ze求导函数,是因为的我们需要寻找它的变化曲线,从而找到极值点,这样就能够确定Ze相对于zw的疏密分布情况.幸运的是,我们找到的导函数是双曲函数,并且我们关心的的右侧是单调递增的. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44946763.欢迎同行前来探讨. 引出上一篇文章的结论,当 时,导函数取得最大值.但是在Zw∈

阴影映射(Shadow Map)的研究(三)

阴影映射(Shadow Map)的研究(三) 最近为了自己制作的项目可是吃了不少苦头,这其中关键的一点就是想要实现阴影映射(Shadow Map).为了实现目标,我参考了网络上很多相关的资料,也看了一些案例,最终花了我一个月的时间将这个效果实现了. 阴影映射这样的效果,其实在即将发布的Qt 3D中已经有相关的介绍,KDAB中有一篇文章<Shadow Mappingin Qt3D 2.0>就在Qt 3D的框架上实现了阴影映射.不过当时这个效果是假定目标机器支持OpenGL 3.0规范的,目前大部

精髓——高度概括几种页框到线性地址的映射技术

第一种:就是页框到线性地址的一 一映射关系.这是在分页阶段,已经建立好的(这部分我可以深入讲一下,但是这部分内容不是很难,而且我的肩膀好酸痛,就不写了,以后在补上),就是为物理内存前896M的每个页框建立页表,并写进页表项.当进程请求这部分内存时,可以直接访问到这些页表,而不并现场创建页表. 第二种:高端内存永久内核映射.就是上一篇博文讲到的.这种技术的映射可以阻塞进程,使进程去睡眠. 第三种:临时内核映射.其实道理差不多.任何一个页框与权限合成的页表可以写进预留的几个页表项中,但这种技术是不能

对AJAX技术的理解,创建,与应用

ajax的理解: 1. ajax是介于客户端与服务器端之间的一个机制,但这一机制是在前台的,利用前台的闲置功能,来进行前台与后台的数据交流,以达到增强用户体检,减少服务器压力,更有效的利用带宽的效果. 2. ajax是采用异步交互的机制. 3. ajax使用于页面局部刷新,按需求验证和取数据. 4. ajax缺点便是浏览器的兼容问题麻烦,与嵌入式移动端对ajax的支持不太理想. 5.ajax已经是一种web开发必备的技术,而且其优点远大于缺点. 6.ajax涉及到的主要技术有7种其中Javasc

.NET学习之路----我对P/Invoke技术的理解(一)

看了P/Invoke技术的介绍,于是想写下点东西,东西包含两个部分:知识的纪录和我的理解及疑问. r托管代码中调用非托管API函数的过程 1.定位包含API的DLL: 2.载入DLL 3.找到DLL中想要的那个API,然后把参数压入栈中.排列数据(排列数据是什么意思?数据封送) 4.把执行权限从托管代码中转移到非托管代码中() 对Dll中的函数进行一些说明,以能调用 DllImport特性来说明函数,有一些特殊的作用,比如换掉API的原来名字,见DLLImport特性. 非托管函数和托管方法中数

阴影映射(Shadow Map)的研究(四)

阴影映射(Shadow Map)的研究(四) 上一篇文章粗略地介绍了要实现OpenGL ES 2.0的阴影映射所需的知识难点,现在简略地说明一下:1.FBO:2.着色器:3.float的分拆以及组合.上篇文章虽然说已经成功地移植了来自Java编写的Android下阴影映射的效果,但这边采用的很大程度上是OpenGL原生代码编写的内容,接下来的目标是采用自Qt 5起就逐渐采用的Qt对OpenGL的封装类,用面向对象的思维来处理OpenGL对象,这样让代码更加优雅. 1.FBO 首先说一下FBO.在

阴影映射(Shadow Map)的研究(五)

阴影映射(Shadow Map)的研究(五) 我成功地将别人的例子加以改进,使用QOpenGLWidget作为渲染窗口,将阴影映射渲染了出来.目前可以确定的是,使用OpenGL ES 2.0作为渲染的接口要求,能够让目前绝大多数机器都能够顺利兼容,但是囿于渲染窗口,可能在某些平台上表现不好.如果移植到Qt Quick 2,这样能够支持的平台就更多了.现在我将这些接口统统使用Qt的方式实现了,移植到Qt Quick 2也很简单. 这里主要参考的是OpenGLUnderQML这个例子,自定义了一个Q