从GLSL着色器获取常量

Dar*_*nth 4 c++ opengl shader const glsl

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

const int NUM_POINT_LIGHTS = 100;
Run Code Online (Sandbox Code Playgroud)

如何使用C++将这些数据从着色器中提取出来,以便我的C++程序确切地知道它可以使用多少个灯?我试过把它声明为

const uniform int NUM_POINT_LIGHTS = 100;
Run Code Online (Sandbox Code Playgroud)

正如所料,这不起作用(虽然奇怪的是,似乎统一规范只是覆盖了const规范,因为OpenGL抱怨我正在初始化一个非const值的数组).我也试过了

const int NUM_POINT_LIGHTS = 100;
uniform numPointLights = NUM_POINT_LIGHTS;
Run Code Online (Sandbox Code Playgroud)

这可以工作,除了GLSL优化掉未使用的制服这样的事实,所以我必须跟踪glsl认为以某种方式使用制服以便能够获得数据.我无法找到任何其他方法来查询程序以获得常量值.有没有人有任何想法,我怎么能够从着色器中拉出一个常量,所以我的程序获取在着色器中功能编码的信息供它使用?

Ret*_*adi 9

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

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

const int NUM_POINT_LIGHTS = 100;
uniform vec3 LightPositions[NUM_POINT_LIGHTS];
Run Code Online (Sandbox Code Playgroud)

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

const GLchar* uniformName = "LightPositions";
GLuint uniformIdx = 0;
glGetUniformIndices(program, 1, &uniformName, &uniformIdx);
Run Code Online (Sandbox Code Playgroud)

使用此索引,您可以检索此统一的属性:

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);
Run Code Online (Sandbox Code Playgroud)

uniformSize那么应该是NUM_POINT_LIGHTS常数的值.请注意,我没有尝试过这个,但我希望我能根据文档得到正确的论据.

一个有点丑陋但可能非常实用的解决方案当然是从着色器源代码中解析出来的值.由于您需要在传递之前以任何方式读取它,因此glShaderSource()选择常量值应该很容易.

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

  • +1用于动态地将"#define NUM_POINT_LIGHTS"注入着色器源 (2认同)