OpenGL灯光限制

9
当我阅读《RedBook》时,我感到很困惑,因为OpenGL在场景中最多只能有8个灯光(数字取决于实现,但应该在8左右)。
但是我可以想象出需要更多灯光的情况,所以我认为在游戏开发中有一些技巧。例如,你有一个有50个路灯的非常长的街道,或者你可以有20个人的小队都使用手电筒。你如何模拟这些情况?问题在于,灯光只照亮网格的一部分,而不是源和对象之间的整个锥形区域,因此如果我们没有100%干净的空气,还必须进行某种形式的模拟。这是如何完成的,并且游戏运行流畅?(我也读到启用所有8个灯光可能会降低FPS)
3个回答

12

“8个灯光”是固定GL管线的限制,您可以启用它们中的每一个,设置模式、参数等。现在您有了像素着色器,灯光是在着色器内完成的。在那里,您可以使用大量动态(未嵌入纹理中)灯光。您只需要充分提供所有这些灯光的参数(也许在一个纹理中),并测试您的着色器能够处理多少个灯光。此外,在着色器中,您可以剔除太弱的灯光(对像素值的贡献太少)或距离太远的灯光。

更新:具有分支的复杂着色器甚至可以生成灯光(想象一下长街或圣诞树)。这可能比提供大量参数更有效率。


更新:这种技术已经被广泛讨论,以下是一个链接: http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=267432 - alxx
弱光不是着色器的特性,因为启用/禁用灯光的能力可以在固定管线之外通过设计灯光管理器来实现,只启用重要的灯光即可。 - Luca
灯光管理器可以启用/禁用整个场景的灯光。像素着色器可以逐像素执行此操作,看到区别了吗?顺便说一下,在传统管线中的8个灯光是每个顶点的,而着色器执行逐像素照明-完全不同的事情。 - alxx
我看到了区别,但从你的回答中似乎着重强调了着色器(通过像素)完成所有工作,但顶点光照有一个漂亮的外观,在当前世界中仍然有效,即使使用着色器。 - Luca
一旦你比较了每顶点和每像素着色,你几乎不会回到前者...想想凹凸贴图、视差贴图、反射和其他效果。 - alxx

5

在计算机图形学中,光照是一个非常复杂的话题。

最重要的当然是对象的照明,模拟真实世界的光照效果或我们所追求的效果。为了近似实现我们想要达到的真实效果,光照环境可以由许多光源组成。

OpenGL的光照实现是动态的光源,它们是抽象的光点,可以“照亮”(即赋予颜色)渲染的顶点(用于渲染三角形)。...顶点被照亮后,每个光源都会对其产生颜色贡献。

正如您所提到的,启用更多的光源会使渲染过程需要更长的时间。为了将其最小化,您有不同的可能性。

  • 光源剔除(排除那些对颜色影响太小的光源),并使用光属性(距离、锥体、衰减、视点和遮挡物)来确定这一点。
  • 静态照明,使用纹理来模拟永远不会移动的物体上的光照。

OpenGL固定光照会对顶点颜色产生贡献,这些颜色与其他顶点颜色插值以光栅化三角形。如果几何形状由少量三角形组成,则无法在每个三角形内看到任何光锥,因为它的片段颜色是三个颜色(三个顶点)的插值结果。

为了实现更精确的光照,软件应像对顶点进行染色一样确定每个片段(像素)的颜色(像素光照),但是正如您所理解的那样,可能会有比顶点更多的像素。

一种方法是在光栅化阶段计算每个几何形状像素的光的贡献(使用着色器或OpenGL扩展),或者使用延迟光照确定像素颜色。

延迟光照使用多个纹理(对应于视口)来存储每个显示像素的光参数。通过这种方式,在生成图像后执行光计算,仅为每个像素确定一次像素光贡献,而不是为每个几何像素确定一次。


4
游戏中用到的一个技巧是使用纹理来模拟光线。因此,在您的路灯示例中,“亮着的”区域实际上将是更亮的纹理图像。只有最近的灯光才能成为光源以获得正确的效果。
还有类似的方法,其中半透明纹理或带有透明锥的纹理被覆盖在场景上,以产生相同的效果。
请不要忘记,实时计算阴影等意味着必须从光的视角渲染场景,以计算任何给定位置的光强度。因此,对于8个光源,您需要在实际呈现场景之前渲染场景(或场景的部分)多达8次。即使这是在GPU而不是CPU上完成的,它也非常昂贵。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接