WebGL just draws shaded triangles. From this, we can create extremely detailed and efficient renderings. For example, the animation below is drawn in WebGL using just one triangle with a complex fragment shader:
Many more examples like the above can be found on shadertoy, which is a great place to learn more about GLSL programming and computer graphics.
In this section we're going to cover the basics of drawing things in regl
starting with a single triangle.
In regl
, you write commands to tell the GPU how to render objects. Each command contains a vertex and fragment shader, which tells the GPU what to draw. Shaders are tiny programs that run on the GPU written in a special language called GLSL.
Here is an example of a draw command in regl:
// Again, we start out by requiring regl
var regl = require('regl')()
// Next, we create a new command.
//
// To do this, we call the main regl function and pass it an object giving a
// description of the rendering command and its properties:
//
var drawTriangle = regl({
//
// First we define a vertex shader. This is a program which tells the GPU
// where to draw the vertices.
//
vert: `
// This is a simple vertex shader that just passes the position through
attribute vec2 position;
void main () {
gl_Position = vec4(position, 0, 1);
}
`,
//
// Next, we define a fragment shader to tell the GPU what color to draw.
//
frag: `
// This is program just colors the triangle white
void main () {
gl_FragColor = vec4(1, 1, 1, 1);
}
`,
// Finally we need to give the vertices to the GPU
attributes: {
position: [
[1, 0],
[0, 1],
[-1, -1]
]
},
// And also tell it how many vertices to draw
count: 3
})
// Now that our command is defined, we hook a callback to draw it each frame:
regl.frame(function () {
// First we clear the color and depth buffers like before
regl.clear({
color: [0, 0, 0, 1],
depth: 1
})
// Then we call the command that we just defined
drawTriangle()
})
var regl = require('regl')()
var drawTriangle = regl({
vert: `
precision mediump float;
attribute vec2 position;
varying vec3 fcolor;
void main () {
fcolor = abs(vec3(position.x, 0, position.y));
gl_Position = vec4(position, 0, 1);
}
`,
frag: `
precision mediump float;
varying vec3 fcolor;
void main () {
gl_FragColor = vec4(fcolor, 1);
}
`,
attributes: {
position: [
[1, 0],
[0, 1],
[-1, -1]
]
},
count: 3
})
regl.frame(function () {
regl.clear({
color: [0, 0, 0, 1],
depth: 1
})
drawTriangle()
})
var regl = require('regl')()
var drawTriangle = regl({
vert: `
precision mediump float;
attribute vec2 position;
attribute vec3 color;
varying vec3 fcolor;
void main () {
fcolor = color;
gl_Position = vec4(position, 0, 1);
}
`,
frag: `
precision mediump float;
varying vec3 fcolor;
void main () {
gl_FragColor = vec4(fcolor, 1);
}
`,
attributes: {
position: [
[1, 0],
[0, 1],
[-1, -1]
],
color: [
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
]
},
count: 3
})
regl.frame(function () {
regl.clear({
color: [0, 0, 0, 1],
depth: 1
})
drawTriangle()
})
var regl = require('regl')()
var drawTriangle = regl({
vert: `
precision mediump float;
uniform float scale;
attribute vec2 position;
attribute vec3 color;
varying vec3 fcolor;
void main () {
fcolor = color;
gl_Position = vec4(scale * position, 0, 1);
}
`,
frag: `
precision mediump float;
varying vec3 fcolor;
void main () {
gl_FragColor = vec4(fcolor, 1);
}
`,
attributes: {
position: [
[1, 0],
[0, 1],
[-1, -1]
],
color: [
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
]
},
uniforms: {
scale: 0.25
},
count: 3
})
regl.frame(function () {
regl.clear({
color: [0, 0, 0, 1],
depth: 1
})
drawTriangle()
})