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

在OpenGL中,有没有一种方法可以获取所有制服的列表&;着色器程序使用的属性?,opengl,3d,shader,glsl,Opengl,3d,Shader,Glsl,我想获得着色器程序对象使用的所有制服和属性的列表glGetAttriblLocation()&glGetUniformLocation()可用于将字符串映射到某个位置,但我真正想要的是字符串列表,而无需解析glsl代码 注意:在OpenGL 2.0中,glGetObjectParameteriv()替换为glGetProgramiv()。枚举是两个示例之间共享的GL\u ACTIVE\u UNIFORMS&GL\u ACTIVE\u ATTRIBUTES变量: 属性 glGetProgramiv

我想获得着色器程序对象使用的所有制服和属性的列表
glGetAttriblLocation()
&
glGetUniformLocation()
可用于将字符串映射到某个位置,但我真正想要的是字符串列表,而无需解析glsl代码

注意:在OpenGL 2.0中,
glGetObjectParameteriv()
替换为
glGetProgramiv()
。枚举是两个示例之间共享的
GL\u ACTIVE\u UNIFORMS
&
GL\u ACTIVE\u ATTRIBUTES

变量:

属性
glGetProgramiv(程序、GL\u活动属性和计数);
printf(“活动属性:%d\n”,计数);
对于(i=0;i
制服
glGetProgramiv(程序、GL\u活动制服和计数);
printf(“活动制服:%d\n”,计数);
对于(i=0;i
OpenGL文档/变量类型 可以在中找到表示变量类型的各种宏 医生。例如
GL\u FLOAT
GL\u FLOAT\u VEC3
GL\u FLOAT\u MAT4
,等等


对于那些在WebGL中发现这个问题的人来说,这里是WebGL的等价物:

var program=gl.createProgram();
//…附加着色器,链接。。。
var na=gl.getProgramParameter(程序、gl.ACTIVE\u属性);
log(na,‘attributes’);
对于(变量i=0;i
在OpenGL中完成此类操作的方式发生了变化。让我们来介绍一下

老路 链接着色器具有许多活动制服和活动属性(顶点着色器阶段输入)的概念。这些是该着色器正在使用的制服/属性。可以使用以下工具查询这些(以及许多其他内容)的数量:

您可以通过这种方式查询活动的统一块、转换反馈变量、原子计数器以及类似的内容

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

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);
}
此外,对于制服,还有
glGetActiveUniforms
,它可以一次查询每个制服的所有名称长度(以及所有类型、数组大小、步幅和其他参数)

新方式 通过这种方式,您可以访问成功链接的程序中有关活动变量的几乎所有信息(常规全局变量除外)。这个扩展还没有被广泛使用,但它会实现的

它首先调用,以查询活动属性/制服的数量。或者任何你想要的东西

GLint numActiveAttribs = 0;
GLint numActiveUniforms = 0;
glGetProgramInterfaceiv(prog, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numActiveAttribs);
glGetProgramInterfaceiv(prog, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numActiveUniforms);
属性只是顶点着色器输入
GL\U PROGRAM\U INPUT
表示程序对象中第一个程序的输入

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

std::矢量名称数据(256);
std::向量属性;
属性。向后推(GL\U名称\U长度​);
属性。推回(GL类型​);
属性。推回(GL\U数组大小)​);
std::向量值(properties.size());
对于(int attrib=0;attrib

完全相同的代码适用于
GL_UNIFORM
;只需将
numativeattribs
numativeuniforms

交换即可。以下是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)

显然,Nicol Bolas提到的“新方法”在python中不起作用。

完美的答案:简短、直截了当,以及我想知道的一切:-)此外,这里没有
GL\u OBJECT\u ACTIVE\u UNIFORMS
,有一个
GL\u OBJECT\u ACTIVE\u UNIFORMS\u ARB
,但是您实际想要使用的是
GL\u ACTIVE\u UNIFORMS
。属性也是如此。我只是注意到了一点,这只为统一数组中的第一个元素提供了位置。不是所有的。W如果你想要/需要所有的元素,你会怎么做?@Makogan整个数组都有这个位置。要设置它,你可以使用
glUniform??v
,将
count
设置为数组中的元素数。制服的实际元素数由
glGetActiveUniform
输出参数返回。谢谢但是
actualLength-1
应该是
actualLength-1
as
glGetActiveAttrib
返回名称的长度,不包括空字符。
GLint numActiveAttribs = 0;
GLint numActiveUniforms = 0;
glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTES, &numActiveAttribs);
glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &numActiveUniforms);
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);
}
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);
}
GLint numActiveAttribs = 0;
GLint numActiveUniforms = 0;
glGetProgramInterfaceiv(prog, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numActiveAttribs);
glGetProgramInterfaceiv(prog, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numActiveUniforms);
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);
}
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)