le but de cette page est d'illustrer l'application d'une compréhension de WebGL. Merci à Greggman. https://stackoverflow.com/questions/27148273/what-is-the-logic-of-binding-buffers-in-webgl/27164577#27164577
let canvas = document.getElementById('canvas');
let gl = canvas.getContext('webgl');
let verticesTriangle1=[
-1,-1,0,
0,1,0,
1,-1,0
];
/*
Buffer objects (sometimes referred to as VBOs) hold vertex attribute data for the GLSL shaders.
*/
let vertex_buffer1 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer1);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesTriangle1), gl.STATIC_DRAW);
let verticesTriangle2=[
-1, 1, 0,
1, 1, 0,
0,-1, 0
];
let vertex_buffer2 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer2);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesTriangle2), gl.STATIC_DRAW);
let vertCode = `
attribute vec3 coordinates;
void main() {
gl_Position = vec4(coordinates, 1.0);
}
`;
let fragCode = `
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
uniform vec4 uColor;
void main() {
gl_FragColor = uColor;
}
`;
let vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
let fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);
let shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);
let coord = gl.getAttribLocation(shaderProgram, "coordinates");
gl.enableVertexAttribArray(coord);
let colorLoc = gl.getUniformLocation(shaderProgram,"uColor");
gl.enable(gl.DEPTH_TEST);
gl.viewport(0, 0, canvas.width, canvas.height);
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer2);
gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
gl.uniform4f(colorLoc,0,1,0,1);
gl.drawArrays(gl.TRIANGLES, 0, 3);
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer1);
gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
gl.uniform4f(colorLoc,0,0,1,1);
gl.drawArrays(gl.TRIANGLES, 0, 3);
explication du code
let vertex_buffer1 = gl.createBuffer();
crée un buffer. un buffer va contenir les données pour les variables de type attribute dans le code glsl. https://registry.khronos.org/webgl/specs/latest/1.0/#5.14.5
let coord = gl.getAttribLocation(shaderProgram, "coordinates");
gl.enableVertexAttribArray(coord);
On va maintenant décrire l'état du contexte WebGL après chaque instruction. Le tableau suivant, Vertex Arrays , stocke les états des attributs. Exemple d'un attribut dans le code glsl : attribute vec3 coordinates; Les attributs établissent la façon d'amener les données des buffers vers le shader de type vertex.
enabled | size | type | normalize | stride | offset | buffer |
---|---|---|---|---|---|---|
false | 4 | FLOAT | false | 0 | 0 | null |
false | 4 | FLOAT | false | 0 | 0 | null |
false | 4 | FLOAT | false | 0 | 0 | null |
false | 4 | FLOAT | false | 0 | 0 | null |
false | 4 | FLOAT | false | 0 | 0 | null |
false | 4 | FLOAT | false | 0 | 0 | null |
le tableau "Vertex Array" contient les états des variables de type "attribute". Ce type définit comment envoyer les données d'un buffer vers le vertex shader. Dans le tableau "vertex array", les éléments sont sous la forme : la ligne : let coord = gl.getAttribLocation(shaderProgram, "coordinates"); assigne l'indice de 'coordinates' : attribute vec3 coordinates; dans ce tableau. la ligne gl.enableVertexAttribArray(coord); //Enable the vertex attribute at index 'coord' as an array. donne à l'élément "enabled" la valeur true :
enabled | size | type | normalize | stride | offset | buffer |
---|---|---|---|---|---|---|
true | 4 | FLOAT | false | 0 | 0 | null |
false | 4 | FLOAT | false | 0 | 0 | null |
false | 4 | FLOAT | false | 0 | 0 | null |
false | 4 | FLOAT | false | 0 | 0 | null |
false | 4 | FLOAT | false | 0 | 0 | null |
false | 4 | FLOAT | false | 0 | 0 | null |
let vertex_buffer1 = gl.createBuffer();
null |
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer1);
le buffer vertex_buffer1 devient le buffer courant. The `ARRAY_BUFFER` binding point is mostly just like an internal variable inside webgl. You set it by calling `gl.bindBuffer(gl.ARRAY_BUFFER, someBuffer);` and then all other buffer functions can refer to the buffer bound there."
ARRAY_BUFFER_BINDING | vertex_buffer1 |
gl.bufferData(gl.ARRAY_BUFFER,
new Float32Array([
-1, -1, 0,
0, 1, 0,
1, -1, 0
]),
gl.STATIC_DRAW);
global state : ============= ARRAY_BUFFER_BINDING : vertex_buffer1 = [-1, -1, 0,0, 1, 0,1, -1, 0] On rempli le buffer courant. Le buffer courant, c'est à dire le buffer précédemment définit comme buffer courant par la fonction bindbuffer. On comprend ainsi que la fonction bufferData n'a pas de paramètre de type buffer.
gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);
enabled | size | type | normalize | stride | offset | divisor | buffer |
---|---|---|---|---|---|---|---|
Peter | Griffin | $100 | |||||
Lois | Griffin | $150 | |||||
Joe | Swanson | $300 | |||||
Cleveland | Brown | $250 |
global state : ============== ARRAY_BUFFER_BINDING : vertex_buffer1= [-1, -1, 0,0, 1, 0,1, -1, 0] vertex array: ============ [ {enabled: false, {enabled: true,...} } ]
this.vertexAttribPointer = function(location, size, type, normalized, stride, offset) { const attribute = vertexArray.attributes[location]; attribute.size = size; // num values to pull from buffer per vertex shader iteration attribute.type = type; // type of values to pull from buffer attribute.normalized = normalized; // whether or not to normalize attribute.stride = stride; // number of bytes to advance for each iteration of the vertex shader. 0 = compute from type, size attribute.offset = offset; // where to start in buffer. // IMPORTANT!!! Associates whatever buffer is currently *bound* to // "arrayBuffer" to this attribute attribute.buffer = arrayBuffer; };