WebGL - Modes of Drawing
Hello, future WebGL wizards! ? Today, we're going to dive into the exciting world of drawing modes in WebGL. As your friendly neighborhood computer teacher, I'm here to guide you through this journey, even if you've never written a line of code before. So, grab your virtual paintbrush, and let's create some digital masterpieces!
The mode Parameter
Before we start drawing, let's talk about the star of our show: the mode
parameter. Think of it as the magic wand that tells WebGL how to connect the dots (or in our case, vertices) to create different shapes and patterns.
In WebGL, when we call the gl.drawArrays()
or gl.drawElements()
function, we need to specify a mode
parameter. This parameter is like giving instructions to a connect-the-dots puzzle – it tells WebGL how to join the points we've defined.
Here's a table of the different drawing modes available in WebGL:
Mode | Description |
---|---|
gl.POINTS | Draws a single point for each vertex |
gl.LINES | Draws a line between each pair of vertices |
gl.LINE_STRIP | Draws a continuous line connecting the vertices |
gl.LINE_LOOP | Similar to LINE_STRIP, but closes the shape |
gl.TRIANGLES | Draws a triangle for every three vertices |
gl.TRIANGLE_STRIP | Draws a connected group of triangles |
gl.TRIANGLE_FAN | Draws a fan-like shape of connected triangles |
Don't worry if these seem confusing now. We'll explore each of them with examples as we go along!
Example – Draw Three Parallel Lines
Let's start with a simple example: drawing three parallel lines. This will help us understand how the mode
parameter works in practice.
// First, let's set up our WebGL context
const canvas = document.getElementById('myCanvas');
const gl = canvas.getContext('webgl');
// Now, let's define our vertex shader
const vertexShaderSource = `
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}
`;
// And our fragment shader
const fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Red color
}
`;
// Create and compile the shaders (don't worry, we'll explain this in detail in future lessons)
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
// Create a program and link the shaders
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
// Define the positions of our lines
const positions = new Float32Array([
-0.8, -0.8, // Line 1 start
-0.8, 0.8, // Line 1 end
-0.3, -0.8, // Line 2 start
-0.3, 0.8, // Line 2 end
0.2, -0.8, // Line 3 start
0.2, 0.8 // Line 3 end
]);
// Create a buffer and put the positions in it
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
// Tell WebGL how to read the buffer and attribute it to a_position
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
// Clear the canvas
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// Draw the lines
gl.drawArrays(gl.LINES, 0, 6);
Now, let's break this down:
-
We set up our WebGL context and define our shaders. Don't worry too much about these now; we'll cover shaders in depth in future lessons.
-
We create a program and link our shaders to it. This is like preparing our digital paintbrush.
-
We define the positions of our lines. Each line is defined by two points (its start and end), and each point is defined by two coordinates (x and y). So, we have 6 points in total for our 3 lines.
-
We create a buffer and put our positions in it. Think of this as loading our paint onto the brush.
-
We tell WebGL how to read this buffer and associate it with the
a_position
attribute in our vertex shader. -
Finally, we call
gl.drawArrays(gl.LINES, 0, 6)
. This is where the magic happens!-
gl.LINES
is our mode. It tells WebGL to draw lines between pairs of vertices. -
0
is the starting index in our array of positions. -
6
is the number of vertices to consider (remember, we have 6 points for our 3 lines).
-
Run this code, and voila! You should see three red parallel lines on a black background. Congratulations, you've just created your first WebGL drawing! ?
Drawing Modes
Now that we've seen gl.LINES
in action, let's explore some other drawing modes. We'll use the same setup as before, but change our positions and the drawing mode.
gl.POINTS
Let's start with the simplest mode: gl.POINTS
. This mode draws a single point for each vertex.
// ... (previous setup code)
const positions = new Float32Array([
-0.5, 0.5,
0.0, 0.0,
0.5, -0.5
]);
// ... (buffer setup code)
gl.drawArrays(gl.POINTS, 0, 3);
This will draw three red points on your canvas. Simple, right?
gl.LINE_STRIP
Now, let's try gl.LINE_STRIP
. This mode draws a continuous line, connecting each vertex to the next.
// ... (previous setup code)
const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);
// ... (buffer setup code)
gl.drawArrays(gl.LINE_STRIP, 0, 3);
You should see a V-shaped line connecting the three points.
gl.LINE_LOOP
gl.LINE_LOOP
is similar to LINE_STRIP
, but it closes the shape by connecting the last vertex back to the first.
// ... (previous setup code)
const positions = new Float32Array([
-0.5, 0.5,
0.0, -0.5,
0.5, 0.5
]);
// ... (buffer setup code)
gl.drawArrays(gl.LINE_LOOP, 0, 3);
This will draw a triangle outline.
gl.TRIANGLES
Now, let's move on to filling shapes with gl.TRIANGLES
. This mode draws a separate triangle for every three vertices.
// ... (previous setup code)
const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
0.0, 0.5
]);
// ... (buffer setup code)
gl.drawArrays(gl.TRIANGLES, 0, 3);
You should see a solid red triangle.
gl.TRIANGLE_STRIP
gl.TRIANGLE_STRIP
is a bit more complex. It draws a connected group of triangles, where each triangle shares two vertices with the previous one.
// ... (previous setup code)
const positions = new Float32Array([
-0.5, -0.5,
0.5, -0.5,
-0.5, 0.5,
0.5, 0.5
]);
// ... (buffer setup code)
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
This will draw two connected triangles forming a rectangle.
gl.TRIANGLE_FAN
Finally, let's look at gl.TRIANGLE_FAN
. This mode draws a fan-like shape, where all triangles share the first vertex as a common point.
// ... (previous setup code)
const positions = new Float32Array([
0.0, 0.0, // Center point
0.5, 0.0, // Point 1
0.35, 0.35, // Point 2
0.0, 0.5, // Point 3
-0.35, 0.35 // Point 4
]);
// ... (buffer setup code)
gl.drawArrays(gl.TRIANGLE_FAN, 0, 5);
This will draw a shape that looks a bit like a quarter of a circle.
And there you have it! We've explored all the drawing modes in WebGL. Remember, the key to mastering these is practice. Try combining different modes, changing colors, and playing with vertex positions. Before you know it, you'll be creating complex WebGL scenes with ease!
In our next lesson, we'll dive deeper into shaders and learn how to add some pizzazz to our drawings with colors and textures. Until then, happy coding, future WebGL artists! ?????
Credits: Image by storyset