如何在C++和GLSL代码中共享预处理宏?

3
我正在为一个OpenGL程序设置照明。我想在不必修改着色器的情况下轻松调整C++中的照明源数量。
在我的C++代码中:
#define NUM_LIGHTS 5
GLfloat lightposn [4 * NUM_LIGHTS];

在我的GLSL代码中:
 uniform vec4 lightposn[NUM_LIGHTS];

如何将NUM_LIGHTS值传递给我的着色器?在着色器中是否可以使用定义在C++文件中的宏?是否有另一种简单的方法来设置NUM_LIGHTS,以使其在我的C++代码和GLSL代码之间生效?

你的着色器是如何存储的?是在磁盘上,还是作为源代码中的字符串? - Synxis
在磁盘上的自己的文件中。 - morgancodes
1个回答

7

将包含#defines的头文件读入字符串中,通过将其首先传递给glShaderSource函数,在着色器前面“添加”它。

char *shader_src[3];
shader_src[0] = "#version ...\n";
shader_src[1] = ReadHeaderFile(....);
shader_src[2] = ReadShaderSourceFile(....);
glShaderSource(shader, 3, shader_src, NULL);
...compile, link, and check for errors...

这会出问题,因为着色器源文件的顶部应该有一个#version指令,并且#version指令必须是第一件事。除非你真的建议在头文件中也放置#version指令? - vallentin
只要头文件只包含 #define,那就没问题了(#version 只需要在任何声明和定义之前,而不是预处理器内容之前)。如果你真的需要的话,可以将 #version 放在它自己的源字符串中。 - Chris Dodd
不,那不是真的,它不应该这样。GLSL规范明确指出:“#version指令必须在着色器中的任何其他内容之前出现,除了注释和空格”。 - vallentin
@vallentin: #define本身会扩展为空格(根据C预处理器规范),因此可能会出现在#version之前。 - Chris Dodd
我该如何执行“...编译、链接和检查错误...”这一步骤?我如何手动运行预处理器?或者我是否可以以编程方式进行操作?而你所说的“链接”是什么意思?(抱歉,当涉及OpenGL着色器时,我是个新手。) - HelloGoodbye
1
@HelloGoodbye 使用glCompileShader进行编译,使用glLinkProgram进行链接,使用glGetShaderInfoLogglGetProgramInfoLog查看错误/警告。 - Chris Dodd

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