Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There has been a change in how this sort of thing is done in OpenGL. So let's present <a href="http://www.opengl.org/wiki/Program_Introspection" rel="nofollow noreferrer">the old way and the new way</a>.</p> <h3>Old Way</h3> <p>Linked shaders have the concept of a number of active uniforms and active attributes (vertex shader stage inputs). These are the uniforms/attributes that are in use by that shader. The number of these (as well as quite a few other things) can be queried with <a href="http://www.opengl.org/wiki/GLAPI/glGetProgram" rel="nofollow noreferrer">glGetProgramiv</a>:</p> <pre><code>GLint numActiveAttribs = 0; GLint numActiveUniforms = 0; glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTES, &amp;numActiveAttribs); glGetProgramiv(prog, GL_ACTIVE_UNIFORMS, &amp;numActiveUniforms); </code></pre> <p>You can query active uniform blocks, transform feedback varyings, atomic counters, and similar things in this way.</p> <p>Once you have the number of active attributes/uniforms, you can start querying information about them. To get info about an attribute, you use <a href="http://www.opengl.org/wiki/GLAPI/glGetActiveAttrib" rel="nofollow noreferrer"><code>glGetActiveAttrib</code></a>; to get info about a uniform, you use <a href="http://www.opengl.org/wiki/GLAPI/glGetActiveUniform" rel="nofollow noreferrer"><code>glGetActiveUniform</code></a>. As an example, extended from the above:</p> <pre><code>GLint maxAttribNameLength = 0; glGetProgramiv(prog, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH​, &amp;maxAttribNameLength); std::vector&lt;GLchar&gt; nameData(maxAttribNameLength) for(int attrib = 0; attrib &lt; numActiveAttribs; ++attrib) { GLint arraySize = 0; GLenum type = 0; GLsizei actualLength = 0; glGetActiveAttrib(prog, attrib, nameData.size(), &amp;actualLength, &amp;arraySize, &amp;type, &amp;nameData[0]); std::string name((char*)&amp;nameData[0], actualLength - 1); } </code></pre> <p>Something similar can be done for uniforms. However, the <code>GL_ACTIVE_UNIFORM_MAX_LENGTH​</code> trick can be buggy on some drivers. So I would suggest this:</p> <pre><code>std::vector&lt;GLchar&gt; nameData(256); for(int unif = 0; unif &lt; numActiveUniforms; ++unif) { GLint arraySize = 0; GLenum type = 0; GLsizei actualLength = 0; glGetActiveUniform(prog, unif, nameData.size(), &amp;actualLength, &amp;arraySize, &amp;type, &amp;nameData[0]); std::string name((char*)&amp;nameData[0], actualLength - 1); } </code></pre> <p>Also, for uniforms, there's <code>glGetActiveUniforms</code>, which can query all of the name lengths for every uniform all at once (as well as all of the types, array sizes, strides, and other parameters).</p> <h3>New Way</h3> <p>This way lets you access pretty much <em>everything</em> about active variables in a successfully linked program (except for regular globals). The <a href="http://www.opengl.org/registry/specs/ARB/program_interface_query.txt" rel="nofollow noreferrer">ARB_program_interface_query</a> extension is not widely available yet, but it'll get there.</p> <p>It starts with a call to <a href="http://www.opengl.org/wiki/GLAPI/glGetProgramInterface" rel="nofollow noreferrer"><code>glGetProgramInterfaceiv</code></a>, to query the number of active attributes/uniforms. Or whatever else you may want.</p> <pre><code>GLint numActiveAttribs = 0; GLint numActiveUniforms = 0; glGetProgramInterfaceiv(prog, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &amp;numActiveAttribs); glGetProgramInterfaceiv(prog, GL_UNIFORM, GL_ACTIVE_RESOURCES, &amp;numActiveUniforms); </code></pre> <p>Attributes are just vertex shader inputs; <code>GL_PROGRAM_INPUT</code> means the inputs to the first program in the program object.</p> <p>You can then loop over the number of active resources, asking for info on each one in turn, from <a href="http://www.opengl.org/wiki/GLAPI/glGetProgramResource" rel="nofollow noreferrer"><code>glGetProgramResourceiv</code></a> and <a href="http://www.opengl.org/wiki/GLAPI/glGetProgramResourceName" rel="nofollow noreferrer"><code>glGetProgramResourceName</code></a>:</p> <pre><code>std::vector&lt;GLchar&gt; nameData(256); std::vector&lt;GLenum&gt; properties; properties.push_back(GL_NAME_LENGTH​); properties.push_back(GL_TYPE​); properties.push_back(GL_ARRAY_SIZE​); std::vector&lt;GLint&gt; values(properties.size()); for(int attrib = 0; attrib &lt; numActiveAttribs; ++attrib) { glGetProgramResourceiv(prog, GL_PROGRAM_INPUT, attrib, properties.size(), &amp;properties[0], values.size(), NULL, &amp;values[0]); nameData.resize(values[0]); //The length of the name. glGetProgramResourceName(prog, GL_PROGRAM_INPUT, attrib, nameData.size(), NULL, &amp;nameData[0]); std::string name((char*)&amp;nameData[0], nameData.size() - 1); } </code></pre> <p>The exact same code would work for <code>GL_UNIFORM</code>; just swap <code>numActiveAttribs</code> with <code>numActiveUniforms</code>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload