En OpenGL hay una manera de obtener una lista de todos los uniformes & amp; Atribus utilizadas por un programa de sombreado?

StackOverflow https://stackoverflow.com/questions/440144

  •  22-07-2019
  •  | 
  •  

Pregunta

Me gustaría obtener una lista de todos los uniformes y amp; Atribus utilizadas por un objeto de programa de sombreado. glGetAttribLocation () & amp; glGetUniformLocation () se puede 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 & amp; GL_ACTIVE_ATTRIBUTES .

¿Fue útil?

Solución

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 de OpenGL / Tipos de variables

Las diversas macros que representan tipos de variables se pueden encontrar en el docs. Como GL_FLOAT , GL_FLOAT_VEC3 , GL_FLOAT_MAT4 , etc.

Otros consejos

Ha habido un cambio en cómo se hace este tipo de cosas en OpenGL. Así que presentemos la forma antigua y la nueva .

Vieja forma

Los sombreadores vinculados tienen el concepto de varios uniformes activos y atributos activos (entradas de etapa de sombreador de vértices). Estos son los uniformes / atributos que usa ese sombreador. El número de estos (así como de muchas 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 de uniformes activos, transformar variaciones de retroalimentación, contadores atómicos y cosas similares de esta manera.

Una vez que tenga el número 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, utiliza glGetActiveUniform . Como ejemplo, extendido de 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 uniformes. Sin embargo, el truco GL_ACTIVE_UNIFORM_MAX_LENGTH puede tener errores en algunos controladores. Entonces 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 uniformes, hay glGetActiveUniforms , que puede consultar todas las longitudes de nombre para cada uniforme a la vez (así como todos los tipos, tamaños de matriz, zancadas y otros parámetros) .

Nueva forma

De esta forma, puede acceder a casi todo sobre las variables activas en un programa vinculado con éxito (excepto los globales). La extensión ARB_program_interface_query aún no está ampliamente disponible, pero llegará allí .

Comienza con una llamada a glGetProgramInterfaceiv , a consulta 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 sombreador de vértice; 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, solicitando información sobre cada uno a su vez, 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 funcionaría exactamente para GL_UNIFORM ; simplemente intercambie numActiveAttribs con numActiveUniforms .

Para cualquiera que encuentre esta pregunta buscando 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);
}

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top