【发布时间】:2016-09-09 22:31:44
【问题描述】:
我有一些用 GLSL 编写的数学函数,我想在同一着色器程序的 TES、几何和片段阶段使用它们。所有这些对所有这些着色器类型都非常有效,现在代码只是跨着色器文件复制粘贴。
我想从着色器文件中提取函数并将它们放入一个单独的文件中,从而生成一个着色器“库”。我至少可以看到两种方法:
- 制作一个着色器源预处理器,将“库”代码插入到着色器源中。
- 创建额外的着色器对象,每个着色器类型一个,从库源代码编译,并将它们链接在一起。这样,“库”可执行代码将在编译器和链接器级别的着色器阶段复制。实际上,这就是“库”着色器的使用方式,但在这种变体中,它们是特定于阶段的,不能在流水线阶段之间共享。
是否可以只编译一次着色器源(有适当的限制),将其链接到着色器程序并在管道的任何阶段使用它?我的意思是这样的:
GLuint shaderLib = glCreateShader(GL_LIBRARY_SHADER);
//...add source and compile....
glAttachShader(shProg, vertexShader);
glAttachShader(shProg, tesShader);
glAttachShader(shProg, geomShader);
glAttachShader(shProg, fragShader);
glAttachShader(shProg, shaderLib);
glLinkProgram(shProg); // Links OK; vertex, TES, geom and frag shader successfully use functions from shaderLib.
当然,库着色器不应该有in或out全局变量,但它可以使用uniforms。此外,函数原型应在每个着色器源中使用之前声明,因为可以将多个相同类型的着色器链接到一个程序中。
如果上述情况是不可能的,那为什么?这样的“库”着色器对于 GLSL 的类 C 编译模型看起来非常合乎逻辑。
【问题讨论】:
-
我个人使用预处理器方法。这很容易理解,您只需使用#include 之类的关键字即可使其工作,并且您可以通过一些索引工作轻松地将任何 GLSL 错误解析回原始库文件。这确实意味着您的驱动程序将编译更多代码,并且该代码将占用更多空间。但我发现这两个问题完全无关紧要。
标签: opengl compilation glsl shader