triangulo - opengl vertex index
En OpenGL, ¿hay alguna manera de obtener una lista de todos los uniformes y attribs utilizados por un programa de sombreado? (4)
Aquí está el código correspondiente en python para obtener los uniformes:
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)
Aparentemente, la ''nueva forma'' mencionada por Nicol Bolas no funciona en Python.
Me gustaría obtener una lista de todos los uniformes y attribs utilizados por un objeto de programa de sombreado. glGetAttribLocation()
y glGetUniformLocation()
se pueden usar para asignar una cadena a una ubicación, pero lo que realmente me gustaría es la lista de cadenas sin tener que analizar el código glsl.
Nota: En OpenGL 2.0 glGetObjectParameteriv()
se reemplaza por glGetProgramiv()
. Y la enumeración es GL_ACTIVE_UNIFORMS
& GL_ACTIVE_ATTRIBUTES
.
Ha habido un cambio en la forma en que se hace este tipo de cosas en OpenGL. Entonces, presentemos el camino antiguo y el nuevo camino .
Vieja forma
Los sombreadores vinculados tienen el concepto de varios uniformes activos y atributos activos (entradas de etapa de sombreado de vértice). Estos son los uniformes / atributos que están en uso por ese sombreador. El número de estos (así como algunas otras cosas) se puede consultar con glGetProgramiv :
GLint numActiveAttribs = 0;
GLint numActiveUniforms = 0;
glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTES, &numActiveAttribs);
glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &numActiveUniforms);
Puede consultar bloques uniformes activos, transformar variaciones de comentarios, contadores atómicos y cosas similares de esta manera.
Una vez que tenga la cantidad de atributos / uniformes activos, puede comenzar a consultar información sobre ellos. Para obtener información sobre un atributo, use glGetActiveAttrib
; para obtener información sobre un uniforme, use glGetActiveUniform
. Como ejemplo, extendido desde lo anterior:
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);
}
Algo similar se puede hacer para los uniformes. Sin embargo, el truco GL_ACTIVE_UNIFORM_MAX_LENGTH
puede tener errores en algunos controladores. Así que sugeriría esto:
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);
}
Además, para los uniformes, hay glGetActiveUniforms
, que pueden consultar todas las longitudes de nombre para todos los uniformes, todo a la vez (así como todos los tipos, tamaños de arreglo, zancadas y otros parámetros).
Nueva manera
De esta manera, le permite acceder prácticamente a todo lo relacionado con las variables activas en un programa vinculado de manera exitosa (a excepción de los globales regulares). La extensión ARB_program_interface_query todavía no está disponible, pero llegará allí.
Comienza con una llamada a glGetProgramInterfaceiv
, para consultar el número de atributos / uniformes activos. O lo que sea que quieras.
GLint numActiveAttribs = 0;
GLint numActiveUniforms = 0;
glGetProgramInterfaceiv(prog, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numActiveAttribs);
glGetProgramInterfaceiv(prog, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numActiveUniforms);
Los atributos son solo entradas de sombreado de vértices; GL_PROGRAM_INPUT
significa las entradas al primer programa en el objeto del programa.
A continuación, puede recorrer el número de recursos activos, pidiendo información sobre cada uno de ellos, desde glGetProgramResourceiv
y 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);
}
El mismo código exacto funcionaría para GL_UNIFORM
; simplemente cambie numActiveAttribs
con numActiveUniforms
.
Para cualquiera que encuentre esta pregunta que busca hacer esto en WebGL, aquí está el equivalente de 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);
}
Variables compartidas entre ambos ejemplos:
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
Atributos
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);
}
Uniformes
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);
}
Documentación OpenGL / Tipos de Variables
Las diversas macros que representan tipos de variables se pueden encontrar en los documentos. Tales como GL_FLOAT
, GL_FLOAT_VEC3
, GL_FLOAT_MAT4
, etc.