当前位置:  开发笔记 > 编程语言 > 正文

在OpenGL中有一种方法可以获得着色器程序使用的所有制服和属性的列表吗?

如何解决《在OpenGL中有一种方法可以获得着色器程序使用的所有制服和属性的列表吗?》经验,为你挑选了3个好方法。

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

注意:在OpenGL 2.0中glGetObjectParameteriv()被替换为glGetProgramiv().而enum是GL_ACTIVE_UNIFORMS&GL_ACTIVE_ATTRIBUTES.



1> NeARAZ..:

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

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等.

glGetActiveAttrib

glGetActiveUniform



2> Nicol Bolas..:

在OpenGL中这种事情是如何完成的.让我们介绍旧的方式和新的方式.

老路

链接着色器具有许多活动制服和活动属性(顶点着色器阶段输入)的概念.这些是着色器正在使用的制服/属性.可以使用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 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 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表示程序对象中第一个程序的输入.

然后,您可以遍历活动资源的数量,要求信息的每一个反过来,从glGetProgramResourceivglGetProgramResourceName:

std::vector nameData(256);
std::vector properties;
properties.push_back(GL_NAME_LENGTH?);
properties.push_back(GL_TYPE?);
properties.push_back(GL_ARRAY_SIZE?);
std::vector 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; 只是换numActiveAttribsnumActiveUniforms.



3> Grumdrig..:

对于那些在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);
}

推荐阅读
跟我搞对象吧
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有