WebGL Overview

tl;dr: If you want to draw a red circle on the web, you give the computer every point in the circle and what color each point should be (red). WebGL is how we give the computer this information. See bottom of article for “Where should I go from here?” and useful links.

I probably should’ve started this series of posts with one about what WebGL is and how it works. This will be that post.

What is WebGL? Why do we care about it?

WebGL is an API for rendering 3D graphics on the web. It’s how we’re able to draw graphics within the browser in real time. WebGL applications are written in Javascript and GLSL, a language designed for rendering graphics. While Javascript is generally pretty readable, GLSL is (in my opinion) unintuitive and hard to understand at first. Thus, people have created WebGL frameworks such as Threejs to help people create web applications, without having to deal with a lot of the ugly code behind the scenes.

tl;dr WebGL is how we draw stuff on the web through code. Threejs and other frameworks make WebGL easy to use by simplifying the code.

Some cool applications of WebGL:

www.masteredfromchaos.com

How does WebGL work?

I’m still learning the ins and outs of it, but here’s a basic and (hopefully) pretty accurate overview:

2D and 3D shapes are made up of points. Each point has a color. If you were to draw a red square on a piece of paper, you would outline the shape of the square, then color it in.

Your computer approaches this task slightly differently. For each point in the square, the GPU (graphics processor) determines where the point is and what color the point is (in this case, red). Then it essentially puts a red dot at a spot on the paper. It repeats this process for every single point in the square, until all the points are drawn out and you end up with a red square. You can imagine it as taking a red pen and dotting the paper until you have a red square.

That’s the basic concept, anyway. You basically tell the GPU which four vertices make up the square, and the GPU will then color in each pixel in the square, asking you what color the pixel should be for each pixel.

So how do we tell the GPU where the vertices are and what each pixel’s color should be? This is where WebGL comes in.

WebGL cares about two things: vertex position and color. This makes sense because the GPU only needs to know where the vertices of a shape are and what color each pixel needs to be.

Thus, WebGL program has two shaders: a vertex shader and a fragment shader (a “shader” is just a program.. a set of instructions). The vertex shader tells the GPU where the vertices are, and the fragment shader tells the GPU what color each pixel should be. Let’s look at a basic vertex and fragment shader:

Vertex Shader:

void main(){

gl_Position = position;

}

Fragment Shader:

void main(){

gl_FragColor = (1, 0, 0);

}

Actual shaders require a few more steps, but this is the basic concept. You give the GPU a set of vertices and the GPU goes through each vertex and runs these two shaders on that particular vertex. Then it draws the vertex at the computed point and gives the appropriate pixel the computed color.

Let’s say the vertex currently being processed is vertex “A” and is located at (0, 0, 0), a point in 3D space. The GPU would run vertex A through these two shaders, and this is what would happen:

For the vertex shader, let’s assume “position” is a special variable containing the position of the current vertex (in this example, the position of the current vertex is [0, 0, 0]). With that being said, gl_Position is another special variable which you set at the end of the vertex shader. The value you give gl_Position determines the final position in space vertex A will be located at. Thus, if your code looked like this:

gl_Position = (1, 0, 0);

Then vertex A would be drawn at (1, 0, 0) instead of (0, 0, 0). Thus, the final position of each vertex is determined by gl_Position, not the original value you give the GPU.

Similarly, for the fragment shader, gl_FragColor is another special variable that you set to determine the color of the pixel currently being drawn. The value (1, 0, 0) is a three-dimensional vector representing the color red (r, g, b). Thus, if you used these two shaders in a WebGL program, the GPU would draw the vertices at their original positions and draw every pixel as red.

Here’s a helpful article with pictures:

So that’s basically how WebGL works. We have a set of vertices and we feed it through a program. The program determines where each vertex will be drawn and the color of each pixel being drawn. Different programs will output different position values and different color values for each vertex, depending on what you write in the shader. Thus, you as the programmer basically have full control over what math you want to do to manipulate a given vertex. For example, a vertex shader that contains this code:

gl_Position = position + (1, 1, 1)

would move each vertex one unit in the positive x, y and z directions.

Of course, the actual syntax/procedure is a bit more complicated than what I have outlined above. One such complication is that points in space (such as [1, 0, 0] or [0, 0, 0]) are abstract concepts that we define for ourselves. The GPU only cares about where on the computer screen it should draw the vertex. Thus, you would have to convert a point in our user-defined “world” into a coordinate on the screen. You accomplish this by multiplying the position vector by a matrix. You can read more about it at:

Getting Started

So if you’re completely new to this sort of stuff, this explanation was probably a lot to take in all at once. WebGL is written in a pretty unintuitive language and doesn’t follow the same programming procedures that we typically learn in school (such scripting or object oriented programming).

I recommend playing around with Threejs and learning how 3D shapes work, how to manipulate vertices and how a typical drawing program is structured on the web. Here’s a REALLY helpful tutorial that achieves some pretty cool effects with very readable, well-explained code:

If you’ve been working with Threejs or other 3D frameworks for a while and want to dig deeper into how WebGL works and how to write your own shaders, I recommend going through some of these articles and following along:

These tutorials can be pretty confusing because of the strange syntax. Here are some useful references in case you’re reading some code and don’t know what a particular function does or type declaration is:

Thanks!

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.