Czy w OpenGL jest sposób na uzyskanie listy wszystkich uniformów i atrybutów używanych przez program shadera?

Chciałbym uzyskać listę wszystkich uniformów i atrybutów używanych przez obiekt programu shadera. glGetAttribLocation() & glGetUniformLocation() może być używany do mapowania łańcucha znaków do lokalizacji, ale to, co naprawdę chciałbym, to lista łańcuchów bez konieczności analizowania kodu glsl.

Uwaga: w OpenGL 2.0 glGetObjectParameteriv() zastępuje się glGetProgramiv(). A enum jest GL_ACTIVE_UNIFORMS & GL_ACTIVE_ATTRIBUTES.

Author: Rabbid76, 2009-01-13

4 answers

zmienne współdzielone między obydwoma przykładami:

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

Atrybuty

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

Mundury

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

Dokumentacja OpenGL / Typy Zmiennych

Różne makra reprezentujące typy zmiennych można znaleźć w docs. Takie jak GL_FLOAT, GL_FLOAT_VEC3, GL_FLOAT_MAT4, itd.

 79
Author: NeARAZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-17 11:42:19

Nastąpiła zmiana w sposobie wykonywania tego typu czynności w OpenGL. Przedstawimy więc starą i nową drogę.

Old Way

[[16]}połączone cieniowniki mają koncepcję wielu aktywnych uniformów i aktywnych atrybutów (wejścia wierzchołków cieniowania). Są to mundury / atrybuty, które są używane przez ten shader. Liczba tych (a także kilka innych rzeczy) można sprawdzić za pomocą glGetProgramiv :
GLint numActiveAttribs = 0;
GLint numActiveUniforms = 0;
glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTES, &numActiveAttribs);
glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &numActiveUniforms);

Możesz odpytywać aktywne uniform blocks, transform feedback varyings, atomic counters, i podobne rzeczy w ten sposób.

Po uzyskaniu liczby aktywnych atrybutów / uniformów, możesz rozpocząć wyszukiwanie informacji o nich. Aby uzyskać informacje o atrybucie, należy użyć glGetActiveAttrib; aby uzyskać informacje o mundurze, używasz glGetActiveUniform. Jako przykład, rozszerzony z powyższego:

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

Coś podobnego można zrobić dla mundurów. Jednak trick GL_ACTIVE_UNIFORM_MAX_LENGTH​ może być wadliwy na niektórych kierowcach. Więc ja bym zasugeruj to:

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

Również, dla mundurów, istnieje glGetActiveUniforms, który może odpytywać wszystkie długości nazw dla każdego munduru na raz (a także wszystkie typy, rozmiary tablic, stopnie i inne parametry).

New Way

W ten sposób można uzyskać dostęp do prawie wszystkiego o aktywnych zmiennych w pomyślnie połączonym programie (poza zwykłymi globalami). Rozszerzenie ARB_program_interface_query nie jest jeszcze powszechnie dostępne, ale będzie tam.

Zaczyna się od wezwania do glGetProgramInterfaceiv, aby sprawdzić liczbę aktywnych atrybutów/uniformów. Albo cokolwiek innego.

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

Atrybuty są tylko wejściami shaderów wierzchołków; GL_PROGRAM_INPUT oznacza wejścia do pierwszego programu w obiekcie programu.

Możesz następnie zapętlić liczbę aktywnych zasobów, prosząc o informacje na temat każdego z nich z kolei, z glGetProgramResourceiv oraz 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);
}

Ten sam kod by działał dla GL_UNIFORM; tylko zamień numActiveAttribs na numActiveUniforms.

 52
Author: Nicol Bolas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-03 19:00:54

Dla każdego, kto znajdzie to pytanie i chce to zrobić w WebGL, oto odpowiednik 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);
}
 19
Author: Grumdrig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-26 21:46:52

Oto odpowiedni kod w Pythonie do pobrania uniformów:

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)

Najwyraźniej 'nowa droga', o której wspomniał Nicol Bolas, nie działa w Pythonie.

 0
Author: Christopher Bruns,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-17 02:49:39