@@ -2,13 +2,12 @@ Title: WebGL Comment ça marche
2
2
Description: Ce que WebGL fait vraiment
3
3
TOC: WebGL - Comment ça marche
4
4
5
-
6
5
Cet article est la suite de [ WebGL - les bases] ( webgl-fundamentals.html ) .
7
6
Avant de poursuivre je pense qu'il faut discuter de ce que WebGL et la carte graphique
8
7
font vraiment. Il y a en gros 2 parties dans le travail de la carte graphique.
9
- La première partie traite les vertices (du moins leurs données) et les convertit
8
+ La première partie traite les vertices (du moins leurs données) et les convertit
10
9
en vertices dans l'espace de coordonnées. La deuxième partie colore les pixels d'après
11
- la première partie.
10
+ la première partie.
12
11
13
12
Quand vous appelez
14
13
@@ -18,24 +17,24 @@ Le 9 ici signifie "il y a 9 vertices à traiter" donc voilà 9 vertices rendus.
18
17
19
18
<img src =" resources/vertex-shader-anim.gif " class =" webgl_center " />
20
19
21
- Sur la gauche il y a les données fournies. Le shader de vertex est une fonction que vous écrivez en
20
+ Sur la gauche il y a les données fournies. Le shader de vertex est une fonction que vous écrivez en
22
21
[ GLSL] ( webgl-shaders-and-glsl.html ) . Il est appelé une fois pour chaque vertex.
23
22
Vous écrivez quelques opérations et renseignez la variable ` gl_Position ` avec une valeur
24
23
dans l'espace de projection pour le vertex en cours. La carte graphique prend cette valeur et la met en mémoire.
25
24
26
- En supposant que vous faîtes des ` TRIANGLES ` , à chaque fois que cette première partie génère
27
- 3 points la carte graphique s'en sert pour faire un triangle. Elle regarde quels pixels sont
25
+ En supposant que vous faîtes des ` TRIANGLES ` , à chaque fois que cette première partie génère
26
+ 3 points la carte graphique s'en sert pour faire un triangle. Elle regarde quels pixels sont
28
27
concernés entre ces trois points, et pixélise le triangle. Pour chaque pixel elle va appeler
29
28
notre shader de fragment pour nous demander quelle couleur nous voulons pour ce pixel. Le
30
29
shader de fragment doit renseigner la variable ` gl_FragColor ` avec la couleur finale de chaque pixel.
31
30
32
- Tout ceci est passionnant mais comme vous voyez dans nos exemples jusqu'à maintenant le
33
- shader de fragment a très peu d'information. Heureusement on peut lui en envoyer davantage. On
34
- définit des “varyings” pour chaque valeur qu'on veut transmettre du shader de vertex au shader
35
- de fragment.
31
+ Tout ceci est passionnant mais comme vous voyez dans nos exemples jusqu'à maintenant le
32
+ shader de fragment a très peu d'information. Heureusement on peut lui en envoyer davantage. On
33
+ définit des “varyings” pour chaque valeur qu'on veut transmettre du shader de vertex au shader
34
+ de fragment.
36
35
37
- Un exemple simple est d'envoyer les coordonnées en espace de projection directement du shader
38
- de vertex au shader de fragment.
36
+ Un exemple simple est d'envoyer les coordonnées en espace de projection directement du shader
37
+ de vertex au shader de fragment.
39
38
40
39
On va dessiner un simple triangle. Après notre [ exemple précédent] ( webgl-2d-matrices.html ) changeons notre F en triangle.
41
40
@@ -59,7 +58,7 @@ Et on n'a qu'à rendre 3 points.
59
58
* gl.drawArrays(gl.TRIANGLES, 0, 3);
60
59
}
61
60
62
- Ensuite dans notre shader de vertex on déclare une * varying * pour passer des données au shader de fragment.
61
+ Ensuite dans notre shader de vertex on déclare une _ varying _ pour passer des données au shader de fragment.
63
62
64
63
varying vec4 v_couleur;
65
64
...
@@ -73,7 +72,7 @@ Ensuite dans notre shader de vertex on déclare une *varying* pour passer des do
73
72
* v_couleur = gl_Position * 0.5 + 0.5;
74
73
}
75
74
76
- Et ensuite on déclare la même * varying * dans le shader de fragment.
75
+ Et ensuite on déclare la même _ varying _ dans le shader de fragment.
77
76
78
77
precision mediump float;
79
78
@@ -89,18 +88,18 @@ Voici la version fonctionnelle.
89
88
90
89
{{{example url="../webgl-2d-triangle-with-position-for-color.html" }}}
91
90
92
- Bougez, tournez et changez l'échelle du triangle. Puisque les couleurs sont calculées
91
+ Bougez, tournez et changez l'échelle du triangle. Puisque les couleurs sont calculées
93
92
depuis l'espace de projection elles ne changent pas avec les transformations.
94
93
Elles sont relatives à l'arrière-plan.
95
94
96
- Maintenant réfléchissons. On ne calcule que 3 points. Notre shader de vertex
97
- n'est appelé que 3 fois et donc il ne calcule que 3 couleurs. Pourtant notre
98
- triangle en a davantage. C'est pour cela qu'on appelle ces variables transmises entre shaders,
99
- des * varying * .
95
+ Maintenant réfléchissons. On ne calcule que 3 points. Notre shader de vertex
96
+ n'est appelé que 3 fois et donc il ne calcule que 3 couleurs. Pourtant notre
97
+ triangle en a davantage. C'est pour cela qu'on appelle ces variables transmises entre shaders,
98
+ des _ varying _ .
100
99
101
- WebGL prends les 3 valeurs qu'on a calculées pour chaque point et
102
- pixélise le triangle en interpolant entre les valeurs renseignées.
103
- Pour chaque pixel le shader de fragment est appelé avec la valeur de
100
+ WebGL prends les 3 valeurs qu'on a calculées pour chaque point et
101
+ pixélise le triangle en interpolant entre les valeurs renseignées.
102
+ Pour chaque pixel le shader de fragment est appelé avec la valeur de
104
103
la varying interpolée pour ce pixel.
105
104
106
105
Dans l'exemple précédent on a commencé avec 3 vertices.
@@ -135,11 +134,11 @@ table.vertex_table td {
135
134
</table >
136
135
</div >
137
136
138
- Notre shader de vertex applique une matrice pour translater, tourner,
139
- changer d'échelle et convertir en espace de projection. Les valeurs
140
- par défaut sont translation = 200, 150, rotation = 0, échelle = 1,1
141
- donc on a en fait seulement une translation. Puisque la taille de notre
142
- tampon est de 400x300 (taille du canvas) notre shader de vertex applique
137
+ Notre shader de vertex applique une matrice pour translater, tourner,
138
+ changer d'échelle et convertir en espace de projection. Les valeurs
139
+ par défaut sont translation = 200, 150, rotation = 0, échelle = 1,1
140
+ donc on a en fait seulement une translation. Puisque la taille de notre
141
+ tampon est de 400x300 (taille du canvas) notre shader de vertex applique
143
142
la matrice et ensuite calcule les 3 vertices suivants dans l'espace de projection.
144
143
145
144
<div class =" hcenter " >
@@ -151,7 +150,7 @@ la matrice et ensuite calcule les 3 vertices suivants dans l'espace de projectio
151
150
</table >
152
151
</div >
153
152
154
- Il convertit aussi celle dans l'espace de couleur et les renseigne dans les * varying *
153
+ Il convertit aussi celle dans l'espace de couleur et les renseigne dans les _ varying _
155
154
v_couleur qu'on a déclarées.
156
155
157
156
<div class =" hcenter " >
@@ -163,15 +162,15 @@ v_couleur qu'on a déclarées.
163
162
</table >
164
163
</div >
165
164
166
- Ces 3 valeurs écrites dans v_couleur sont ensuite interpolées et passées au
165
+ Ces 3 valeurs écrites dans v_couleur sont ensuite interpolées et passées au
167
166
shader de fragment pour chaque pixel.
168
167
169
168
{{{diagram url="resources/fragment-shader-anim.html" width="600" height="400" caption="v_couleur est interpolé entre v0, v1 et v2" }}}
170
169
171
- On peut aussi envoyer plus de données au shader de vertex et les
172
- transmettre ensuite au shader de fragment. Par exemple, dessinons un rectangle,
173
- soit 2 triangles, en 2 couleurs. Pour cela on va indiquer un autre attribut
174
- dans le shader de vertex pour lui envoyer cette nouvelle information, et on va la
170
+ On peut aussi envoyer plus de données au shader de vertex et les
171
+ transmettre ensuite au shader de fragment. Par exemple, dessinons un rectangle,
172
+ soit 2 triangles, en 2 couleurs. Pour cela on va indiquer un autre attribut
173
+ dans le shader de vertex pour lui envoyer cette nouvelle information, et on va la
175
174
transmettre directement au shader de fragment.
176
175
177
176
attribute vec2 a_position;
@@ -229,10 +228,10 @@ Voici le résultat
229
228
230
229
{{{example url="../webgl-2d-rectangle-with-2-colors.html" }}}
231
230
232
- Notons que nous avons deux couleurs homogènes dans les triangles. Pourtant on passe
233
- bien les couleurs à nos * varying * et elles sont toujours interpolées pour chaque
234
- pixel. Mais on a mis les mêmes couleurs aux sommets d'un même
235
- triangle, d'où ce résultat. Si on indique des couleurs différentes l'interpolation
231
+ Notons que nous avons deux couleurs homogènes dans les triangles. Pourtant on passe
232
+ bien les couleurs à nos _ varying _ et elles sont toujours interpolées pour chaque
233
+ pixel. Mais on a mis les mêmes couleurs aux sommets d'un même
234
+ triangle, d'où ce résultat. Si on indique des couleurs différentes l'interpolation
236
235
redevient visible :
237
236
238
237
// Remplit le tampon avec les couleurs pour les deux triangles
@@ -251,27 +250,27 @@ redevient visible :
251
250
gl.STATIC_DRAW);
252
251
}
253
252
254
- L'interpolation de nos * varying * est visible.
253
+ L'interpolation de nos _ varying _ est visible.
255
254
256
255
{{{example url="../webgl-2d-rectangle-with-random-colors.html" }}}
257
256
258
- Rien de très excitant je suppose mais ça démontre l'utilisation de
259
- plusieurs attributs et la transmission d'information entre les deux shaders.
257
+ Rien de très excitant je suppose mais ça démontre l'utilisation de
258
+ plusieurs attributs et la transmission d'information entre les deux shaders.
260
259
Si vous jetez un oeil aux [ exemples de traitement d'image] ( webgl-image-processing.html )
261
- on verra qu'ils utilisent aussi un attribut spécial pour transmettre les coordonnées de texture.
260
+ on verra qu'ils utilisent aussi un attribut spécial pour transmettre les coordonnées de texture.
262
261
263
262
##Que font ces tampons et ces fonctions pour attributs ?
264
263
265
- Les tampons (buffer) sont l'espace mémoire dans la carte graphique dans lequel on place les informations
264
+ Les tampons (buffer) sont l'espace mémoire dans la carte graphique dans lequel on place les informations
266
265
de géométrie. ` gl.createBuffer ` créé un tampon.
267
266
` gl.bindBuffer ` active le tampon pour une action à suivre.
268
267
` gl.bufferData ` place des données dans le tampon.
269
268
270
- Une fois que les données sont dans le tampon on doit indiquer au programme WebGL comment
269
+ Une fois que les données sont dans le tampon on doit indiquer au programme WebGL comment
271
270
lire ces données et où sont les attributs à envoyer à notre shader de vertex.
272
271
273
- Pour cela on demande d'abord au programme WebGL l'emplacement qu'il a assigné aux attributs (le pointeur).
274
- Par exemple dans le code précédent on a
272
+ Pour cela on demande d'abord au programme WebGL l'emplacement qu'il a assigné aux attributs (le pointeur).
273
+ Par exemple dans le code précédent on a
275
274
276
275
// créé les pointeurs pour nos données de vertices
277
276
var emplacementPosition = gl.getAttribLocation(programme, "a_position");
@@ -291,18 +290,18 @@ Cette commande dit à WebGL qu'on veut fournir des données depuis un tampon
291
290
tailleDeLaFenêtreDeLecture,
292
291
décalage);
293
292
294
- Et cette commande dit à WebGL d'utiliser les données du dernier tampon activé gl.bindBuffer,
295
- combient de composant il y a dans l'attribut par vertex (1 - 4), de quel type de donnée il s'agit
296
- (` BYTE ` , ` FLOAT ` , ` INT ` , ` UNSIGNED_SHORT ` , etc.), la taille (en byte) de la fenêtre de lecture,
293
+ Et cette commande dit à WebGL d'utiliser les données du dernier tampon activé gl.bindBuffer,
294
+ combien de composants il y a dans l'attribut par vertex (1 - 4), de quel type de données il s'agit
295
+ (` BYTE ` , ` FLOAT ` , ` INT ` , ` UNSIGNED_SHORT ` , etc.), la taille (en byte) de la fenêtre de lecture,
297
296
et le décalage de départ de la première composante de l'attribut.
298
297
299
- Le nombre de composantes est toujours entre 1 et 4.
298
+ Le nombre de composantes est toujours compris entre 1 et 4.
300
299
301
- Si vous utilisez un tampon par type de données alors la fenêtre de lecture et le décalage de départ
302
- peuvent être laissés à 0. 0 pour la fenêtre de lecture signifie "utilise une fenêtre qui correspond
303
- au type et à la la taille des données indiquées". 0 pour le décalage signifie que le démarrage de
304
- la lecture commence à la première donnée du tampon. Mais indiquer d'autres valeurs devient plus compliqué et
305
- bien que ça ait des avantages en performance, ça ne vaut pas toujours le coup à moins que vous poussiez les limites
300
+ Si vous utilisez un tampon par type de données alors la fenêtre de lecture et le décalage de départ
301
+ peuvent être laissés à 0. 0 pour la fenêtre de lecture signifie "utilise une fenêtre qui correspond
302
+ au type et à la la taille des données indiquées". 0 pour le décalage signifie que le démarrage de
303
+ la lecture commence à la première donnée du tampon. Mais indiquer d'autres valeurs devient plus compliqué et
304
+ bien que ça ait des avantages en performance, ça ne vaut pas toujours le coup à moins que vous poussiez les limites
306
305
de votre carte graphique.
307
306
308
307
J'espère que ça éclaire les notions de tampon et d'attribut.
@@ -311,8 +310,8 @@ Rendez-vous ensuite à [shaders et GLSL](webgl-shaders-and-glsl.html).
311
310
312
311
<div class =" webgl_bottombar " ><h3 >Qu'est-ce que le paramètre donnéesNormaliséesOuNon dans la métode vertexAttribPointer?</h3 >
313
312
<p >
314
- La normalisation concerne les valeurs à type non décimal (autre que FLOAT).
315
- Si vous mettez false, ces valeurs seront interprétées avec le type qu'elles ont.
313
+ La normalisation concerne les valeurs à type non décimal (autre que FLOAT).
314
+ Si vous mettez false, ces valeurs seront interprétées avec le type qu'elles ont.
316
315
BYTE va de -128 à 127, UNSIGNED_BYTE va de 0 à 255, SHORT va de -32768 à 32767 etc...
317
316
</p >
318
317
<p >
@@ -321,11 +320,11 @@ sont transformées en -1.0 à +1.0, UNSIGNED_BYTE (0 à 255) en 0.0 to +1.0.
321
320
Les valeurs de type SHORT vont aussi de -1.0 to +1.0 mais ont plus de précision que BYTE.
322
321
</p >
323
322
<p >
324
- Le cas le plus courrant de données normalisées est pour les couleurs. La
325
- plupart du temps les couleurs vont de 0.0 à 1.0. Utiliser un FLOAT complet pour chaque composante
326
- rouge, verte, bleue et alpha demande 16 bytes par vertex et par couleur. Avec des grosses géométries
327
- ça fait beaucoup de mémoire. En convertissant les couleurs en UNSIGNED_BYTE 0 vaudra 0.0 et 255 vaudra 1.0.
328
- Et ça ne demandera que 4 bytes par couleur soit une économie de 75%.
323
+ Le cas le plus courrant de données normalisées est pour les couleurs. La
324
+ plupart du temps les couleurs vont de 0.0 à 1.0. Utiliser un FLOAT complet pour chaque composante
325
+ rouge, verte, bleue et alpha demande 16 bytes par vertex et par couleur. Avec des grosses géométries
326
+ ça fait beaucoup de mémoire. En convertissant les couleurs en UNSIGNED_BYTE 0 vaudra 0.0 et 255 vaudra 1.0.
327
+ Et ça ne demandera que 4 bytes par couleur soit une économie de 75%.
329
328
</p >
330
329
<p >Changeons notre code pour faire ça. Quand on dit au programme WebGL de prendre nos couleurs on utilisera </p >
331
330
<pre class =" prettyprint showlinemods " >
@@ -344,23 +343,23 @@ function creerCouleurs(gl) {
344
343
var b2 = Math.random() * 256; // Uint8Array
345
344
var g2 = Math.random() * 256;
346
345
347
- gl.bufferData(
348
- gl.ARRAY_BUFFER,
349
- new Uint8Array( // Uint8Array
350
- [ r1, b1, g1, 255,
351
- r1, b1, g1, 255,
352
- r1, b1, g1, 255,
353
- r2, b2, g2, 255,
354
- r2, b2, g2, 255,
355
- r2, b2, g2, 255]),
356
- gl.STATIC_DRAW);
346
+ gl.bufferData(
347
+ gl.ARRAY_BUFFER,
348
+ new Uint8Array( // Uint8Array
349
+ [ r1, b1, g1, 255,
350
+ r1, b1, g1, 255,
351
+ r1, b1, g1, 255,
352
+ r2, b2, g2, 255,
353
+ r2, b2, g2, 255,
354
+ r2, b2, g2, 255]),
355
+ gl.STATIC_DRAW);
357
356
}
357
+
358
358
</pre >
359
359
<p >
360
360
Voilà le résultat
361
361
</p >
362
362
363
363
{{{example url="../webgl-2d-rectangle-with-2-byte-colors.html" }}}
364
- </div >
365
-
366
364
365
+ </div >
0 commit comments