Skip to content

WebGL - Modes of Drawing

WebGL provides several ways to interpret vertex data to form different kinds of shapes, known as drawing modes or primitive types. These modes are specified as the first argument to gl.drawArrays() and gl.drawElements().

Recall the syntax for the drawing commands:

void gl.drawArrays(mode, first, count);
void gl.drawElements(mode, count, type, offset);

The mode parameter determines how the vertices (specified by count and first/offset and potentially indices) are connected to form geometric primitives.

S.No.Mode ConstantDescriptionVertex Order Example
1gl.POINTSDraws a single point for each vertex specified. Point size can be controlled via gl_PointSize in the vertex shader.
2gl.LINESDraws a series of separate line segments. Vertices (0, 1), (2, 3), (4, 5), etc., each form an independent line. Requires an even number of vertices (count must be multiple of 2).
3gl.LINE_STRIPDraws a connected sequence of line segments. Vertices (0, 1), (1, 2), (2, 3), etc., form a continuous polyline.
4gl.LINE_LOOPSimilar to gl.LINE_STRIP, but also draws an additional line segment connecting the last vertex back to the first vertex, forming a closed loop.
5gl.TRIANGLESDraws a series of separate triangles. Vertices (0, 1, 2), (3, 4, 5), etc., each form an independent triangle. Requires count to be a multiple of 3.
6gl.TRIANGLE_STRIPDraws a series of connected triangles. After the first triangle (0, 1, 2), subsequent vertices n form triangles (n-1, n-2, n), (n-1, n, n+1), etc., alternating winding order. Efficient for rendering meshes represented as strips.Text Description: Creates triangles (v0,v1,v2), (v2,v1,v3), (v2,v3,v4), (v4,v3,v5)…
7gl.TRIANGLE_FANDraws a series of connected triangles that share the first vertex (vertex 0). Triangles are formed as (0, 1, 2), (0, 2, 3), (0, 3, 4), etc. Useful for drawing circles, cones, or other fan-like shapes.Text Description: Creates triangles (v0,v1,v2), (v0,v2,v3), (v0,v3,v4)…

Example: Drawing Parallel Lines using gl.LINES

Section titled “Example: Drawing Parallel Lines using gl.LINES”

This example uses gl.LINES to draw three separate horizontal line segments.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebGL Drawing Modes - Lines</title>
<style>
body { margin: 0; overflow: hidden; background-color: #fff; }
canvas { display: block; border: 1px solid black; }
</style>
</head>
<body>
<canvas id="webgl-canvas" width="400" height="400"></canvas>
<script>
// --- Shader Sources (Simple pass-through) ---
const vsSource = `
attribute vec3 a_position;
void main() {
gl_Position = vec4(a_position, 1.0);
// Make lines visible even if thin
gl_PointSize = 1.0; // Needed for some drivers if lines are thin
}
`;
const fsSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(0.0, 0.0, 0.8, 1.0); // Blue color
}
`;
// --- Utilities: createShader, createProgram (Assume defined) ---
function createShader(gl, type, source) { /* ... */
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error(`Shader compilation error (${type === gl.VERTEX_SHADER ? 'Vertex' : 'Fragment'}):`, gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
function createProgram(gl, vsSource, fsSource) { /* ... */
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);
if (!vertexShader || !fragmentShader) return null;
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('Program linking error:', gl.getProgramInfoLog(program));
gl.deleteProgram(program);
return null;
}
return program;
}
// --- Main WebGL ---
const canvas = document.getElementById('webgl-canvas');
const gl = canvas.getContext('webgl');
if (!gl) { alert('WebGL not supported.'); throw new Error('WebGL not supported'); }
const shaderProgram = createProgram(gl, vsSource, fsSource);
if (!shaderProgram) throw new Error('Failed program creation.');
// --- Geometry (6 vertices for 3 separate lines) ---
const lineVertices = new Float32Array([
// Line 1
-0.7, 0.6, 0.0, // Start point
0.7, 0.6, 0.0, // End point
// Line 2
-0.7, 0.0, 0.0,
0.7, 0.0, 0.0,
// Line 3
-0.7, -0.6, 0.0,
0.7, -0.6, 0.0
]);
// --- Buffer ---
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, lineVertices, gl.STATIC_DRAW);
// --- Attribute Setup ---
const positionAttribLocation = gl.getAttribLocation(shaderProgram, 'a_position');
if (positionAttribLocation < 0) console.error("Attr 'a_position' not found");
gl.enableVertexAttribArray(positionAttribLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer(positionAttribLocation, 3, gl.FLOAT, false, 0, 0);
// --- Drawing ---
gl.useProgram(shaderProgram);
gl.clearColor(1.0, 1.0, 1.0, 1.0); // White background
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
// Draw using LINES mode
gl.drawArrays(
gl.LINES, // Mode: Draw separate lines
0, // Start index
6 // Number of vertices (3 lines * 2 vertices/line)
);
</script>
</body>
</html>

Expected Output:

The code will render three separate horizontal blue lines stacked vertically on a white background.

Visualizing Other Modes (Using the Same Vertices)

Section titled “Visualizing Other Modes (Using the Same Vertices)”

If you change gl.LINES to other modes in the gl.drawArrays call using the same six vertices from the example above, you would see different results:

  • gl.LINE_STRIP: A zig-zag line connecting all six points in order: (-0.7, 0.6) -> (0.7, 0.6) -> (-0.7, 0.0) -> (0.7, 0.0) -> (-0.7, -0.6) -> (0.7, -0.6).
  • gl.LINE_LOOP: Same as gl.LINE_STRIP, but with an extra line connecting the last point (0.7, -0.6) back to the first (-0.7, 0.6), forming a closed, complex shape.
  • gl.TRIANGLES: Two separate triangles. The first uses vertices 0, 1, 2 ((-0.7, 0.6), (0.7, 0.6), (-0.7, 0.0)). The second uses vertices 3, 4, 5 ((0.7, 0.0), (-0.7, -0.6), (0.7, -0.6)).
  • gl.TRIANGLE_STRIP: A sequence of connected triangles: (0,1,2), (1,2,3), (2,3,4), (3,4,5). This would form a complex, possibly overlapping shape.
  • gl.TRIANGLE_FAN: A fan of triangles originating from vertex 0: (0,1,2), (0,2,3), (0,3,4), (0,4,5). This would also form a complex shape centered around the first vertex.

Choosing the right drawing mode depends on the geometry you want to render and how your vertex/index data is structured.