@@ -2,12 +2,11 @@ Title: WebGL2 How It Works
2
2
Description: What WebGL is really doing under the hood
3
3
TOC: How It Works
4
4
5
-
6
5
This is a continuation from [ WebGL Fundamentals] ( webgl-fundamentals.html ) .
7
6
Before we continue I think we need to discuss at a
8
- basic level what WebGL and your GPU actually do. There are basically 2
9
- parts to this GPU thing. The first part processes vertices (or streams of
10
- data) into clip space vertices. The second part draws pixels based on the
7
+ basic level what WebGL and your GPU actually do. There are basically 2
8
+ parts to this GPU thing. The first part processes vertices (or streams of
9
+ data) into clip space vertices. The second part draws pixels based on the
11
10
first part.
12
11
13
12
When you call
@@ -18,28 +17,28 @@ The 9 there means "process 9 vertices" so here are 9 vertices being processed.
18
17
19
18
<div class =" webgl_center " ><img src =" resources/vertex-shader-anim.gif " /></div >
20
19
21
- On the left is the data you provide. The vertex shader is a function you
22
- write in [ GLSL] ( webgl-shaders-and-glsl.html ) . It gets called once for each vertex.
20
+ On the left is the data you provide. The vertex shader is a function you
21
+ write in [ GLSL] ( webgl-shaders-and-glsl.html ) . It gets called once for each vertex.
23
22
You do some math and set the special variable ` gl_Position ` with a clip space value
24
23
for the current vertex. The GPU takes that value and stores it internally.
25
24
26
25
Assuming you're drawing ` TRIANGLES ` , every time this first part generates 3
27
- vertices the GPU uses them to make a triangle. It figures out which
26
+ vertices the GPU uses them to make a triangle. It figures out which
28
27
pixels the 3 points of the triangle correspond to, and then rasterizes the
29
- triangle which is a fancy word for “draws it with pixels”. For each
28
+ triangle which is a fancy word for “draws it with pixels”. For each
30
29
pixel it will call your fragment shader asking you what color to make that
31
30
pixel. Your fragment shader has output a vec4
32
31
with the color it wants for that pixel.
33
32
34
33
That’s all very interesting but as you can see in our examples up to
35
34
this point the fragment shader has very little info per pixel.
36
- Fortunately we can pass it more info. We define “varyings” for each
35
+ Fortunately we can pass it more info. We define “varyings” for each
37
36
value we want to pass from the vertex shader to the fragment shader.
38
37
39
38
As a simple example, let's just pass the clip space coordinates we computed
40
39
directly from the vertex shader to the fragment shader.
41
40
42
- We'll draw with a simple triangle. Continuing from our
41
+ We'll draw with a simple triangle. Continuing from our
43
42
[ previous example] ( webgl-2d-matrices.html ) let's change our rectangle to a
44
43
triangle.
45
44
@@ -63,7 +62,7 @@ And we have to only draw 3 vertices.
63
62
* gl.drawArrays(gl.TRIANGLES, 0, 3);
64
63
}
65
64
66
- Then in our vertex shader we declare a * varying * by making an ` out ` to pass data to the
65
+ Then in our vertex shader we declare a _ varying _ by making an ` out ` to pass data to the
67
66
fragment shader.
68
67
69
68
out vec4 v_color;
@@ -78,7 +77,7 @@ fragment shader.
78
77
* v_color = gl_Position * 0.5 + 0.5;
79
78
}
80
79
81
- And then we declare the same * varying * as an ` in ` in the fragment shader.
80
+ And then we declare the same _ varying _ as an ` in ` in the fragment shader.
82
81
83
82
#version 300 es
84
83
@@ -99,17 +98,17 @@ Here's the working version.
99
98
100
99
{{{example url="../webgl-2d-triangle-with-position-for-color.html" }}}
101
100
102
- Move, scale and rotate the triangle. Notice that since the colors are
103
- computed from clip space they don't move with the triangle. They are
101
+ Move, scale and rotate the triangle. Notice that since the colors are
102
+ computed from clip space they don't move with the triangle. They are
104
103
relative to the background.
105
104
106
- Now think about it. We only compute 3 vertices. Our vertex shader only
105
+ Now think about it. We only compute 3 vertices. Our vertex shader only
107
106
gets called 3 times therefore it's only computing 3 colors yet our
108
- triangle is many colors. This is why it's called a * varying * .
107
+ triangle is many colors. This is why it's called a _ varying _ .
109
108
110
109
WebGL takes the 3 values we computed for each vertex and as it rasterizes
111
110
the triangle it interpolates between the values we computed for the
112
- vertices. For each pixel it calls our fragment shader with the
111
+ vertices. For each pixel it calls our fragment shader with the
113
112
interpolated value for that pixel.
114
113
115
114
In the example above we start out with the 3 vertices
@@ -145,9 +144,9 @@ table.vertex_table td {
145
144
</div >
146
145
147
146
Our vertex shader applies a matrix to translate, rotate, scale and convert
148
- to clip space. The defaults for translation, rotation and scale are
147
+ to clip space. The defaults for translation, rotation and scale are
149
148
translation = 200, 150, rotation = 0, scale = 1,1 so that's really only
150
- translation. Given our backbuffer is 400x300 our vertex shader applies
149
+ translation. Given our backbuffer is 400x300 our vertex shader applies
151
150
the matrix and then computes the following 3 clip space vertices.
152
151
153
152
<div class =" hcenter " >
@@ -159,7 +158,7 @@ the matrix and then computes the following 3 clip space vertices.
159
158
</table >
160
159
</div >
161
160
162
- It also converts those to color space and writes them to the * varying *
161
+ It also converts those to color space and writes them to the _ varying _
163
162
v_color that we declared.
164
163
165
164
<div class =" hcenter " >
@@ -177,8 +176,8 @@ fragment shader for each pixel.
177
176
{{{diagram url="resources/fragment-shader-anim.html" width="600" height="400" caption="v_color is interpolated between v0, v1 and v2" }}}
178
177
179
178
We can also pass in more data to the vertex shader which we can then pass
180
- on to the fragment shader. So for example let's draw a rectangle, that
181
- consists of 2 triangles, in 2 colors. To do this we'll add another
179
+ on to the fragment shader. So for example let's draw a rectangle, that
180
+ consists of 2 triangles, in 2 colors. To do this we'll add another
182
181
attribute to the vertex shader so we can pass it more data and we'll pass
183
182
that data directly to the fragment shader.
184
183
@@ -247,10 +246,10 @@ And here's the result.
247
246
248
247
{{{example url="../webgl-2d-rectangle-with-2-colors.html" }}}
249
248
250
- Notice that we have 2 solid color triangles. Yet we're passing the values
251
- in a * varying * so they are being varied or interpolated across the
252
- triangle. It's just that we used the same color on each of the 3 vertices
253
- of each triangle. If we make each color different we'll see the
249
+ Notice that we have 2 solid color triangles. Yet we're passing the values
250
+ in a _ varying _ so they are being varied or interpolated across the
251
+ triangle. It's just that we used the same color on each of the 3 vertices
252
+ of each triangle. If we make each color different we'll see the
254
253
interpolation.
255
254
256
255
// Fill the buffer with colors for the 2 triangles
@@ -269,27 +268,27 @@ interpolation.
269
268
gl.STATIC_DRAW);
270
269
}
271
270
272
- And now we see the interpolated * varying * .
271
+ And now we see the interpolated _ varying _ .
273
272
274
273
{{{example url="../webgl-2d-rectangle-with-random-colors.html" }}}
275
274
276
275
Not very exciting I suppose but it does demonstrate using more than one
277
- attribute and passing data from a vertex shader to a fragment shader. If
276
+ attribute and passing data from a vertex shader to a fragment shader. If
278
277
you check out [ the image processing examples] ( webgl-image-processing.html )
279
278
you'll see they also use an extra attribute to pass in texture coordinates.
280
279
281
- ##What do these buffer and attribute commands do?
280
+ ## What do these buffer and attribute commands do?
282
281
283
282
Buffers are the way of getting vertex and other per vertex data onto the
284
- GPU. ` gl.createBuffer ` creates a buffer.
283
+ GPU. ` gl.createBuffer ` creates a buffer.
285
284
` gl.bindBuffer ` sets that buffer as the buffer to be worked on.
286
285
` gl.bufferData ` copies data into the current buffer.
287
286
288
287
Once the data is in the buffer we need to tell WebGL how to get data out
289
288
of it and provide it to the vertex shader's attributes.
290
289
291
290
To do this, first we ask WebGL what locations it assigned to the
292
- attributes. For example in the code above we have
291
+ attributes. For example in the code above we have
293
292
294
293
// look up where the vertex data needs to go.
295
294
var positionLocation = gl.getAttribLocation(program, "a_position");
@@ -318,8 +317,8 @@ next piece of data, and an offset for how far into the buffer our data is.
318
317
Number of components is always 1 to 4.
319
318
320
319
If you are using 1 buffer per type of data then both stride and offset can
321
- always be 0. 0 for stride means "use a stride that matches the type and
322
- size". 0 for offset means start at the beginning of the buffer. Setting
320
+ always be 0. 0 for stride means "use a stride that matches the type and
321
+ size". 0 for offset means start at the beginning of the buffer. Setting
323
322
them to values other than 0 is more complicated and though it might have some
324
323
benefits in terms of performance it's not worth the complication unless
325
324
you are trying to push WebGL to its absolute limits.
@@ -373,23 +372,23 @@ function setColors(gl) {
373
372
var b2 = Math.random() * 256; // Uint8Array
374
373
var g2 = Math.random() * 256;
375
374
376
- gl.bufferData(
377
- gl.ARRAY_BUFFER,
378
- new Uint8Array( // Uint8Array
379
- [ r1, b1, g1, 255,
380
- r1, b1, g1, 255,
381
- r1, b1, g1, 255,
382
- r2, b2, g2, 255,
383
- r2, b2, g2, 255,
384
- r2, b2, g2, 255]),
385
- gl.STATIC_DRAW);
375
+ gl.bufferData(
376
+ gl.ARRAY_BUFFER,
377
+ new Uint8Array( // Uint8Array
378
+ [ r1, b1, g1, 255,
379
+ r1, b1, g1, 255,
380
+ r1, b1, g1, 255,
381
+ r2, b2, g2, 255,
382
+ r2, b2, g2, 255,
383
+ r2, b2, g2, 255]),
384
+ gl.STATIC_DRAW);
386
385
}
386
+
387
387
</pre >
388
388
<p >
389
389
Here's that sample.
390
390
</p >
391
391
392
392
{{{example url="../webgl-2d-rectangle-with-2-byte-colors.html" }}}
393
- </div >
394
-
395
393
394
+ </div >
0 commit comments