这一节主要讲的是动态阴影的技术。
阴影为照明场景增添了大量真实感,并使观看者更容易观察对象之间的空间关系。 它们为我们的场景和物体提供了更大的深度感。

在当前的实时(光栅化图形)研究中,还没有开发出完美的阴影算法。 有几种很好的阴影近似技术,但它们都有我们必须考虑的缺点。
基础知识:
1.shadow mapping阴影映射
大多数游戏使用的一种技术可以提供不错的结果并且相对容易实现,那就是shadow mapping阴影映射。 shadow mapping不太难理解,不会在性能上花费太多,并且很容易扩展到更高级的算法(如Omnidirectional Shadow Maps (全向)and Cascaded Shadow Maps(级联))。
我们从灯光的角度渲染场景并将生成的深度值存储在纹理中会怎样?通过这种方式,我们可以从灯光的角度对最接近的深度值进行采样。毕竟,深度值显示了从灯光的角度可见的第一个片段。我们将所有这些深度值存储在称为depth map深度贴图或shadow map阴影贴图的纹理中。

蓝色部分为亮光,黑色为阴影。

个人理解:
depth test流程:顶点生成fragment,重叠的fragment根据z值来进行depth记录
shadow mapping阴影映射:
如果要看某个点P是否在阴影里,先转换为光源视角,坐标P变成坐标T(坐标系变换),然后depth test 记录T点的depth值,是否看得见(检索此像素的depth map看能不能找到更小的depth),如果看不见,则把阴影信息记录在shadow mapping中。
注意:阴影深度图,是以灯光的视角坐标系来存储图像的。
Shadow mapping阴影映射由两个PASS通道组成:
第一个PASS通道,渲染深度图
第二个PASS通道中,我们正常渲染场景,并使用生成的深度图来计算片段是否在阴影中。
2.The depth map(第一个PASS,渲染深度图)
我们要生成深度图。 深度贴图是从灯光的角度渲染的深度纹理,我们将使用它来测试阴影。 因为我们需要将场景的渲染结果存储到纹理中,所以我们将再次需要framebuffer帧缓冲区。
unsigned int depthMapFBO;
glGenFramebuffers(1, &depthMapFBO);
接下来我们创建一个 2D 纹理,我们将使用它作为帧缓冲区的depth深度缓冲区:
const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
unsigned int depthMap;
glGenTextures(1, &depthMap);
glBindTexture(GL_TEXTURE_2D, depthMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
使用生成的深度纹理,我们可以将其附加为帧缓冲区的深度缓冲区:
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
//没有颜色缓冲区的帧缓冲区对象是不完整的,因此我们需要明确告诉 OpenGL 我们不会渲染任何颜色数据
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
//绑

本文详细介绍了动态阴影技术的基础知识,包括shadowmapping、深度贴图生成、光空间变换、阴影失真防治(Shadow Acne、Peter Panning)及PCF过滤。探讨了阴影映射的原理、常见问题如摩尔纹、阴影偏差和过度采样的解决方案,以及正交与透视投影的应用。
最低0.47元/天 解锁文章
285

被折叠的 条评论
为什么被折叠?



