In OpenGL c'è un modo per ottenere un elenco di tutte le uniformi & amp; attributi usati da un programma shader?

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

  •  22-07-2019
  •  | 
  •  

Domanda

Vorrei avere un elenco di tutte le uniformi & amp; attributi utilizzati da un oggetto programma shader. glGetAttribLocation () & amp; glGetUniformLocation () può essere utilizzato per mappare una stringa in una posizione, ma quello che mi piacerebbe davvero è l'elenco delle stringhe senza dover analizzare il codice glsl.

Nota: in OpenGL 2.0 glGetObjectParameteriv () è sostituito da glGetProgramiv () . E l'enum è GL_ACTIVE_UNIFORMS & amp; GL_ACTIVE_ATTRIBUTES .

È stato utile?

Soluzione

Variabili condivise tra entrambi gli esempi:

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

Attributi

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);
}

Divise

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);
}

Documentazione OpenGL / Tipi di variabili

Le varie macro che rappresentano i tipi di variabili sono disponibili in Documenti. Come GL_FLOAT , GL_FLOAT_VEC3 , GL_FLOAT_MAT4 , ecc.

Altri suggerimenti

C'è stato un cambiamento nel modo in cui questo tipo di cose viene fatto in OpenGL. Quindi presentiamo il vecchio e il nuovo .

Old Way

Gli shader collegati hanno il concetto di un numero di uniformi attive e attributi attivi (input dello stadio shader del vertice). Queste sono le uniformi / attributi che sono in uso da quello shader. Il numero di questi (così come alcune altre cose) può essere interrogato con glGetProgramiv :

GLint numActiveAttribs = 0;
GLint numActiveUniforms = 0;
glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTES, &numActiveAttribs);
glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &numActiveUniforms);

È possibile eseguire query su blocchi uniformi attivi, trasformare in questo modo variazioni di feedback, contatori atomici e cose simili.

Una volta ottenuto il numero di attributi / uniformi attivi, è possibile iniziare a richiedere informazioni su di essi. Per ottenere informazioni su un attributo, usi glGetActiveAttrib ; per ottenere informazioni su un'uniforme, utilizzare glGetActiveUniform . Ad esempio, esteso da quanto sopra:

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);
}

Qualcosa di simile può essere fatto per le uniformi. Tuttavia, il trucco GL_ACTIVE_UNIFORM_MAX_LENGTH & # 8203; può essere errato su alcuni driver. Quindi suggerirei questo:

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);
}

Inoltre, per le uniformi, c'è glGetActiveUniforms , che può interrogare tutte le lunghezze dei nomi per ogni uniforme in una sola volta (così come tutti i tipi, dimensioni di array, falcate e altri parametri) .

New Way

In questo modo puoi accedere praticamente a tutto sulle variabili attive in un programma collegato con successo (tranne che per i normali globi). L'estensione ARB_program_interface_query non è ancora ampiamente disponibile, ma ci arriverà .

Inizia con una chiamata a glGetProgramInterfaceiv , a interrogare il numero di attributi / uniformi attivi. O qualsiasi altra cosa tu possa desiderare.

GLint numActiveAttribs = 0;
GLint numActiveUniforms = 0;
glGetProgramInterfaceiv(prog, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numActiveAttribs);
glGetProgramInterfaceiv(prog, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numActiveUniforms);

Gli attributi sono solo input di shader di vertici; GL_PROGRAM_INPUT indica gli input per il primo programma nell'oggetto programma.

È quindi possibile scorrere il numero di risorse attive, chiedendo informazioni su ciascuna a turno, da glGetProgramResourceiv e 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);
}

Lo stesso codice esatto funzionerebbe per GL_UNIFORM ; scambia numActiveAttribs con numActiveUniforms .

Per tutti quelli che trovano questa domanda cercando di farlo in WebGL, ecco l'equivalente di 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);
}

Ecco il codice corrispondente in Python per ottenere le uniformi:

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)

Apparentemente il 'nuovo modo' menzionato da Nicol Bolas non funziona in pitone.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top