源码分析学习记录(8)——阴影

2021SC@SDUSC
当光源发出的光线因为被其他物体遮挡而没有照射到某个物体时,该物体处于阴影中。阴影为渲染场景增添了大量真实感,并使观察者更容易看出对象之间的空间关系,为我们的场景提供了更大的深度感。到目前为止,能进行完美的实时阴影计算的算法并不存在,我们只有一些近似模拟的算法,不过它们都有各自的局限性和使用范围。

Shadow Mapping

阴影映射(shadow mapping)是 1978 年由兰斯·威廉姆斯 (Lance Williams) 在一篇题为“ Casting curved shadows on curved surfaces ”的论文中提出的。从那时起,它就开始被广泛用于离线渲染和实时图形渲染。
Shadow Map是一种非常常见的算法。它的原理非常简单,就是假设有一个摄像机在灯光的位置,从灯光的位置往物体看,这时候会有一张光源空间的深度信息图,这就是Shadow Map。凡是物体的深度值大于Shadow Map上的深度值的都是被遮挡的部分,都要显示阴影。图中蓝线代表光源可以看到的部分,被遮挡的部分显示为黑线,黑色部分被渲染为阴影。如果我们从光源到最右侧的盒子画一条射线,我们可以看到光线首先击中悬空的盒子,然后再击中最右侧的容器。结果,浮动容器的片段被点亮,而最右边的容器的片段没有被点亮,因此处于阴影中。在这里插入图片描述

Shadow Map只是在图形应用程序中产生阴影的方式之一,每种方式都有自己的优点和缺点。在阴影映射的情况下,这些包括:

深度缓冲

左图显示了一个发射平行光线的定向光源在立方体下方的表面上投射出阴影的场景。我们使用存储在深度图中的深度值,找到最近的点并根据它来确定片段是否在阴影中。我们通过使用针对该光源的视图和投影矩阵渲染场景来创建深度图。这个视图和投影矩阵一起形成了一个变换,该变换矩阵T将任意三维坐标转换到光源的坐标空间。深度缓冲区就是通过帧缓冲生成深度缓存,然后真实绘制时,去查询深度缓存确认当前纹理的坐标是否被遮挡,是的话就要绘制成阴影效果。
在右图中,我们看到相同的定向光和观察者。我们在点P渲染一个片段时,必须确定它是否处于阴影中。为此,我们首先利用矩阵T将点P转换到光源的坐标空间. 现在从光源的角度来看,P点的z坐标对应它的深度。我们还可以使用P点检索深度/阴影贴图,从光源的角度获得其最近的可见深度。由于索引深度图返回的深度小于点P的深度我们可以得出P点被遮挡的结论,因此片段处于阴影中。
在这里插入图片描述
因此,shadow map由两个部分组成:首先我们渲染深度图,然后我们渲染场景并使用生成的深度图来计算片段是否在阴影中

优点

  • 不需要场景几何知识或处理,因为阴影映射是一种图像空间技术,可自动处理在 GPU 上创建或更改的对象。
  • 只需要一个纹理来保存每个灯光的阴影信息;不使用模板缓冲区。
  • 避免阴影体积的高填充要求。

缺点

  • 混叠,尤其是在使用小阴影贴图时。
  • 场景几何体必须为每个光源渲染一次,以便为聚光灯生成阴影贴图,为全向点光源生成更多次。

获取深度图

使用对应的的帧缓冲区将深度值渲染到纹理。

NormalAndDepthMapsGenerator::NormalAndDepthMapsGenerator(ModelWidget *modelWidget)
{
   
    m_viewPortSize = QSize(modelWidget->widthInPixels(),
		modelWidget->heightInPixels());
    m_normalMapRender = createOfflineRender(modelWidget, 1);
    m_depthMapRender = createOfflineRender(modelWidget, 2);
}

ModelOffscreenRender *NormalAndDepthMapsGenerator::createOfflineRender(ModelWidget *modelWidget, int purpose)
{
   
    ModelOffscreenRender *offlineRender = new ModelOffscreenRender(modelWidget->format());
    offlineRender->setXRotation(modelWidget->xRot());
    offlineRender->setYRotation(modelWidget->yRot());
    offlineRender->setZRotation(modelWidget->zRot());
    offlineRender->setEyePosition
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值