代码之家  ›  专栏  ›  技术社区  ›  hyperlogic

在OpenGL中,有没有一种方法可以获取一个着色程序使用的所有制服和属性的列表?

  •  39
  • hyperlogic  · 技术社区  · 16 年前

    我想获得一个shader程序对象使用的所有制服和属性的列表。 glGetAttribLocation() 和; glGetUniformLocation() 可以用来将一个字符串映射到一个位置,但我真正想要的是不需要解析glsl代码的字符串列表。

    注:在OpenGL 2.0中 glGetObjectParameteriv() 被替换 glGetProgramiv() . 枚举是 GL_ACTIVE_UNIFORMS 和; GL_ACTIVE_ATTRIBUTES .

    4 回复  |  直到 16 年前
        1
  •  59
  •   vallentin Remi    8 年前

    两个示例之间共享的变量:

    GLint i;
    GLint count;
    
    GLint size; // size of the variable
    GLenum type; // type of the variable (float, vec3 or mat4, etc)
    
    const GLsizei bufSize = 16; // maximum name length
    GLchar name[bufSize]; // variable name in GLSL
    GLsizei length; // name length
    

    属性

    glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &count);
    printf("Active Attributes: %d\n", count);
    
    for (i = 0; i < count; i++)
    {
        glGetActiveAttrib(program, (GLuint)i, bufSize, &length, &size, &type, name);
    
        printf("Attribute #%d Type: %u Name: %s\n", i, type, name);
    }
    

    制服

    glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &count);
    printf("Active Uniforms: %d\n", count);
    
    for (i = 0; i < count; i++)
    {
        glGetActiveUniform(program, (GLuint)i, bufSize, &length, &size, &type, name);
    
        printf("Uniform #%d Type: %u Name: %s\n", i, type, name);
    }
    

    OpenGL文档/变量类型

    表示变量类型的各种宏可以在 博士学位。如 GL_FLOAT , GL_FLOAT_VEC3 , GL_FLOAT_MAT4 等。

        2
  •  44
  •   Nicol Bolas    8 年前

    这类事情在OpenGL中的处理方式发生了变化。所以,让我们呈现 the old way and the new way .

    老路

    链接的明暗器具有许多活动一致性和活动属性(顶点明暗器阶段输入)的概念。这些是该材质球正在使用的制服/属性。可以查询这些(以及许多其他事物)的数量 glGetProgramiv :

    GLint numActiveAttribs = 0;
    GLint numActiveUniforms = 0;
    glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTES, &numActiveAttribs);
    glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &numActiveUniforms);
    

    您可以用这种方式查询活动的统一块、转换反馈变量、原子计数器和类似的东西。

    一旦拥有活动属性/制服的数量,就可以开始查询有关这些属性/制服的信息。要获取有关属性的信息,请使用 glGetActiveAttrib ;要获取有关制服的信息,请使用 glGetActiveUniform . 例如,从上面扩展:

    GLint maxAttribNameLength = 0;
    glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH​, &maxAttribNameLength);
    std::vector<GLchar> nameData(maxAttribNameLength)
    for(int attrib = 0; attrib < numActiveAttribs; ++attrib)
    {
      GLint arraySize = 0;
      GLenum type = 0;
      GLsizei actualLength = 0;
      glGetActiveAttrib(prog, attrib, nameData.size(), &actualLength, &arraySize, &type, &nameData[0]);
      std::string name((char*)&nameData[0], actualLength - 1);
    }
    

    制服也可以做类似的事情。然而, GL_ACTIVE_UNIFORM_MAX_LENGTH​ 对一些司机来说,这种把戏可能是恶作剧。所以我建议:

    std::vector<GLchar> nameData(256);
    for(int unif = 0; unif < numActiveUniforms; ++unif)
    {
      GLint arraySize = 0;
      GLenum type = 0;
      GLsizei actualLength = 0;
      glGetActiveUniform(prog, unif, nameData.size(), &actualLength, &arraySize, &type, &nameData[0]);
      std::string name((char*)&nameData[0], actualLength - 1);
    }
    

    另外,对于制服来说, glGetActiveUniforms 它可以一次查询每个统一体的所有名称长度(以及所有类型、数组大小、步幅和其他参数)。

    新途径

    通过这种方式,您几乎可以访问 一切 关于成功链接程序中的活动变量(常规全局变量除外)。这个 ARB_program_interface_query 扩展还没有被广泛使用,但它会到达那里。

    它从一个呼叫开始 glGetProgramInterfaceiv ,以查询活动属性/制服的数量。或者其他你想要的。

    GLint numActiveAttribs = 0;
    GLint numActiveUniforms = 0;
    glGetProgramInterfaceiv(prog, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numActiveAttribs);
    glGetProgramInterfaceiv(prog, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numActiveUniforms);
    

    属性只是顶点着色输入; GL_PROGRAM_INPUT 表示程序对象中第一个程序的输入。

    然后,您可以循环访问活动资源的数量,依次询问每个资源的信息,从 glGetProgramResourceiv glGetProgramResourceName :

    std::vector<GLchar> nameData(256);
    std::vector<GLenum> properties;
    properties.push_back(GL_NAME_LENGTH​);
    properties.push_back(GL_TYPE​);
    properties.push_back(GL_ARRAY_SIZE​);
    std::vector<GLint> values(properties.size());
    for(int attrib = 0; attrib < numActiveAttribs; ++attrib)
    {
      glGetProgramResourceiv(prog, GL_PROGRAM_INPUT, attrib, properties.size(),
        &properties[0], values.size(), NULL, &values[0]);
    
      nameData.resize(values[0]); //The length of the name.
      glGetProgramResourceName(prog, GL_PROGRAM_INPUT, attrib, nameData.size(), NULL, &nameData[0]);
      std::string name((char*)&nameData[0], nameData.size() - 1);
    }
    

    完全相同的代码也适用于 GL_UNIFORM 只是交换 numActiveAttribs 具有 numActiveUniforms .

        3
  •  14
  •   Grumdrig    12 年前

    对于任何在webgl中发现这个问题的人,这里是webgl的等价物:

    var program = gl.createProgram();
    // ...attach shaders, link...
    
    var na = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
    console.log(na, 'attributes');
    for (var i = 0; i < na; ++i) {
      var a = gl.getActiveAttrib(program, i);
      console.log(i, a.size, a.type, a.name);
    }
    var nu = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
    console.log(nu, 'uniforms');
    for (var i = 0; i < nu; ++i) {
      var u = gl.getActiveUniform(program, i);
      console.log(i, u.size, u.type, u.name);
    }
    
        4
  •  -1
  •   Christopher Bruns    6 年前

    下面是python中获取制服的相应代码:

    from OpenGL import GL
    ...
    num_active_uniforms = GL.glGetProgramiv(program, GL.GL_ACTIVE_UNIFORMS)
    for u in range(num_active_uniforms):
        name, size, type_ = GL.glGetActiveUniform(program, u)
        location = GL.glGetUniformLocation(program, name)
    

    显然,NicolBolas提到的“新方法”在Python中不起作用。