In OpenGL ist es eine Möglichkeit, eine Liste aller Uniformen & attribs von einem Shader-Programm verwendet zu bekommen?

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

  •  22-07-2019
  •  | 
  •  

Frage

Ich möchte eine Liste aller Uniformen & attribs von einem Shader-Programm-Objekt verwendet erhalten. glGetAttribLocation() & glGetUniformLocation() kann verwendet werden, um eine Zeichenfolge zu einem Ort auf der Karte, aber was würde ich wirklich gerne die Liste von Strings, ohne den GLSL Code zu analysieren zu haben.

Hinweis: In OpenGL 2.0 glGetObjectParameteriv() durch glGetProgramiv() ersetzt wird. Und die Enum ist GL_ACTIVE_UNIFORMS & GL_ACTIVE_ATTRIBUTES.

War es hilfreich?

Lösung

Variablen zwischen beiden Beispielen geteilt:

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

Attribute

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

Uniformen

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

OpenGL Dokumentation / Variablentypen

Die verschiedenen Makros repräsentieren Variablentypen können in die gefunden werden docs. Wie GL_FLOAT, GL_FLOAT_VEC3, GL_FLOAT_MAT4, etc.

Andere Tipps

Es hat eine Änderung, wie diese Art der Sache in OpenGL gemacht wird. Also lassen Sie uns vorliegenden die alte Art und Weise und die neue Art und Weise .

Old Way

verlinkte Shadern haben das Konzept einer Anzahl von aktiven Uniformen und aktivem Attribute (Vertex-Shader Stufeneingänge). Dies sind die Uniformen / Attribute, die von diesem Shader verwendet werden. Die Zahl dieser (wie auch schon einige andere Dinge) mit glGetProgramiv abgefragt werden :

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

Sie können aktive einheitliche Blöcke abfragen, verwandeln Feedback varyings, Atom-Zähler und ähnliche Dinge auf diese Weise.

Wenn Sie die Anzahl der aktiven Attribute / Uniformen haben, können Sie die Abfrage Informationen über sie starten. Um Daten zu einem Attribut, verwenden Sie glGetActiveAttrib ; Informationen über eine Uniform zu erhalten, verwenden Sie glGetActiveUniform . Als Beispiel aus der oben erweitert:

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

Etwas Ähnliches kann für Uniformen durchgeführt werden. Allerdings kann der GL_ACTIVE_UNIFORM_MAX_LENGTH​ Trick auf einige Treiber fehlerhaft sein. So würde ich dies vorschlagen:

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

Auch für Uniformen, gibt es glGetActiveUniforms, die alle Namenslängen für jede Uniform auf einmal (wie alle Typen, Feldgrößen, Schritte und andere Parameter als auch) abfragen können.

New Way

Auf diese Weise können Sie Zugriff auf so ziemlich alles über aktive Variablen in einem erfolgreich verknüpft Programm (mit Ausnahme der regulären Globals). Die ARB_program_interface_query Erweiterung ist nicht weit noch vorhanden, aber es wird dort .

Es beginnt mit einem Aufruf an glGetProgramInterfaceiv , die Anzahl der aktiven Attribute abzufragen / Uniformen. Oder was auch immer Sie möchten.

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

Attribute sind nur Vertex-Shader-Eingänge; GL_PROGRAM_INPUT bedeutet, dass die Eingaben in dem ersten Programm in dem Programmobjekt.

Sie können dann eine Schleife über die Anzahl der aktiven Ressourcen, für Informationen zu jeder wiederum zu fragen, von glGetProgramResourceiv und 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);
}

Der exakt gleiche Code würde für GL_UNIFORM arbeiten; nur tauschen numActiveAttribs mit numActiveUniforms.

Für jemanden da draußen, die diese Frage findet diese in WebGL suchen zu tun, hier ist die WebGL-äquivalent:

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

Hier ist der entsprechende Code in Python für die Uniformen bekommen:

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)

Anscheinend ist der von Nicol Bolas genannten ‚neuen Weg‘ nicht in Python funktioniert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top