glsl-es着色器中可变数量的灯光

时间:2014-06-14 14:37:29

标签: opengl-es glsl shader lighting

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

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

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

1 个答案:

答案 0 :(得分:2)

由于着色器的源代码由在运行时传入的字符串组成,因此根据光源的数量或控制何种类型的任何其他参数,没有什么能阻止您动态构建源代码你需要的着色器。

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

#define LIGHT_COUNT 4

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

着色器编译相当昂贵,因此您可能希望为每个灯数缓存着色器程序。

另一个选择是Andon在评论中提出的建议。您可以将着色器写入所需光量计数的上限,然后传入作为每个光源倍增器的制服。对于你不需要的灯,你可以将乘数设置为0.由于你不需要对你不需要的光源进行额外的计算,因此效率不高。简单,如果符合您的性能要求可能会很好。