gl.getUniformLocation
gl.bindVertexArray
gl.useProgram
gl.clear
gl.uniformMatrix4fv
gl.bindBuffer
gl.bufferData
gl.drawElements
gl.createBuffer
gl.attachShader
gl.createShader
gl.shaderSource
gl.compileShader
gl.getShaderParameter
gl.getShaderInfoLog
gl.uniform1f
gl.clearColor
gl.enableVertexAttribArray
gl.vertexAttribPointer
gl.getAttribLocation
gl.createProgram
gl.linkProgram
gl.getProgramParameter
gl.getProgramInfoLog
gl.createVertexArray
gl.drawArrays
gl.uniform4fv
gl.uniform1i
gl.enable
gl.viewport
gl.uniform3fv
gl.blendFunc
gl.uniform4f
gl.uniform2fv
gl.uniform2f
gl.texParameteri
gl.activeTexture
gl.disable
gl.uniform1fv
gl.bindTexture
gl.texImage2D
gl.uniformMatrix3fv
gl.uniform4iv
gl.uniform3iv
gl.uniform2iv
gl.getUniform
gl.generateMipmap
gl.detachShader
gl.createTexture
gl.bufferSubData
gl.vertexAttrib3f
gl.validateProgram
gl.uniformMatrix2fv
gl.pixelStorei
gl.getVertexAttrib
gl.getExtension
gl.getActiveUniform
gl.depthFunc
gl.deleteProgram
gl.blendEquation
The following are presented in order of frequency of use in roughly 200 student’s submissions of 4 WebGL2 assignments.
gl.getUniformLocation
uniform
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 location per program, and may pick different locations each compilation.
gl.bindVertexArray
gl.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
depends on gl.getAttribLocation
which
is program-dependent; thus, the VAO is unlikely to work correctly with
multiple programs unless they all share the same vertex shader or the
attribute locations are specified manually in the vertex shader source
code.
gl.useProgram
gl.clear
gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT
gl.uniformMatrix4fv
gl.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,
.uniformMatrix4fv(loc, false,
gl1, 2, 3, 4
[ , 5, 6, 7, 8
, 9, 10, 11, 12
,13, 14, 15, 16
])
will create the matrix \begin{bmatrix}1&5&9&13\\2&6&10&14\\3&7&11&15\\4&8&12&16\end{bmatrix} which is not the order that most programmers expect.
gl.bindBuffer
gl.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.bufferData
gl.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.drawElements
gl.TRIANGLES
gl.bindBuffer
and generally
re-enabled via gl.bindVertexArray
gl.UNSIGNED_SHORT
gl.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.createBuffer
The 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.attachShader
gl.createProgram
gl.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.createShader
gl.VERTEX_SHADER
or
gl.FRAGMENT_SHADER
gl.shaderSource
, gl.compileShader
, and gl.attachShader
.
gl.shaderSource
gl.createShader
gl.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.compileShader
gl.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.getShaderParameter
gl.createShader
gl.getShaderParameter
gl.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.getShaderInfoLog
gl.createShader
gl.getShaderInfoLog
does not remove the need for gl.getShaderParameter
:
the info log might be non-empty even if the compilation succeeds.
gl.uniform1f
gl.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.clearColor
gl.clear
will replace the entire
canvas with, assuming gl.COLOR_BUFFER_BIT
is included in
the gl.clear
call.
gl.enableVertexAttribArray
gl.getAttribLocation
gl.enableVertexAttribArray
must be called on an attribute
location before it is used in any other functions.
gl.vertexAttribPointer
index
: the return value of gl.getAttribLocation
size
: 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.FLOAT
normalized
: whether to try to convert integers to
floats or not; typically false
, ignored if the previous
argument was gl.FLOAT
stride
: how many bytes to skip between the end of one
attribute value and the start of the next; typically 0
offset
: the index of the first byte of the first value
to reach; typically 0
in
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 (0,0,0,1).
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 [p_{1,x}, p_{1,y}, p_{1,z},
n_{1,x}, n_{1,y}, n_{1,z}, p_{2,x}, p_{2,y}, \dots] I’d send it
to the GPU using gl.bufferData
and tell the GPU to parse it as
let posiLoc = gl.getAttribLocation("position")
let normLoc = gl.getAttribLocation("normal")
.vertexAttribPointer(posiLoc, 3, gl.FLOAT, 0, 3*4, 0*4)
gl.vertexAttribPointer(normLoc, 3, gl.FLOAT, 0, 3*4, 3*4) gl
where the *4
is 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.getAttribLocation
in
variable in
that programs vertex shader
Attributes require multiple parts to work, including gl.bufferData
to send data to the
GPU and gl.vertexAttribPointer
to tell the GPU how to parse that data.
Each attribute is given a specific location, a small integer usually between 0 and 15. The vertex shader compiler picks these locations per program, and may pick different locations each compilation.
gl.enableVertexAttribArray
must be called on the return value before it is used in any other
functions.
gl.createProgram
gl.linkProgram
gl.getProgramParameter
gl.getProgramInfoLog
gl.createVertexArray
gl.drawArrays
gl.uniform4fv
gl.uniform1i
gl.enable
gl.viewport
gl.uniform3fv
gl.blendFunc
gl.uniform4f
gl.uniform2fv
gl.uniform2f
gl.texParameteri
gl.activeTexture
gl.disable
gl.uniform1fv
gl.bindTexture
gl.texImage2D
gl.uniformMatrix3fv
gl.uniform4iv
gl.uniform3iv
gl.uniform2iv
gl.getUniform
gl.generateMipmap
gl.detachShader
gl.createTexture
gl.bufferSubData
gl.vertexAttrib3f
gl.validateProgram
gl.uniformMatrix2fv
gl.pixelStorei
gl.getVertexAttrib
gl.getExtension
gl.getActiveUniform
gl.depthFunc
gl.deleteProgram
gl.blendEquation