从GLSL着色器获取常量

时间:2014-10-24 03:44:23

标签: c++ opengl glsl const shader

我有一个用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,认为以某种方式使用制服以便能够获取数据。我无法找到任何其他方法来查询程序以获得常量值。有没有人有任何想法,我怎么能够从着色器中拉出一个常量,以便我的程序获取在着色器中功能编码的信息以供它使用?

2 个答案:

答案 0 :(得分:9)

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

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

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()

答案 1 :(得分:0)

您无法从GLSL程序中查询常量。 GLSL规范中没有定义这样的东西。

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