Nous avons créer un carré dans l'article précédent, la prochaine étape consiste à ajouter de la couleur à notre forme. Nous allons faire cela en étudiant les shaders.
Colorer les sommets
En GL, les objets sont construits en utilisants des sommets, chacun d'entre eux possèdent une position et une couleur, par défaut, la couleur des autres sommets (ainsi que les autres attributs comme la position) sont calculés en faisant une interpolation linéaire, créant automatiquement des dégradés.
Dans l'article précédent, notre fragment shader assignait la valeur blanche à chaque pixel ce qui avait donné comme résultat un carré blanc.
Dans cet article nous allons créer un dégradé ayant dans chaque coin du carré une couleur différente : du rouge, du bleu, du vert et du blanc.
La première chose à faire est d'assigner la valeur de ces couleurs à chacun des sommets. Pour cela, nous allons créer un tableau contenant les couleurs de chaque sommet puis stocker ce tableau dans un buffer WebGL.
Pour cela il faut ajouter le code suivant dans la fonction initBuffers()
:
var colors = [ 1.0, 1.0, 1.0, 1.0, // blanc 1.0, 0.0, 0.0, 1.0, // rouge 0.0, 1.0, 0.0, 1.0, // vert 0.0, 0.0, 1.0, 1.0 // bleu ]; squareVerticesColorBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); }
Ce code commence par créer un tableau contenant des vecteurs 4, un pour chaque couleur de sommet. Ensuite un buffer WebGL est alloué pour stocker ces couleurs et le tableau est converti en un tableau de flottant WebGL puis stocké dans le buffer.
Ensuite il est nécessaire d'ajouter le code suivant à la fonction initShaders()
pour initialiser l'attribut couleur de notre programme de shader :
vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor"); gl.enableVertexAttribArray(vertexColorAttribute);
Ensuite drawScene() doit être modifiée pour utiliser ces couleurs lorsque l'on dessine le carrée :
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer); gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
Pour que ces couleurs soit vraiment utilisées, le vertex shader a besoin d'être mis à jour pour transmettre la bonne couleur au fragment shader.
<script id="shader-vs" type="x-shader/x-vertex"> attribute vec3 aVertexPosition; attribute vec4 aVertexColor; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; varying lowp vec4 vColor; void main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); vColor = aVertexColor; } </script>
La principale différence ici c'est que pour chaque sommet, on assigne la valeur correspondant à sa couleur dans le tableau.
Les variables de type varying sont transmises au fragment shader.
Colorer les fragments
Voici ce à quoi ressembler notre fragment shader dans l'article précédent :
<script id="shader-fs" type="x-shader/x-fragment"> void main(void) { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); } </script>
Pour réaliser notre objectif de création d'un dégradé entre chaque sommet, il nous faut seulement assigner la couleur du fragment à la variable vColor :
<script id="shader-fs" type="x-shader/x-fragment"> varying lowp vec4 vColor; void main(void) { gl_FragColor = vColor; } </script>
C'est un changement simple car chaque fragment reçoit la couleur interpolée basée sur sa position vis à vis de chaque sommet au lieu d'une valeur fixe.
A ce moment là, vous pouvez observer le résultat produit dans un navigateur compatible avec WebGL, vous devriez voir quelquechose de semblable à ceci (mais centré sur un grand fond noir) :