WebGL Month. Day 6. Indexed buffer
Andrei Lesnitsky
Posted on July 6, 2019
Day 6. Index buffer
This is a series of blog posts related to WebGL. New post will be available every day
Join mailing list to get new posts right to your inbox
Built with
Hey πWelcome back to WebGL month. Yesterday we've learned how to use interleaved buffers. However our buffer contains a lot of duplicate data, because some polygons share the same vertices
Let's get back to a simple example of rectangle
π src/webgl-hello-world.js
[128, 0.0, 128, 255], // purple
];
- const triangles = createHexagon(canvas.width / 2, canvas.height / 2, canvas.height / 2, 7);
+ const triangles = createRect(0, 0, canvas.height, canvas.height);
function createHexagon(centerX, centerY, radius, segmentsCount) {
const vertexData = [];
and fill it only with unique vertex coordinates
π src/webgl-hello-world.js
const triangles = createRect(0, 0, canvas.height, canvas.height);
+ function createRect(top, left, width, height) {
+ return [
+ left, top, // x1 y1
+ left + width, top, // x2 y2
+ left, top + height, // x3 y3
+ left + width, top + height, // x4 y4
+ ];
+ }
+
function createHexagon(centerX, centerY, radius, segmentsCount) {
const vertexData = [];
const segmentAngle = Math.PI * 2 / (segmentsCount - 1);
Let's also disable color attribute for now
π src/webgl-hello-world.js
const attributeSize = 2;
const type = gl.FLOAT;
const nomralized = false;
- const stride = 24;
+ const stride = 0;
const offset = 0;
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, attributeSize, type, nomralized, stride, offset);
- gl.enableVertexAttribArray(colorLocation);
- gl.vertexAttribPointer(colorLocation, 4, type, nomralized, stride, 8);
+ // gl.enableVertexAttribArray(colorLocation);
+ // gl.vertexAttribPointer(colorLocation, 4, type, nomralized, stride, 8);
gl.drawArrays(gl.TRIANGLES, 0, vertexData.length / 6);
Ok, so our buffer contains 4 vertices, but how does webgl render 2 triangles with only 4 vertices?
THere's a special type of buffer which can specify how to fetch data from vertex buffer and build primitives (in our case triangles)
This buffer is called index buffer
and it contains indices of vertex data chunks in vertex buffer.
So we need to specify indices of triangle vertices.
π src/webgl-hello-world.js
const vertexData = new Float32Array(triangles);
const vertexBuffer = gl.createBuffer(gl.ARRAY_BUFFER);
+ const indexBuffer = gl.createBuffer(gl.ARRAY_BUFFER);
+
+ const indexData = new Uint6Array([
+ 0, 1, 2, // first triangle
+ 1, 2, 3, // second trianlge
+ ]);
+
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
gl.lineWidth(10);
Next step β upload data to a WebGL buffer.
To tell GPU that we're using index buffer
we need to pass gl.ELEMENT_ARRAY_BUFFER
as a first argument of gl.bindBuffer
and gl.bufferData
π src/webgl-hello-world.js
1, 2, 3, // second trianlge
]);
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW);
+
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
gl.lineWidth(10);
And the final step: to render indexed vertices we need to call different method β drawElements
instead of drawArrays
π src/webgl-hello-world.js
const indexBuffer = gl.createBuffer(gl.ARRAY_BUFFER);
- const indexData = new Uint6Array([
+ const indexData = new Uint8Array([
0, 1, 2, // first triangle
1, 2, 3, // second trianlge
]);
// gl.enableVertexAttribArray(colorLocation);
// gl.vertexAttribPointer(colorLocation, 4, type, nomralized, stride, 8);
- gl.drawArrays(gl.TRIANGLES, 0, vertexData.length / 6);
+ gl.drawElements(gl.TRIANGLES, indexData.length, gl.UNSIGNED_BYTE, 0);
Wait, why is nothing rendered?
The reason is that we've disabled color attribute, so it got filled with zeros. (0, 0, 0, 0) β transparent black.
Let's fix that
π src/webgl-hello-world.js
void main() {
gl_FragColor = vColor / 255.0;
+ gl_FragColor.a = 1.0;
}
`;
Conclusion
We now know how to use index buffer to eliminate number of vertices we need to upload to gpu.
Rectangle example is very simple (only 2 vertices are duplicated), on the other hand this is 33%, so on a larger amount of data being rendered this might be quite a performance improvement, especially if you update vertex data frequently and reupload buffer contents
Homework
Render n-gon using index buffer
See you tomorrow π
This is a series of blog posts related to WebGL. New post will be available every day
Join mailing list to get new posts right to your inbox
Built with
Posted on July 6, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.