GLGETACTIVEUNIFORM(3G)

πŸ’… GLGETACTIVEUNIFORM(3G) πŸ’…

okay so bestie, welcome to glGetActiveUniform β€” it's giving "tell me everything about this one uniform variable in this one program object," and honestly? iconic. it's a section 3G manual page, so settle in.


✨ NAME ✨

glGetActiveUniform β€” returns the deets about one (1) active uniform variable inside the program object you point at. that's it, that's the whole vibe πŸŽ€


🌸 C SPECIFICATION 🌸

void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufSize,
                        GLsizei *length, GLint *size, GLenum *type,
                        GLchar *name);

like, copy it exactly, no cap β€” every type and pointer matters here 🫢


πŸ¦‹ PARAMETERS πŸ¦‹

  • program β€” the program object you're interrogating. this is who you're asking about πŸ’–
  • index β€” which uniform variable you want the tea on. it's the index, bestie, not the name πŸ‘‘
  • bufSize β€” the absolute max number of characters OpenGL is allowed to write into the character buffer you handed over in name. think of it as a hard limit, fr fr 🚧
  • length β€” if you pass something that isn't NULL, this gets filled with the number of characters OpenGL actually wrote into the string at name β€” and that count does not include the null terminator 🀏
  • size β€” returns the size of the uniform variable. like, how big it is πŸ’«
  • type β€” returns the data type of the uniform variable 🌈
  • name β€” returns a null terminated string holding the name of the uniform variable. the actual name, in text, for you 🎁

πŸ’œ DESCRIPTION πŸ’œ

so glGetActiveUniform returns info about an active uniform variable in the program object specified by program. periodt.

wanna know how many active uniform variables there even are? call glGetProgram() with the value GL_ACTIVE_UNIFORMS β€” that's the count, bestie πŸ”’. and a value of 0 for index selects the very first active uniform variable, like the main character of the list πŸ‘‘. permissible values for index range from zero all the way up to the number of active uniform variables minus one. so zero-indexed, as everything in your life should be.

now, the shader lore ✨: shaders may use either built-in uniform variables, user-defined uniform variables, or both. slay, versatile.

  • built-in uniform variables have a prefix of "gl_" and they reference existing OpenGL state or values derived from such state β€” e.g. gl_DepthRangeParameters. (see the OpenGL Shading Language specification for a complete list, because this page is not about to list them all πŸ’€)
  • user-defined uniform variables have arbitrary names and they obtain their values from the application through calls to glUniform(). that's you, you're the application, you're doing that 🌟

a uniform variable β€” built-in or user-defined, doesn't matter β€” is considered active if it's determined during the link operation that it may be accessed during program execution. so basically the linker did a vibe check and went "yeah, this one might get used" βœ…. and because of that, program should have previously been the target of a call to glLinkProgram() β€” but plot twist: it is not necessary for it to have been linked successfully πŸ™ˆ

now, buffer sizing, because this is the part that bites people 😭. the size of the character buffer you need to store the longest uniform variable name in program can be obtained by calling glGetProgram() with the value GL_ACTIVE_UNIFORM_MAX_LENGTH. this value should be used to allocate a buffer of sufficient size to store the returned uniform variable name. that size β€” of this character buffer β€” is what you pass in bufSize, and a pointer to this character buffer is what you pass in name. match made in heaven 🫢

then glGetActiveUniform returns the name of the uniform variable indicated by index, storing it in the character buffer specified by name. the string returned will be null terminated, as strings should be πŸŽ€. the actual number of characters written into this buffer comes back in length, and β€” say it with me β€” this count does not include the null termination character. and if you don't care about the length of the returned string at all? just pass a value of NULL in the length argument and move on with your life πŸ’…

ngl bestie, bufSize is a real one β€” OpenGL will not write past what you tell it, so give it room. the longest-name size from GL_ACTIVE_UNIFORM_MAX_LENGTH is literally right there for you πŸ“

So like, type is gonna write a pointer to the uniform variable's data type into wherever you pointed it πŸ’… β€” and bestie, the symbolic constants it hands back for each uniform type? Literally a whole glow-up list, here's the full rundown, no skips:

  • GL_FLOAT β€” float
  • GL_FLOAT_VEC2 β€” vec2
  • GL_FLOAT_VEC3 β€” vec3
  • GL_FLOAT_VEC4 β€” vec4
  • GL_DOUBLE β€” double
  • GL_DOUBLE_VEC2 β€” dvec2
  • GL_DOUBLE_VEC3 β€” dvec3
  • GL_DOUBLE_VEC4 β€” dvec4
  • GL_INT β€” int
  • GL_INT_VEC2 β€” ivec2
  • GL_INT_VEC3 β€” ivec3
  • GL_INT_VEC4 β€” ivec4
  • GL_UNSIGNED_INT β€” unsigned int
  • GL_UNSIGNED_INT_VEC2 β€” uvec2
  • GL_UNSIGNED_INT_VEC3 β€” uvec3
  • GL_UNSIGNED_INT_VEC4 β€” uvec4
  • GL_BOOL β€” bool
  • GL_BOOL_VEC2 β€” bvec2
  • GL_BOOL_VEC3 β€” bvec3
  • GL_BOOL_VEC4 β€” bvec4
  • GL_FLOAT_MAT2 β€” mat2
  • GL_FLOAT_MAT3 β€” mat3
  • GL_FLOAT_MAT4 β€” mat4
  • GL_FLOAT_MAT2x3 β€” mat2x3
  • GL_FLOAT_MAT2x4 β€” mat2x4
  • GL_FLOAT_MAT3x2 β€” mat3x2
  • GL_FLOAT_MAT3x4 β€” mat3x4
  • GL_FLOAT_MAT4x2 β€” mat4x2
  • GL_FLOAT_MAT4x3 β€” mat4x3
  • GL_DOUBLE_MAT2 β€” dmat2
  • GL_DOUBLE_MAT3 β€” dmat3
  • GL_DOUBLE_MAT4 β€” dmat4
  • GL_DOUBLE_MAT2x3 β€” dmat2x3
  • GL_DOUBLE_MAT2x4 β€” dmat2x4
  • GL_DOUBLE_MAT3x2 β€” dmat3x2
  • GL_DOUBLE_MAT3x4 β€” dmat3x4
  • GL_DOUBLE_MAT4x2 β€” dmat4x2

okay so we're still deep in the type table, bestie β€” like, the table, the one that maps what GL tells you (params) to what it actually means in shader-speak. Picking up right where we left off, no skipping, every single row, let's go πŸƒβ€β™€οΈπŸ’¨

  • GL_DOUBLE_MAT4x3 β†’ dmat4x3
  • GL_SAMPLER_1D β†’ sampler1D
  • GL_SAMPLER_2D β†’ sampler2D
  • GL_SAMPLER_3D β†’ sampler3D
  • GL_SAMPLER_CUBE β†’ samplerCube
  • GL_SAMPLER_1D_SHADOW β†’ sampler1DShadow
  • GL_SAMPLER_2D_SHADOW β†’ sampler2DShadow
  • GL_SAMPLER_1D_ARRAY β†’ sampler1DArray
  • GL_SAMPLER_2D_ARRAY β†’ sampler2DArray
  • GL_SAMPLER_1D_ARRAY_SHADOW β†’ sampler1DArrayShadow
  • GL_SAMPLER_2D_ARRAY_SHADOW β†’ sampler2DArrayShadow
  • GL_SAMPLER_2D_MULTISAMPLE β†’ sampler2DMS
  • GL_SAMPLER_2D_MULTISAMPLE_ARRAY β†’ sampler2DMSArray
  • GL_SAMPLER_CUBE_SHADOW β†’ samplerCubeShadow
  • GL_SAMPLER_BUFFER β†’ samplerBuffer
  • GL_SAMPLER_2D_RECT β†’ sampler2DRect
  • GL_SAMPLER_2D_RECT_SHADOW β†’ sampler2DRectShadow
  • GL_INT_SAMPLER_1D β†’ isampler1D
  • GL_INT_SAMPLER_2D β†’ isampler2D
  • GL_INT_SAMPLER_3D β†’ isampler3D
  • GL_INT_SAMPLER_CUBE β†’ isamplerCube
  • GL_INT_SAMPLER_1D_ARRAY β†’ isampler1DArray
  • GL_INT_SAMPLER_2D_ARRAY β†’ isampler2DArray
  • GL_INT_SAMPLER_2D_MULTISAMPLE β†’ isampler2DMS
  • GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY β†’ isampler2DMSArray
  • GL_INT_SAMPLER_BUFFER β†’ isamplerBuffer
  • GL_INT_SAMPLER_2D_RECT β†’ isampler2DRect
  • GL_UNSIGNED_INT_SAMPLER_1D β†’ usampler1D
  • GL_UNSIGNED_INT_SAMPLER_2D β†’ usampler2D
  • GL_UNSIGNED_INT_SAMPLER_3D β†’ usampler3D
  • GL_UNSIGNED_INT_SAMPLER_CUBE β†’ usamplerCube
  • GL_UNSIGNED_INT_SAMPLER_1D_ARRAY β†’ usampler2DArray
  • GL_UNSIGNED_INT_SAMPLER_2D_ARRAY β†’ usampler2DArray
  • GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE β†’ usampler2DMS
  • GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY β†’ usampler2DMSArray
  • GL_UNSIGNED_INT_SAMPLER_BUFFER β†’ usamplerBuffer
  • GL_UNSIGNED_INT_SAMPLER_2D_RECT β†’ usampler2DRect
  • GL_IMAGE_1D β†’ image1D
  • GL_IMAGE_2D β†’ image2D
🫢 real talk: yes, usampler2DArray shows up twice up there, and no, that's not me being sloppy β€” that's literally how it's written in the spec, so I'm keeping it character-for-character. Copy it exactly as-is and move on, bestie. no cap πŸ’…

and we're still going, the image squad is just getting started β€” hold that thought ✨

  • GL_IMAGE_3D β†’ image3D
  • GL_IMAGE_2D_RECT β†’ image2DRect
  • GL_IMAGE_CUBE β†’ imageCube
  • GL_IMAGE_BUFFER β†’ imageBuffer
  • GL_IMAGE_1D_ARRAY β†’ image1DArray
  • GL_IMAGE_2D_ARRAY β†’ image2DArray
  • GL_IMAGE_2D_MULTISAMPLE β†’ image2DMS
  • GL_IMAGE_2D_MULTISAMPLE_ARRAY β†’ image2DMSArray
  • GL_INT_IMAGE_1D β†’ iimage1D
  • GL_INT_IMAGE_2D β†’ iimage2D
  • GL_INT_IMAGE_3D β†’ iimage3D
  • GL_INT_IMAGE_2D_RECT β†’ iimage2DRect
  • GL_INT_IMAGE_CUBE β†’ iimageCube
  • GL_INT_IMAGE_BUFFER β†’ iimageBuffer
  • GL_INT_IMAGE_1D_ARRAY β†’ iimage1DArray
  • GL_INT_IMAGE_2D_ARRAY β†’ iimage2DArray
  • GL_INT_IMAGE_2D_MULTISAMPLE β†’ iimage2DMS
  • GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY β†’ iimage2DMSArray
  • GL_UNSIGNED_INT_IMAGE_1D β†’ uimage1D
  • GL_UNSIGNED_INT_IMAGE_2D β†’ uimage2D
  • GL_UNSIGNED_INT_IMAGE_3D β†’ uimage3D
  • GL_UNSIGNED_INT_IMAGE_2D_RECT β†’ uimage2DRect
  • GL_UNSIGNED_INT_IMAGE_CUBE β†’ uimageCube
  • GL_UNSIGNED_INT_IMAGE_BUFFER β†’ uimageBuffer
  • GL_UNSIGNED_INT_IMAGE_1D_ARRAY β†’ uimage1DArray
  • GL_UNSIGNED_INT_IMAGE_2D_ARRAY β†’ uimage2DArray
  • GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE β†’ uimage2DMS
  • GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY β†’ uimage2DMSArray
  • GL_UNSIGNED_INT_ATOMIC_COUNTER β†’ atomic_uint

okay bestie, arrays time 🌸 and this is the part where people get confused, so like, breathe.

If one or more elements of an array are active, the name of the array is returned in name, the type is returned in type, and the size parameter returns the highest array element index used, plus one, as determined by the compiler and/or linker. Not the count of active elements β€” the highest index used, plus one. That distinction is doing a lot of work, ngl πŸ’… And only one active uniform variable will be reported for a uniform array. One array = one report. Periodt.

πŸŽ€ Lowkey important: size is not "how many elements are active". It's the top index + 1. Don't get it twisted.

Now, the structures thing, and honestly this is the icon of "wait what" 😭

Uniform variables that are declared as structures or arrays of structures will not be returned directly by this function. Nope. Instead, each of these uniform variables will be reduced to its fundamental components containing the "." and "[]" operators such that each of the names is valid as an argument to glGetUniformLocation(). Each of these reduced uniform variables is counted as one active uniform variable and is assigned an index. So like, the compiler is out here decomposing your struct into a bunch of dotted names, and every one of those gets its own lil index 🫢

And check this caveat, it's giving rules: a valid name cannot be a structure, an array of structures, or a subcomponent of a vector or matrix. So don't come asking for mystruct and expect a happy answer β€” ask for the leaf nodes, bestie πŸ“


The size of the uniform variable will be returned in size ✨

  • Uniform variables other than arrays will have a size of 1.
  • Structures and arrays of structures will be reduced as described earlier, such that each of the names returned will be a data type in the earlier list.
  • If this reduction results in an array, the size returned will be as described for uniform arrays; otherwise, the size returned will be 1.

so: non-array = 1. Reduction that lands on an array = array rules. Reduction that doesn't = 1. easy 🧚


The list of active uniform variables may include both built-in uniform variables (which begin with the prefix "gl_") as well as user-defined uniform variable names. So yeah, the gl_ squad is in the list too β€” don't be surprised, iykyk πŸ‘‘


This function will return as much information as it can about the specified active uniform variable πŸ’–

But if no information is available, length will be 0, and name will be an empty string. When could that happen? This situation could occur if this function is called after a link operation that failed πŸ’€ yep. Failed link β†’ shrug.

😭 And the big one, keep this in your notes: if an error occurs, the return values length, size, type, and name will be unmodified. Not zeroed, not cleared β€” untouched. So check those errors, bestie, fr fr.

✨ NOTES ✨

okay so before you go indexing anything, there's a whole vibe check about which types even exist on your driver πŸ‘€

The double types β€” GL_DOUBLE, GL_DOUBLE_VEC2, GL_DOUBLE_VEC3, GL_DOUBLE_VEC4, GL_DOUBLE_MAT2, GL_DOUBLE_MAT3, GL_DOUBLE_MAT4, GL_DOUBLE_MAT2x3, GL_DOUBLE_MAT2x4, GL_DOUBLE_MAT3x2, GL_DOUBLE_MAT3x4, GL_DOUBLE_MAT4x2, and GL_DOUBLE_MAT4x3 β€” are only available if the GL version is 4.1 or higher. not before. don't even try πŸ’…

And the image types, bestie, are a whole list: GL_IMAGE_1D, GL_IMAGE_2D, GL_IMAGE_3D, GL_IMAGE_2D_RECT, GL_IMAGE_CUBE, GL_IMAGE_BUFFER, GL_IMAGE_1D_ARRAY, GL_IMAGE_2D_ARRAY, GL_IMAGE_2D_MULTISAMPLE, GL_IMAGE_2D_MULTISAMPLE_ARRAY, GL_INT_IMAGE_1D, GL_INT_IMAGE_2D, GL_INT_IMAGE_3D, GL_INT_IMAGE_2D_RECT, GL_INT_IMAGE_CUBE, GL_INT_IMAGE_BUFFER, GL_INT_IMAGE_1D_ARRAY, GL_INT_IMAGE_2D_ARRAY, GL_INT_IMAGE_2D_MULTISAMPLE, GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, GL_UNSIGNED_INT_IMAGE_1D, GL_UNSIGNED_INT_IMAGE_2D, GL_UNSIGNED_INT_IMAGE_3D, GL_UNSIGNED_INT_IMAGE_2D_RECT, GL_UNSIGNED_INT_IMAGE_CUBE, GL_UNSIGNED_INT_IMAGE_BUFFER, GL_UNSIGNED_INT_IMAGE_1D_ARRAY, GL_UNSIGNED_INT_IMAGE_2D_ARRAY, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY β€” plus the atomic counter type GL_UNSIGNED_INT_ATOMIC_COUNTER β€” are only available if the GL version is 4.2 or higher. yes, all of them. every single one. i counted 🫢


πŸ’€ ERRORS πŸ’€

so here's where it can go wrong. and it will, if you're not paying attention 😭

  • GL_INVALID_VALUE β€” gets generated if program is not a value generated by OpenGL. like, where did you even get that number babe
  • GL_INVALID_OPERATION β€” gets generated if program is not a program object. close but no cigar
  • GL_INVALID_VALUE β€” gets generated if index is greater than or equal to the number of active uniform variables in program. you asked for uniform #9000 and there are like three of them
  • GL_INVALID_VALUE β€” gets generated if bufSize is less than 0. negative buffer size. genuinely what are you doing πŸ™ˆ
fr fr, check your values before you call this, it's giving "debugging at 3am" energy otherwise

πŸ¦‹ ASSOCIATED GETS πŸ¦‹

the little functions that hang out with this one, iykyk:

  • glGet() with argument GL_MAX_VERTEX_UNIFORM_COMPONENTS, GL_MAX_GEOMETRY_UNIFORM_COMPONENTS, GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS, GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS.
  • glGetProgram() with argument GL_ACTIVE_UNIFORMS or GL_ACTIVE_UNIFORM_MAX_LENGTH.
  • glIsProgram()

those last two are literally your besties for this function, no cap πŸ’–


🌈 VERSION SUPPORT 🌈

bestie the original had a whole table with cute little boxes and checkmarks, so let me just tell you the tea:

glGetActiveUniform is supported everywhere. like, every single version:

  • 2.0 β€” βœ”
  • 2.1 β€” βœ”
  • 3.0 β€” βœ”
  • 3.1 β€” βœ”
  • 3.2 β€” βœ”
  • 3.3 β€” βœ”
  • 4.0 β€” βœ”
  • 4.1 β€” βœ”
  • 4.2 β€” βœ”
  • 4.3 β€” βœ”
  • 4.4 β€” βœ”
  • 4.5 β€” βœ”

twelve for twelve. ate and left no crumbs πŸ‘‘


πŸ”₯ SEE ALSO πŸ”₯

go read these next, they're all connected:

  • glGetUniform()
  • glGetUniformLocation()
  • glLinkProgram()
  • glUniform()
  • glUseProgram()

Copyright Β© 2003-2005 3Dlabs Inc. Ltd. Copyright Β© 2010-2014 Khronos Group This material may be distributed subject to the terms and conditions set forth in the Open Publication License, v 1.0, 8 June 1999. http://opencontent.org/openpub/.


Copyright Β© 2003-2005 3Dlabs Inc. Ltd. Copyright Β© 2010-2014 Khronos Group


and that's the whole page, bestie 🫢 it's from [FIXME: source], dated 08/09/2021, and it lives at GLGETACTIVEUNIFORM(3G) β€” go forth and query those uniforms, you absolute icon πŸ’…βœ¨

πŸ“¦ where this page comes from