Global Illumination_Reflective Shadow Maps(RSM)、Virtual Point Light(VPL)

本文详细介绍了反射阴影贴图(RSM)中的虚拟点光源算法,包括其基本原理、着色公式、优缺点以及算法改进。通过G-buffer生成和RSM计算步骤,展示了如何在图形学中模拟间接光照,解决多光源效率和遮挡问题。

在这里插入图片描述

光照可以分为两类:一类为直接光照,这类光照是直接由光源或者发光物发出的光照;另一类为直接光照之后反射的光照称为间接光照。直接光照的计算十分简单,因为计算的范围和次数(没有反射)有限。而对于间接光照而言计算就十分复杂,因为间接光照可能不止反射了一次,一束光可能需要经历了很多次反射才能到达着色点。而间接光照又十分重要,因此间接光照的模拟是图形学中一个经久不衰的话题。
在这里插入图片描述

一、反射阴影贴图/立即辐射度光照算法

1.1 虚拟点光源算法

RSM(Reflective Shadow Maps)的核心思想是把直接光源照亮的区域又作为发光物(虚拟点光源)来进行计算。
在这里插入图片描述

根据RSM的思想可以将本算法主要分成以下四步:

  1. 先单独计算直接光照对环境的影响;
  2. 从光源的视角进行一次渲染就可以得到从光源视角看的区域,也就是Shadow Map的基本思想。渲染之后我们需要再保存额外的G-Buffer数据:位置信息,法线信息和颜色信息(flux信息)到纹理中;
  3. 用第二步保存的信息用于计算间接光照,RSM的核心就是把这个发光区域的每一个像素都看成一个光源叫做虚拟点光源(也有的地方叫Virtual point light:VPL),然后用这所有的虚拟点光源来计算间接光照,那我们计算的时候就把每一个虚拟成点光源用下面的公式1计算即可;
  4. 将间接光照和直接光照融合起来(直接相加即可)。

1.2 着色公式

这部分可根据渲染方程具体推导得到,详细讲解可参照闫大神的202相关教程。

如上图,着色点 x 收到的某一个虚拟点光源 Xp 的辐射强度如下所示:
在这里插入图片描述

这个公式非常容易理解,如果大家把 L(Xp) 当做颜色的话,这就是一个点光源对着色点x的光照公式,这里最大的变数就在 L(Xp)

其中包括两种情况:

  • 第一种情况:如果我们的直接光源是平行光(也就是太阳光,不会衰减的),那么:
    在这里插入图片描述

其中 Cp 就为点 Xp 的颜色, I 为平行光的光照强度。

  • 第二种情况:如果直接光源为点光源 v
    在这里插入图片描述
    其中 I 为点光源的光照强度。

从上面可以看出来,VPL的方法就是先计算出VPL接收到的光照强度 L(Xp) ,然后再把这个VPL当成一个点光源来计算着色点的光照即可。

1.3 优缺点

在这里插入图片描述

简而言之,本方法最大的优点就是:简单易行。缺点就是:针对多光源效率差、没有考虑间接光的遮挡问题、受限于采样率、过多的假设。但总体来说问题不大可介绍。

1.4 算法改进

针对上述的效果受限于采样率的问题,可采用如下的优化:
这个算法非常直接,不过简单的代价就是效率低,大家可以想象如果发光区域很大的话比如长宽为 512 * 512 ,那么虚拟点光源的数量就为 512 * 512 个,如果要老老实实的计算所有虚拟点光源的话效率太过低下。因此文章提出了一个改进的办法,不把所有的VPL都用于间接光照的计算,而是有一个侧重的选取。那如何选取呢,作者假设屏幕空间里面里这个着色点越近的那么对光源贡献就更大。因此多选取一点离着色点近的VPL,并且为了弥补越往外采样数越少可能会带来的问题,作者引入了权重,越近了权重越小,越远的权重越大。如下图所示。
在这里插入图片描述

可以看到随着采样距离变大,采样密度在逐渐减小。采样公式(选取虚拟点光源)如下:
在这里插入图片描述
(s,t) 是当前着色点的屏幕空间的坐标(UV坐标),我们可以通过生成多组(这个一组就代表多计算一次间接光照,有几个就相当于用多少个虚拟点光源),ξ1,ξ2 为随机数(一组采样就需要一对随机数)代入上面的公式就可以得到一个采样坐标,然后再根据上面的光照计算公式来计算这个VPL对着色点的光照公式。注意:这种方法会有很大的误差,为了进行一些弥补,在每计算完一个虚拟点光源对着色点的光照之后应该再乘以权重 ξ1 * ξ2

二、算法实现

2.1 G-buffer生成

首先来看一下第一个pass的着色器如下:

顶点着色器:

#version 330 core
layout (location=0) in vec3 position;
layout (location=1) in vec3 normal;

out vec3 FS_normal;
out vec3 FS_position;

uniform mat4 lightSpaceMatrix;
uniform mat4 model;

void main()
{
   
   
	FS_normal=mat3(transpose(inverse(model)))*normal;
	vec4 worldPos=model*vec4(position, 1.0);
	FS_position=worldPos.xyz;
	gl_Position=lightSpaceMatrix*model*vec4(position, 1.0f);
}

片元着色器:

#version 330 core
layout (location=0) out vec3 normal;
layout 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值