从 GLSL 着色器获取常量

Getting a constant from a GLSL shader

本文关键字:获取 常量 GLSL      更新时间:2023-10-16

我有一个用GLSL编写的着色器,其中包含用于保存光数据的结构数组。我使用常量来声明数组大小,这是很好的做法。假设此变量声明为

const int NUM_POINT_LIGHTS = 100;

如何使用C++从着色器中提取此数据,以便我的C++程序确切地知道它有多少光源可供它使用?我试过将其声明为

const uniform int NUM_POINT_LIGHTS = 100;

正如预期的那样,这不起作用(尽管奇怪的是,似乎统一规范只是覆盖了 const 规范,因为 OpenGL 抱怨我正在使用非 const 值初始化数组(。我也试过

const int NUM_POINT_LIGHTS = 100;
uniform numPointLights = NUM_POINT_LIGHTS;

这将起作用,除了GLSL优化了未使用的制服这一事实,所以我必须跟踪glsl,认为制服以某种方式使用,以便能够掌握数据。我无法找到任何其他方法来查询程序以获取常量值。有没有人知道我如何能够从着色器中提取常量,以便我的程序获取在着色器中功能编码的信息以供使用?

我认为你不能直接获得常量的值。但是,我认为您必须使用常量的值,最有可能作为统一数组的大小。如果是这种情况,您可以获取统一数组的大小,从而间接获取常量的值。

假设您的着色器包含如下内容:

const int NUM_POINT_LIGHTS = 100;
uniform vec3 LightPositions[NUM_POINT_LIGHTS];

然后你可以先得到这件制服的索引:

const GLchar* uniformName = "LightPositions";
GLuint uniformIdx = 0;
glGetUniformIndices(program, 1, &uniformName, &uniformIdx);

使用此索引,您可以检索此制服的属性:

const int nameLen = strlen("LightPositions") + 1;
const GLchar name[nameLen];
GLint uniformSize = 0;
GLenum uniformType = GL_NONE;
glGetActiveUniform(program, uniformIdx, nameLen, NULL,
                   &uniformSize, &uniformType, name);

然后uniformSize应该是NUM_POINT_LIGHTS常量的值。请注意,我还没有尝试过这个,但我希望我根据文档得到了正确的论点。

一个有点丑陋但可能非常实用的解决方案当然是从着色器源代码中解析值。由于在将其传递给glShaderSource()之前无论如何都需要读取它,因此挑选常量值应该很容易。

另一种选择,如果您的主要目标是避免在多个位置使用常量,则是在C++代码中定义它,并在读取着色器代码后动态地将常量定义添加到着色器代码中,然后在传递之前glShaderSource()

您不能只从 GLSL 程序查询常量。GLSL 规范中没有定义这样的事情。

统一

缓冲区对象可能是解决统一被优化问题的一种方法。https://www.opengl.org/wiki/Uniform_Buffer_Object