漫反射光/阴影

Leo*_*Leo 9 opengl lighting glsl shadow game-engine

我刚刚在我的引擎中实现了一个灯光系统.在下面的屏幕截图中,您可以看到正在运行的灯光(黄色方块):

1 考虑到在照亮场景的光线之上,它还实现了一个FOV,它会遮挡你视野之外的任何东西.这就是为什么阴影的左侧部分看起来如此偏离.

正如你所看到的那样,光线的阴影非常"坚硬",因为它们甚至不能照亮其直接范围之外的一个区域.为了使灯光看起来更好,我对它们应用了一个过滤器,它几乎限制了要照明的范围,并且在该限制范围内略微照亮了该区域:

2

在大黄色圆圈中,即使没有直射光照射,您也可以看到该区域是如何照亮的.

然而,该解决方案带来一些不希望的副作用.正如您在下面的屏幕截图中看到的那样,即使没有任何光到达某个区域,如果它太靠近光源,它也会被点亮:

10

我想知道是否有任何方法可以通过正确使用着色器来实现我想要做的事情.我遇到的主要问题来自于我如何绘制这些阴影.

1)首先,我采用光线范围内的结构.

此时,我正在使用顶点,因为它们定义了阴影投射项的区域: 3

2)然后,对于这些对象中的每一个,我计算它们单独投射的阴影: 4

五

6 他们施放的阴影由CPU完成,通过计算身体每个顶点的投影.

3)然后GPU将这些形状绘制到纹理中以构成最终阴影:

7

我发现的问题是,制作这种弥散阴影效果,我需要最后的阴影.如果我在步骤2)中计算漫射阴影,则在固体B和C之间会出现光隙.

但是如果我在第3步中消除了阴影,我就不再拥有顶点信息,因为我拥有的所有信息都是在一个最终纹理中加起来的3个局部纹理.

那么,无论如何要实现这一目标吗?我的第一个想法是将变量传递给碎片器以计算有多少光进入暗区,但由于我将在最终阴影上处理此信息,因为它没有顶点信息,我完全迷失了什么我应该用这个做法.

我对这种方法可能完全错了,因为我对着色器的经验非常有限.

这是我现在拥有的一个例子,以及我想要的东西:我拥有的东西:光线半径的明亮照明(导致光线穿过墙壁. 7

我想要的是:距离光线结束的距离越远,阴影越强烈. 7

Nat*_*one 1

我认为无论您做什么,都必须针对无法直接看到原始光源的场景区域以不同的方式计算光线衰减。我不确定您实际上是如何将阴影体积应用到场景中的,但是您也许可以在生成阴影体积时执行诸如对边缘进行分类之类的操作(即它们来自墙壁还是来自线条)从光线到角落?),并相应地对待它们。

简而言之,我认为没有任何聪明的特定于着色器的技巧可以解决这个问题。这是您所使用的算法的限制,因此您需要改进算法以考虑阴影体积中边缘的不同性质。

- - 编辑 - -

好吧,我认为你最好的选择是创建两个阴影体积(或者更确切地说是阴影区域,因为我们在 2D 中工作)。一个将与您现在的情况完全相同,另一个将更小 - 您需要排除“软”阴影中的区域。然后,片段着色器中将包含三个类别:总阴影、软阴影和无阴影。

要创建第二个阴影贴图,我认为您需要执行一些操作,例如向由角落周围的光线创建的边缘添加固定角度。

--- 编辑 #2 ---

我认为你可以通过拍摄阴影区域和场景外框的轮廓来解决物体B和C之间的间隙问题。因此,对于每个阴影区域,您都会找到与外部框相交的两个最外面的点,然后丢弃中间的所有线段并用框的该部分替换它们。我觉得我应该能够说出该算法的名称,但此刻我却想不起来......

原场景: 原场景

单独的“硬”阴影: 单独的“硬”阴影

现在将阴影合并在一起: 联盟

最后,沿着阴影周围描边,保持盒子的边缘。您要识别的角是黄色的角。当您沿着阴影的周边进行追踪时,您需要穿过盒子的边缘,直到到达对角。这不是最容易编码的事情,但如果你已经做到了这一点,我想你可以弄清楚:)

轮廓

或者,简单地考虑照明区域可能会更容易。例如,您可以执行诸如取场景框和联合阴影区域之差的操作,这通常会给您多个多边形;丢弃除了包含光的那一个之外的所有东西,因为其余的都是假间隙。