{"id":457,"date":"2017-07-19T12:03:10","date_gmt":"2017-07-19T12:03:10","guid":{"rendered":"http:\/\/imalogic.com\/blog\/?p=457"},"modified":"2017-07-19T12:03:10","modified_gmt":"2017-07-19T12:03:10","slug":"glsl-variable-qualifiers","status":"publish","type":"post","link":"https:\/\/imalogic.com\/blog\/2017\/07\/19\/glsl-variable-qualifiers\/","title":{"rendered":"GLSL &#8211; Variable Qualifiers"},"content":{"rendered":"<body><p><\/p><strong>Variable Qualifiers<\/strong>\n<p>Qualifiers give a special meaning to the variable. The following qualifiers are available:<\/p>\n<ul>\n<li>const \u2013 The declaration is of a compile time constant.<\/li>\n<li>attribute \u2013 Global variables that may change per vertex, that are passed from the OpenGL application to vertex shaders. This qualifier can only be used in vertex shaders. For the shader this is a read-only variable. See Attribute section.<\/li>\n<li>uniform \u2013 Global variables that may change per primitive [\u2026], that are passed from the OpenGL application to the shaders. This qualifier can be used in both vertex and fragment shaders. For the shaders this is a read-only variable. See Uniform section.<\/li>\n<li>varying \u2013 used for interpolated data between a vertex shader and a fragment shader. Available for writing in the vertex shader, and read-only in a fragment shader. See Varying section.<\/li>\n<\/ul>\n<ul>\n<li><code>uniform<\/code> are <strong>per-primitive<\/strong> parameters (constant during an entire draw call) ;<\/li>\n<li><code>attribute<\/code> are <strong>per-vertex<\/strong> parameters (typically : positions, normals, colors, UVs, \u2026) ;<\/li>\n<li><code>varying<\/code> are <strong>per-fragment<\/strong> (or <strong>per-pixel<\/strong>) parameters : they <strong>vary<\/strong> from pixels to pixels.<\/li>\n<\/ul>\n<p>Understanding the mecanism of <code>varying<\/code> is necessary to shader programming.<br>\nImagine you define a varying parameter <code>v<\/code> for each vertex of a triangle inside the <em>vertex shader<\/em>. When the varying parameter arrives in the <em>fragment shader<\/em>, it would be interpolated through <em>bilinear interpolation<\/em> based on the pixel to draw.<\/p>\n<p>In the following image, the red pixel received an interpolated value of the varying parameter <code>v<\/code>. That\u2019s why we call them \u201cvarying\u201d.<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/M0Yqe.png?ssl=1\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"459\" data-permalink=\"https:\/\/imalogic.com\/blog\/2017\/07\/19\/glsl-variable-qualifiers\/m0yqe\/\" data-orig-file=\"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/M0Yqe.png?fit=500%2C345&amp;ssl=1\" data-orig-size=\"500,345\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"M0Yqe\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/M0Yqe.png?fit=500%2C345&amp;ssl=1\" class=\"wp-image-459 size-full aligncenter\" src=\"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/M0Yqe.png?resize=500%2C345&#038;ssl=1\" alt=\"\" width=\"500\" height=\"345\" loading=\"lazy\" srcset=\"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/M0Yqe.png?w=500&amp;ssl=1 500w, https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/M0Yqe.png?resize=300%2C207&amp;ssl=1 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/p>\n<p>\u00a0<\/p>\n<h2><em>Variables shared between both examples:<\/em><\/h2>\n<pre class=\"lang-c prettyprint prettyprinted\"><code><span class=\"typ\">GLint<\/span><span class=\"pln\"> i<\/span><span class=\"pun\">;<\/span>\r\n<span class=\"typ\">GLint<\/span><span class=\"pln\"> count<\/span><span class=\"pun\">;<\/span>\r\n\r\n<span class=\"typ\">GLint<\/span><span class=\"pln\"> size<\/span><span class=\"pun\">;<\/span> <span class=\"com\">\/\/ size of the variable<\/span>\r\n<span class=\"typ\">GLenum<\/span><span class=\"pln\"> type<\/span><span class=\"pun\">;<\/span> <span class=\"com\">\/\/ type of the variable (float, vec3 or mat4, etc)<\/span>\r\n\r\n<span class=\"kwd\">const<\/span> <span class=\"typ\">GLsizei<\/span><span class=\"pln\"> bufSize <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">16<\/span><span class=\"pun\">;<\/span> <span class=\"com\">\/\/ maximum name length<\/span>\r\n<span class=\"typ\">GLchar<\/span><span class=\"pln\"> name<\/span><span class=\"pun\">[<\/span><span class=\"pln\">bufSize<\/span><span class=\"pun\">];<\/span> <span class=\"com\">\/\/ variable name in GLSL<\/span>\r\n<span class=\"typ\">GLsizei<\/span><span class=\"pln\"> length<\/span><span class=\"pun\">;<\/span> <span class=\"com\">\/\/ name length<\/span><\/code><\/pre>\n<h2>Attributes<\/h2>\n<pre class=\"lang-c prettyprint prettyprinted\"><code><span class=\"pln\">glGetProgramiv<\/span><span class=\"pun\">(<\/span><span class=\"pln\">program<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> GL_ACTIVE_ATTRIBUTES<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">count<\/span><span class=\"pun\">);<\/span><span class=\"pln\">\r\nprintf<\/span><span class=\"pun\">(<\/span><span class=\"str\">\"Active Attributes: %d\\n\"<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> count<\/span><span class=\"pun\">);<\/span>\r\n\r\n<span class=\"kwd\">for<\/span> <span class=\"pun\">(<\/span><span class=\"pln\">i <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">;<\/span><span class=\"pln\"> i <\/span><span class=\"pun\">&lt;<\/span><span class=\"pln\"> count<\/span><span class=\"pun\">;<\/span><span class=\"pln\"> i<\/span><span class=\"pun\">++)<\/span>\r\n<span class=\"pun\">{<\/span><span class=\"pln\">\r\n    glGetActiveAttrib<\/span><span class=\"pun\">(<\/span><span class=\"pln\">program<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">(<\/span><span class=\"typ\">GLuint<\/span><span class=\"pun\">)<\/span><span class=\"pln\">i<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> bufSize<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">length<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">size<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">type<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> name<\/span><span class=\"pun\">);<\/span><span class=\"pln\">\r\n\r\n    printf<\/span><span class=\"pun\">(<\/span><span class=\"str\">\"Attribute #%d Type: %u Name: %s\\n\"<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> i<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> type<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> name<\/span><span class=\"pun\">);<\/span>\r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n<h2>Uniforms<\/h2>\n<pre class=\"lang-c prettyprint prettyprinted\"><code><span class=\"pln\">glGetProgramiv<\/span><span class=\"pun\">(<\/span><span class=\"pln\">program<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> GL_ACTIVE_UNIFORMS<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">count<\/span><span class=\"pun\">);<\/span><span class=\"pln\">\r\nprintf<\/span><span class=\"pun\">(<\/span><span class=\"str\">\"Active Uniforms: %d\\n\"<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> count<\/span><span class=\"pun\">);<\/span>\r\n\r\n<span class=\"kwd\">for<\/span> <span class=\"pun\">(<\/span><span class=\"pln\">i <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">;<\/span><span class=\"pln\"> i <\/span><span class=\"pun\">&lt;<\/span><span class=\"pln\"> count<\/span><span class=\"pun\">;<\/span><span class=\"pln\"> i<\/span><span class=\"pun\">++)<\/span>\r\n<span class=\"pun\">{<\/span><span class=\"pln\">\r\n    glGetActiveUniform<\/span><span class=\"pun\">(<\/span><span class=\"pln\">program<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">(<\/span><span class=\"typ\">GLuint<\/span><span class=\"pun\">)<\/span><span class=\"pln\">i<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> bufSize<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">length<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">size<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">type<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> name<\/span><span class=\"pun\">);<\/span><span class=\"pln\">\r\n\r\n    printf<\/span><span class=\"pun\">(<\/span><span class=\"str\">\"Uniform #%d Type: %u Name: %s\\n\"<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> i<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> type<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> name<\/span><span class=\"pun\">);<\/span>\r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n<h3>OpenGL Documentation \/ Variable Types<\/h3>\n<p>The various macros representing variable types can be found in the docs. Such as <code>GL_FLOAT<\/code>, <code>GL_FLOAT_VEC3<\/code>, <code>GL_FLOAT_MAT4<\/code>, etc.<\/p>\n<ul>\n<li><a href=\"https:\/\/www.opengl.org\/sdk\/docs\/man\/html\/glGetActiveAttrib.xhtml\">glGetActiveAttrib<\/a><\/li>\n<li><a href=\"https:\/\/www.opengl.org\/sdk\/docs\/man\/html\/glGetActiveUniform.xhtml\">glGetActiveUniform<\/a><\/li>\n<\/ul>\n<p>\u00a0<\/p>\n<h1>New way<\/h1>\n<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\">ARB_program_interface_query<\/a> extension is not widely available yet, but it\u2019ll get there.<\/p>\n<p>It starts with a call to <a href=\"http:\/\/www.opengl.org\/wiki\/GLAPI\/glGetProgramInterface\" rel=\"nofollow\"><code>glGetProgramInterfaceiv<\/code><\/a>, to query the number of active attributes\/uniforms. Or whatever else you may want.<\/p>\n<pre class=\"lang-c prettyprint prettyprinted\"><code><span class=\"typ\">GLint<\/span><span class=\"pln\"> numActiveAttribs <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">;<\/span>\r\n<span class=\"typ\">GLint<\/span><span class=\"pln\"> numActiveUniforms <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">;<\/span><span class=\"pln\">\r\nglGetProgramInterfaceiv<\/span><span class=\"pun\">(<\/span><span class=\"pln\">prog<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> GL_PROGRAM_INPUT<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> GL_ACTIVE_RESOURCES<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">numActiveAttribs<\/span><span class=\"pun\">);<\/span><span class=\"pln\">\r\nglGetProgramInterfaceiv<\/span><span class=\"pun\">(<\/span><span class=\"pln\">prog<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> GL_UNIFORM<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> GL_ACTIVE_RESOURCES<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">numActiveUniforms<\/span><span class=\"pun\">);\r\n<\/span><\/code><\/pre>\n<p>Attributes are just vertex shader inputs; <code>GL_PROGRAM_INPUT<\/code> means the inputs to the first program in the program object.<\/p>\n<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\"><code>glGetProgramResourceiv<\/code><\/a> and <a href=\"http:\/\/www.opengl.org\/wiki\/GLAPI\/glGetProgramResourceName\" rel=\"nofollow\"><code>glGetProgramResourceName<\/code><\/a>:<\/p>\n<pre class=\"lang-c prettyprint prettyprinted\"><code><span class=\"pln\">std<\/span><span class=\"pun\">::<\/span><span class=\"typ\">vector<\/span><span class=\"pun\">&lt;<\/span><span class=\"typ\">GLchar<\/span><span class=\"pun\">&gt;<\/span><span class=\"pln\"> nameData<\/span><span class=\"pun\">(<\/span><span class=\"lit\">256<\/span><span class=\"pun\">);<\/span><span class=\"pln\">\r\nstd<\/span><span class=\"pun\">::<\/span><span class=\"typ\">vector<\/span><span class=\"pun\">&lt;<\/span><span class=\"typ\">GLenum<\/span><span class=\"pun\">&gt;<\/span><span class=\"pln\"> properties<\/span><span class=\"pun\">;<\/span><span class=\"pln\">\r\nproperties<\/span><span class=\"pun\">.<\/span><span class=\"pln\">push_back<\/span><span class=\"pun\">(<\/span><span class=\"pln\">GL_NAME_LENGTH<\/span><span class=\"pun\">\u200b);<\/span><span class=\"pln\">\r\nproperties<\/span><span class=\"pun\">.<\/span><span class=\"pln\">push_back<\/span><span class=\"pun\">(<\/span><span class=\"pln\">GL_TYPE<\/span><span class=\"pun\">\u200b);<\/span><span class=\"pln\">\r\nproperties<\/span><span class=\"pun\">.<\/span><span class=\"pln\">push_back<\/span><span class=\"pun\">(<\/span><span class=\"pln\">GL_ARRAY_SIZE<\/span><span class=\"pun\">\u200b);<\/span><span class=\"pln\">\r\nstd<\/span><span class=\"pun\">::<\/span><span class=\"typ\">vector<\/span><span class=\"pun\">&lt;<\/span><span class=\"typ\">GLint<\/span><span class=\"pun\">&gt;<\/span><span class=\"pln\"> values<\/span><span class=\"pun\">(<\/span><span class=\"pln\">properties<\/span><span class=\"pun\">.<\/span><span class=\"pln\">size<\/span><span class=\"pun\">());<\/span>\r\n<span class=\"kwd\">for<\/span><span class=\"pun\">(<\/span><span class=\"typ\">int<\/span><span class=\"pln\"> attrib <\/span><span class=\"pun\">=<\/span> <span class=\"lit\">0<\/span><span class=\"pun\">;<\/span><span class=\"pln\"> attrib <\/span><span class=\"pun\">&lt;<\/span><span class=\"pln\"> numActiveAttribs<\/span><span class=\"pun\">;<\/span> <span class=\"pun\">++<\/span><span class=\"pln\">attrib<\/span><span class=\"pun\">)<\/span>\r\n<span class=\"pun\">{<\/span><span class=\"pln\">\r\n  glGetProgramResourceiv<\/span><span class=\"pun\">(<\/span><span class=\"pln\">prog<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> GL_PROGRAM_INPUT<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> attrib<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> properties<\/span><span class=\"pun\">.<\/span><span class=\"pln\">size<\/span><span class=\"pun\">(),<\/span>\r\n    <span class=\"pun\">&amp;<\/span><span class=\"pln\">properties<\/span><span class=\"pun\">[<\/span><span class=\"lit\">0<\/span><span class=\"pun\">],<\/span><span class=\"pln\"> values<\/span><span class=\"pun\">.<\/span><span class=\"pln\">size<\/span><span class=\"pun\">(),<\/span><span class=\"pln\"> NULL<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">values<\/span><span class=\"pun\">[<\/span><span class=\"lit\">0<\/span><span class=\"pun\">]);<\/span><span class=\"pln\">\r\n\r\n  nameData<\/span><span class=\"pun\">.<\/span><span class=\"pln\">resize<\/span><span class=\"pun\">(<\/span><span class=\"pln\">values<\/span><span class=\"pun\">[<\/span><span class=\"lit\">0<\/span><span class=\"pun\">]);<\/span> <span class=\"com\">\/\/The length of the name.<\/span><span class=\"pln\">\r\n  glGetProgramResourceName<\/span><span class=\"pun\">(<\/span><span class=\"pln\">prog<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> GL_PROGRAM_INPUT<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> attrib<\/span><span class=\"pun\">,<\/span><span class=\"pln\"> nameData<\/span><span class=\"pun\">.<\/span><span class=\"pln\">size<\/span><span class=\"pun\">(),<\/span><span class=\"pln\"> NULL<\/span><span class=\"pun\">,<\/span> <span class=\"pun\">&amp;<\/span><span class=\"pln\">nameData<\/span><span class=\"pun\">[<\/span><span class=\"lit\">0<\/span><span class=\"pun\">]);<\/span><span class=\"pln\">\r\n  std<\/span><span class=\"pun\">::<\/span><span class=\"pln\">string name<\/span><span class=\"pun\">((<\/span><span class=\"kwd\">char<\/span><span class=\"pun\">*)&amp;<\/span><span class=\"pln\">nameData<\/span><span class=\"pun\">[<\/span><span class=\"lit\">0<\/span><span class=\"pun\">],<\/span><span class=\"pln\"> nameData<\/span><span class=\"pun\">.<\/span><span class=\"pln\">size<\/span><span class=\"pun\">()<\/span> <span class=\"pun\">-<\/span> <span class=\"lit\">1<\/span><span class=\"pun\">);<\/span>\r\n<span class=\"pun\">}<\/span><\/code><\/pre>\n<p>The exact same code would work for <code>GL_UNIFORM<\/code>; just swap <code>numActiveAttribs<\/code> with <code>numActiveUniforms<\/code>.<\/p>\n<p>\u00a0<\/p>\n<\/body>","protected":false},"excerpt":{"rendered":"<p>Variable Qualifiers Qualifiers give a special meaning to the variable. The following qualifiers are available: const \u2013 The declaration is<\/p>\n","protected":false},"author":1,"featured_media":481,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[7,66,2],"tags":[],"class_list":["post-457","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-coding","category-computer-graphics","category-demo"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/imalogic.com\/blog\/wp-content\/uploads\/2017\/05\/glsl.png?fit=225%2C225&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8J21V-7n","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts\/457","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/comments?post=457"}],"version-history":[{"count":1,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts\/457\/revisions"}],"predecessor-version":[{"id":462,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/posts\/457\/revisions\/462"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/media\/481"}],"wp:attachment":[{"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/media?parent=457"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/categories?post=457"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/imalogic.com\/blog\/wp-json\/wp\/v2\/tags?post=457"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}