gl.functionsThe following are presented in order of frequency of use in roughly 200 student’s submissions of 4 WebGL2 assignments.
gl.getUniformLocationuniform variable in one or both of those shaders.
Uniforms are generally data sent from the CPU to the GPU once and accessed by all the vertices and/or fragments in the scene. They are commonly used for matrices, textures, and some scene-wide constants like light locations.
Each uniform is given a specific location, a small integer usually between 0 and 15. The shader linker picks these locations per program, and may pick different locations each compilation.
gl.bindVertexArraygl.createVertexArray, a Vertex Array Object (VAO).
Two related effects.
First, the VAO will record all subsequent calls of
and a few related but uncommon functions.
Second, at the moment of binding, anything recorded by the previously-bound VAO (which may be a default VAO managed by WebGL2 if none was ever bound) will be disabled and anything previously recorded by this VAO will be re-enabled.
gl.vertexAttribPointer are manually specified, not generated by the compiler.
gl.useProgramgl.cleargl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT
gl.uniformMatrix4fvgl.getUniformLocation, which is a shader program-specific integerfalse (no other value permitted)Float32Array containing 16 numbersuniform mat4 in the GPU.
WebGL2 assumes arrays are given in column-major order; that is,
gl.uniformMatrix4fv(loc, false,
[ 1, 2, 3, 4
, 5, 6, 7, 8
, 9, 10, 11, 12
,13, 14, 15, 16
])will create the matrix which is not the order that most programmers expect.
gl.bindBuffergl.ARRAY_BUFFER (for attributes) or gl.ELEMENT_ARRAY_BUFFER (for indices)gl.createBuffer, an opaque pointer to an array in GPU memorygl.bindBuffer might accidentally work if the correct buffer was the last one bound, but then stop working if you later change setup code or the like. To avoid this problem, it is recommended that any JavaScript function that interacts with a buffer calls gl.bindBuffer before doing so.
gl.bufferDatagl.bindBuffer)Float32Array for attributes or Uint16Array for indicesgl.STATIC_DRAW for data that will be supplied just once or gl.DYNAMIC_DRAW for data that will be re-supplied every frameIn more flexible standards like Vulkan, step 4 is not guaranteed as an array might be referenced by multiple buffers, but that can’t happen in WebGL2. Because step 4 is guaranteed in WebGL2, it can be moved to happen earlier in this sequence, often re-using memory from the old array for the new one.
gl.bufferSubData may be faster as it does not rely on optimizations to avoid allocating more memory.
gl.drawElementsgl.TRIANGLESgl.bindBuffer and generally re-enabled via gl.bindVertexArraygl.UNSIGNED_SHORTgl.vertexAttribPointer, primitive connectivity set by the current gl.ELEMENT_ARRAY_BUFFER, and the shader program set by gl.useProgram.
The count is a count of indices, not primitives: if you have 10 triangles then the count needs to be 30, not 10.
The offset is in bytes, not indices or primitives: if you want to skip the first 10 triangles and have gl.UNSIGNED_SHORT indices then the offset is (2 bytes per index) × (3 indices per triangle) × (10 triangles) = 60.
gl.createBufferThe thing returned by this function does not have a precise parallel in the CPU-only code that you’d used in other classes. It serves primarily as a way of managing GPU memory.
Actions on buffers all requiring using gl.bindBuffer to link them to one of a fixed set of bind points. The buffer returned by gl.createBuffer is not used otherwise directly used in your code.
Arrays allocated in GPU memory by gl.bufferData are attached to the buffer currently bound to the bind point. If a different array is attached to the same buffer or when the buffer is garbage collected by JavaScript, the array is freed.
gl.createBuffer controls GPU memory management and should be called only as needed. If you want to change data, use gl.bufferData without re-calling gl.createBuffer; calling gl.createBuffer every frame is likely to cause a GPU memory leak.
gl.createBuffer does not bind its return value; you’ll generally want to follow it with gl.bindBuffer.
Buffers only store bytes. The data types represented by those bytes is handled by the combination of the data supply functions gl.bufferData/gl.bufferSubData and the data use functions gl.vertexAttribPointer/gl.drawElements. Mixing and matching types in those calls is very unlikely to work.
gl.attachShadergl.createProgramgl.createShader, after calling gl.shaderSource and gl.compileShader on itYou may attach the same shader to as many shader programs as you wish.
Exactly one vertex shader and one fragment shader must be attached to a shader program prior to linking.
Once attached to a shader program, the shader variable is no longer needed.
gl.createShadergl.VERTEX_SHADER or gl.FRAGMENT_SHADER
gl.shaderSource, gl.compileShader, and gl.attachShader.
gl.shaderSourcegl.createShadergl.compileShader. gl.shaderSource performs no error checking or any kind; all that is done by gl.compileShader.
#version 300 es. Without that, the shader defaults to WebGL1’s shader language which had various differences in syntax and semantics and might cause errors either at compile or run time.
gl.compileShadergl.createShader, after calling gl.shaderSource on it
gl.COMPILE_STATUS using gl.getShaderParameter after running this function; without that you can’t tell if the compilation succeeded or not.
gl.getShaderParametergl.createShadergl.getShaderParametergl.getShaderParameter, either true for success or false for any compiler error.
Always check the gl.COMPILE_STATUS after running gl.compileShader; without that you can’t tell if the compilation succeeded or not.
If the status is false, use gl.getShaderInfoLog to learn why the compilation failed.
gl.getShaderInfoLoggl.createShader
gl.getShaderInfoLog does not remove the need for gl.getShaderParameter: the info log might be non-empty even if the compilation succeeds.
gl.uniform1fgl.getUniformLocation, which is a shader program-specific integeruniform float in the GPU.
gl.uniform1f to set a vec4, but doing so tends to cause confusion and errors and should be avoided.
gl.clearColorgl.clear will replace the entire canvas with, assuming gl.COLOR_BUFFER_BIT is included in the gl.clear call.
gl.enableVertexAttribArraylayout(location=...) in the vertex shader
gl.enableVertexAttribArray must be called on an attribute location before it is used in any other functions.
gl.vertexAttribPointerindex: the location of an attribute, as given by layout(location=...) in the vertex shadersize: an integer between 1 and 4 (inclusive), indicating how many numbers are in the array per attribute (e.g. for 2D Cartesian vectors this would be 2)type: a type code, describing how to parse the bytes in the array; typically gl.FLOATnormalized: whether to try to convert integers to floats or not; typically false, ignored if the previous argument was gl.FLOATstride: how many bytes to skip between the end of one attribute value and the start of the next; typically 0offset: the index of the first byte of the first value to reach; typically 0in variables). Note that this is connected to the attribute, not the buffer, to support cases where multiple attributes are stored in different parts of the same buffer.
The size argument should be the number of elements per value in the buffer, not in the vertex shader. For example, if you have a vec3 in GLSL being supplied with 2-vectors in the buffer you’d use 2, not 3; the GPU will automatically fill in any missing parts of the GLSL declaration with the corresponding coordinate of the homogeneous zero point .
The type and normalized arguments are primarily for memory-constrained systems with very large geometries; they should be gl.FLOAT and false, respectively, unless you spend time learning the various other formats and how they are mapped to floats.
The stride and offset arguments can be used to store several attributes in a single buffer.
If I had a Float32Array storing position and normal interleaved as
I’d send it to the GPU using gl.bufferData and tell the GPU to parse it as
let posiLoc = /* the value from layout(location=...) in the vertex shader */
let normLoc = /* the value from layout(location=...) in the vertex shader */
gl.vertexAttribPointer(posiLoc, 3, gl.FLOAT, 0, 3*4, 0*4)
gl.vertexAttribPointer(normLoc, 3, gl.FLOAT, 0, 3*4, 3*4)where the *4 is handling the bytes per value in a Float32Array.
size is the size of one attribute value, not the entire array.
size uses the unit of numbers
, while stride and offset use the unit of bytes
.
type must match the format of the typed array passed to gl.bufferData; for example, Float32Array must be paired with gl.FLOAT.
gl.enableVertexAttribArray must be called on an attribute location before it is used in any other functions, including gl.vertexAttribPointer.
gl.createProgramgl.linkProgramgl.getProgramParametergl.getProgramInfoLoggl.createVertexArraygl.drawArraysgl.uniform4fvgl.uniform1igl.enablegl.viewportgl.uniform3fvgl.blendFuncgl.uniform4fgl.uniform2fvgl.uniform2fgl.texParameterigl.activeTexturegl.disablegl.uniform1fvgl.bindTexturegl.texImage2Dgl.uniformMatrix3fvgl.uniform4ivgl.uniform3ivgl.uniform2ivgl.getUniformgl.generateMipmapgl.detachShadergl.createTexturegl.bufferSubDatagl.vertexAttrib3fgl.validateProgramgl.uniformMatrix2fvgl.pixelStoreigl.getVertexAttribgl.getExtensiongl.getActiveUniformgl.depthFuncgl.deleteProgramgl.blendEquation