【问题标题】:Variable number of lights in glsl-es shaderglsl-es着色器中可变数量的灯光
【发布时间】:2014-07-20 10:16:54
【问题描述】:

我正在开发一个 3d 引擎,它应该适用于移动平台。目前我只想制作一个可以在 iOS 上运行并使用前向渲染的原型。在引擎中,场景可以有数量不定的不同类型(定向、聚光灯等)的灯光。渲染时,为每个对象(网格)构造一个影响该对象的灯光数组。该数组将始终具有 1 个或多个元素。我可以将光源信息打包成 1D 纹理并传递给着色器。灯光的数量可以放入这个纹理中,也可以作为单独的制服传递(我还没有尝试过,但这些是我在谷歌上搜索后的想法)。

问题在于并非所有 glsl-es 实现都支持具有可变限制的for 循环。所以我不能编写一个循环遍历光源的着色器,并期望它可以在广泛的平台上工作。 如果不支持具有可变限制的for 循环,是否有任何技术支持着色器中的可变数量的灯光?

我的想法: 对着色器源进行一些预处理,以针对不同数量的灯光手动展开循环。 因此,在这种情况下,如果我使用一种着色器渲染所有对象,并且灯光数量限制为 1 到 3,我最终将拥有 3 个不同的着色器(自动生成)用于 1、2 和 3 个灯光。 这是个好主意吗?

【问题讨论】:

  • 我认为着色器变体是通往这里的道路......我知道 tri-ace 最终为 Star Ocean 4 提供了 60,000 个着色器:slideshare.net/DAMSIGNUP/…
  • 这真的与你的循环控制是一个变量无关;没有它你就无法实现循环。您遇到的问题是用于循环索引变量的实际测试表达式是非常量的。并不是所有的实现都保证在 ES 2.0 中支持它。您可以考虑的一件事是始终执行循环的 3 次迭代,但将每次迭代的循环结果乘以布尔数组。如果你只想要灯光 0 的结果,那么这个数组看起来像 { 1, 0, 0 }。这充其量只是一个 hack,但它使事情变得简单。

标签: opengl-es glsl shader lighting


【解决方案1】:

由于着色器的源代码由您在运行时传入的字符串组成,因此没有什么可以阻止您动态构建源代码,具体取决于灯光数量或控制所需着色器类型的任何其他参数.

如果您使用的设置是着色器代码位于单独的文本文件中,并且您希望保持这种状态,您可以利用可以在着色器代码中使用预处理器指令这一事实。假设您使用LIGHT_COUNT 作为着色器代码中的灯光数量。然后在编译着色器代码时,在它前面加上所需计数的定义,例如:

#define LIGHT_COUNT 4

由于glShaderSource() 采用字符串数组,您甚至不需要任何字符串操作来将其连接到您从文件中读取的着色器代码。您只需将其作为附加字符串传递给glShaderSource()

着色器编译相当昂贵,因此您可能需要为每个光照计数缓存着色器程序。

另一个选项是 Andon 在评论中建议的。您可以为所需的光照计数上限编写着色器,然后传入作为每个光源乘数的制服。对于不需要的灯,将乘数设置为 0。这不是很有效,因为您要对不需要的光源进行额外的计算,但它很简单,如果它满足您的性能要求可能会很好.

【讨论】:

  • 非常感谢!预处理正是我想做的,但由于我是 openGL 的新手,我不确定这是一个好主意
猜你喜欢
  • 1970-01-01
  • 2019-01-09
  • 1970-01-01
  • 2023-04-05
  • 2017-08-11
  • 2011-08-31
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多