# Managing Shader Variables # The `legacygl` object is tightly coupled with its shader program, and takes care of the process of sending the shader variables (uniform/attribute) data to the GPU. ## Example Vertex Shader Code ## ``` // the only mandatory vertex attribute attribute vec3 a_vertex; // all other uniform/attribute vars are at your will uniform int u_myint; uniform float u_myfloat; uniform vec2i u_myvec2i; uniform mat4 u_mymat4; attribute float a_anotherfloat; attribute vec3 a_anothervec3; void main(void) { gl_Position = vec4(a_vertex, 1.0); } ``` ## Uniform Variables ## Each uniform variable used in the shader needs to be registered to `legacygl` by calling ``` legacygl.add_uniform(name, type); ``` `name` is the same as the one used in the GLSL code without the prefix `u_`, and `type` must be one of the following: `"1f"`, `"2f"`, `"3f"`, `"4f"`, `"1i"`, `"2i"`, `"3i"`, `"4i"`, `"Matrix2f"`, `"Matrix3f"`, and `"Matrix4f"`. For the above example code, the registration process would be: ``` legacygl.add_uniform("myint", "1i"); legacygl.add_uniform("myfloat", "1f"); legacygl.add_uniform("myvec2i", "2i"); legacygl.add_uniform("mymat4", "Matrix4f"); ``` This automatically creates an entry for each variable, e.g., `legacygl.uniforms.myint`, and you can access the actual data on the CPU via `legacygl.uniforms.myint.value` which is just a number for scalars or a [glMatrix](http://glmatrix.net) object for vectors and matrices. The transfer of these uniform variables data to GPU occurs when ``` legacygl.set_uniforms(); ``` is called, but this is implicitly called inside `legacygl.begin()` and `legacygl.callList()`, so you don't need to call it yourself. `legacygl` also provides a simple push/pop mechanism (much like `glPushMatrix/glPopMatrix`) for each variable: ``` legacygl.uniforms.myint.push(); legacygl.uniforms.myint.value = 3; drawfunc(); legacygl.uniforms.myint.pop(); drawfunc(); ``` ## Vertex Attribute Variables ## Each vertex attribute variable is registered to `legacygl` by calling ``` legacygl.add_vertex_attribute(name, size); ``` where `name` is the same as the one in the shader code without the prefix `a_`, and `size` is the number of numbers per vertex (e.g., 9 for `mat3`). For the above example code, the registration process would be: ``` legacygl.add_vertex_attribute("anotherfloat", 1); legacygl.add_vertex_attribute("anothervec3", 3); ``` This automatically creates a function for each variable that changes its “current value”. For example, you can do something like: ``` legacygl.anotherfloat(0.2); legacygl.begin(gl.TRIANGLES); legacygl.anothervec3(1, -2, 3); legacygl.vertex(0, 0, 0); legacygl.anothervec3(2, 3, 0); legacygl.vertex(1, 0, 0); legacygl.anotherfloat(-0.5); legacygl.vertex(0, 0, 1); legacygl.end(); ``` Note that the `vertex` attribute is mandatory and is treated differently; there's no “current value” for it, and every time `legacygl.vertex(x, y, z)` is called, the vertex position along with its all other attribute data are appended to the arrays stored inside `legacygl` (which are then passed to the GPU when `legacygl.end()` is called).