计算机图形学入门18:阴影映射

1.前言

前面几篇关于光栅化的文章中介绍了如何计算物体表面的光照,但是着色并不会进行阴影的计算,阴影需要单独进行处理,目前最常用的阴影计算技术之一就是Shadow Mapping技术,也就是俗称的阴影映射技术。

2.阴影映射

Shadow Mapping是一种图像空间的算法。所谓图像空间就是使用Shadow Mapping在生成阴影的这一步,是不需要考虑场景中几何信息的。Shadow Mapping还会产生走样现象。

Shadow Mapping最重要的核心思想是:不在阴影中的点必须同时被光线和相机看到。

2.1 阴影映射过程

1.先从光源看向场景,得到深度图 。如下图所示,在一个点光源位置上放一个虚拟的相机看向场景,做一遍光栅化得到光源能看到的图,这张图不需要着色,只需要把深度记录下来即可,此时得到的这个深度图 即为Shadow Map

2.从相机视角渲染场景,得到对应深度图对应深度值。如下图所示,从相机视角渲染场景,将所有相机视角可见的点,利用光源视角下的那一套投影矩阵的逆矩阵,将坐标从世界坐标转换到光源视角的空间坐标,得到光源视角下的深度值,并找到在深度图上对应的深度值。

如果该点投影回光源视角的实际深度值不大于在深度图上对应的深度值(注意这里的深度值是浮点数,因为精度问题难以比较两个值相等),则说明此点可被光源照射,因此不在阴影中,如上图黄色线的这种情况。

如果该点投影回光源视角的实际深度值大于在深度图上对应的深度值,则说明该点前方有物体遮挡,因此在阴影中,如上图红色线这种情况。

这样就能判断哪些像素在阴影中了。下面举一个例子,如下图所示,是一个生成了阴影的场景。

先来比较有阴影和无阴影的区别,如下图所示。

从光线角度看生成的Shadow Map如下图所示。距离光源越近代表深度越小,所以颜色越黑,反之亦然。

将相机视角方向渲染的投影到光源视角,通过深度图得到对应的深度值。如下图所示,球上对应的阴影信息看起来很脏,那是因为判断浮点数相等是很难的,只能判断大于。还会存在精度和走样的问题。

2.2 Shadow Map的问题

1.Shadow Map只能产生硬阴影(Hard Shadows) 。虽然有其他办法可以用来生成软阴影(Soft Shadows),但是理论上只用来生成硬阴影,只适用于没有体积的点光源。

软硬阴影区别示意如下,上方棱角分明为硬阴影,下方为软阴影。软阴影效果更加真实。

产生这种问题的原因是因为光源具有体积,导致有的地方完全看不到光源**(本影, Umbra)** ,有的地方能看到一部分光源**(半影,Penumbra)**。所以阴影的边缘在本影与半影之间会有过渡的情况,从而产生软阴影现象,就像上图中太阳与地球的角度导致的日食现象一样。所以点光源也无法产生软阴影,因为点光源没有体积大小。

2.阴影质量取决于Shadow Map的分辨率。分辨率越高性能消耗也更多。

3.涉及相等比较的浮点深度值意味着尺度、偏差、容差等问题

相关推荐
踢足球的程序员·2 天前
图形渲染: tinyrenderer 实现笔记(Lesson 5 - 7)
笔记·图形渲染
踢足球的程序员·9 天前
GAMES101-现代计算机图形学入门(Animation/simulation)
图形渲染
米芝鱼10 天前
LearnOpenGL(九)自定义转换类
开发语言·c++·算法·游戏·图形渲染·shader·opengl
二川bro15 天前
HarmonyOS NEXT(九) :图形渲染体系
华为·图形渲染·harmonyos
小老鼠不吃猫15 天前
万象更新(一)VTK 坐标轴、相机方向坐标轴、立方体坐标轴
c++·开源·图形渲染
HELLOMILI1 个月前
[Unity3D] 动态立方体贴图系统
游戏·unity·游戏引擎·图形渲染·着色器
拿我格子衫来1 个月前
图形编辑器基于Paper.js教程24:图像转gcode的重构,元素翻转,旋转
前端·javascript·图像处理·编辑器·图形渲染
HELLOMILI1 个月前
第四章:反射-Reflecting Your World《Unity Shaders and Effets Cookbook》
游戏·unity·游戏引擎·游戏程序·图形渲染·材质·着色器
Thomas_YXQ1 个月前
Unity3D 图形渲染(Graphics & Rendering)详解
开发语言·unity·图形渲染·unity3d·shader