我想得到一份所有制服和服装的清单。着色器程序对象使用的属性。 glGetAttribLocation()
& glGetUniformLocation()
可用于将字符串映射到某个位置,但我真正想要的是字符串列表,而不必解析glsl代码。
注意:在OpenGL 2.0中,glGetObjectParameteriv()
被glGetProgramiv()
取代。枚举是GL_ACTIVE_UNIFORMS
& GL_ACTIVE_ATTRIBUTES
。
答案 0 :(得分:62)
两个示例之间共享的变量:
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);
}
表示变量类型的各种宏可以在
文档。例如GL_FLOAT
,GL_FLOAT_VEC3
,GL_FLOAT_MAT4
等
答案 1 :(得分:45)
在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
交换。
答案 2 :(得分:16)
对于那些在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);
}
答案 3 :(得分:-1)
以下是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中不起作用。