Index buffer
Estendiamo l’esempio Attributi multipli disegnando un quadrato e sfruttando gli index buffer per evitare la duplicazione dei vertici.
Cominciamo ridefinendo vertices in modo da includere due triangoli:
const vertices = [
// 1st vertex
-1, -1, 1, 0, 0,
// 2nd vertex
1, -1, 0, 1, 0,
// 3rd vertex
-1, 1, 0, 0, 1,
// 1st vertex
-1, 1, 0, 0, 1,
// 2nd vertex
1, -1, 0, 1, 0,
// 3rd vertex
1, 1, 1, 1, 1
]Aggiornando ora la chiamata a drawArrays per disegnare 6 vertici otteniamo il nostro quadrato
gl.drawArrays(gl.TRIANGLES, 0, 6)Vogliamo quindi ridurre la dimensione di vertices e introdurre un index buffer:
export function setupWhatToDraw() {
const vertices = [
// 1st vertex
-1, -1, 1, 0, 0,
// 2nd vertex
1, -1, 0, 1, 0,
// 3rd vertex
-1, 1, 0, 0, 1,
// 4th vertex
1, 1, 1, 1, 1
]
const typedVertices = new Float32Array(vertices)
const buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, typedVertices, gl.STATIC_DRAW)
const indices = [
// 1st triangle
0, 1, 2,
// 2nd triangle
2, 1, 3
]
const typedIndices = new Uint16Array(indices)
const ibo = gl.createBuffer()
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, typedIndices, gl.STATIC_DRAW)
}Notare l’importanza di Uint: gli indici devo obbligatoriamente essere unsigned int. In questo caso abbiamo specificato 16 bit, quindi unsigned short, perché WebGL 1 di default non supporta unsigned int a 32 bit per gli indici. Vi è un estensione (di cui però bisogna verificare la disponibilità per ogni dispositivo) che permette di utilizzare unsigned int a 32 bit:
const ext = gl.getExtension('OES_element_index_uint')
if (!ext) {
// il dispositivo non supporta uint per gli indici!!!
}Aggiorniamo infine la funzione draw per utilizzare drawElements anziché drawArrays:
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0)Come per drawArrays è richiesto il tipo di primitiva (TRIANGLES), il numero di primitive da renderizzare (6), e l’offset (0), ma è anche richiesto il tipo utilizzato per gli indici (UNSIGNED_SHORT nel nostro caso)