I'm kinda new to WebGL in general, I've started to make some batching experiences on primitives (just drying a bunch of rectangles by using a combination of two triangles repeatedly).
I've started by implementing Direct Drawing that draws a rectangle (TRIANGLE_STRIP like) as soon it is requested:
var colorArr = new Float32Array(<color values here>);
var vertices = [
rectangle.x, rectangle.y, 0.0, // TOP LEFT
rectangle.x, rectangle.y + rectangle.height, 0.0, // BOTTOM LEFT
rectangle.x + rectangle.width, rectangle.y, 0.0, // TOP RIGHT
rectangle.x + rectangle.width, rectangle.y + rectangle.height, 0.0 // BOTTOM RIGHT
];
_this.game.getShaderManager().useShader(_this.primitiveShader);
// position buffer
gl.bindBuffer(gl.ARRAY_BUFFER, _this.vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.enableVertexAttribArray(_this.primitiveShader.attributes.aVertexPosition);
gl.vertexAttribPointer(_this.primitiveShader.attributes.aVertexPosition, 3, _this.gl.FLOAT, false, 0, 0);
// color buffer
gl.bindBuffer(gl.ARRAY_BUFFER, _this.colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, colorArr, gl.STATIC_DRAW);
gl.enableVertexAttribArray(_this.primitiveShader.attributes.aColor);
gl.vertexAttribPointer(_this.primitiveShader.attributes.aColor, 4, _this.gl.FLOAT, false, 0, 0);
// set uniforms
gl.uniformMatrix4fv(_this.primitiveShader.uniforms.uMatrix._location, false, _this.game.getActiveCamera().getMatrix());
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
But then I wanted to go one step further and I've implemented a simple batcher (mostly by common sense, which is probably where I started wrong).
Basically the batcher does the same thing has the code above, the difference is that I concat all the vertex and color data into a big array of data and then draw everything:
// position buffer
gl.bindBuffer(gl.ARRAY_BUFFER, _this.vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(_this.rectangleVertexData), gl.STATIC_DRAW);
gl.enableVertexAttribArray(_this.primitiveShader.attributes.aVertexPosition);
gl.vertexAttribPointer(_this.primitiveShader.attributes.aVertexPosition, 3, _this.gl.FLOAT, false, 0, 0);
// color buffer
gl.bindBuffer(gl.ARRAY_BUFFER, _this.colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(_this.rectangleColorData), gl.STATIC_DRAW);
gl.enableVertexAttribArray(_this.primitiveShader.attributes.aColor);
gl.vertexAttribPointer(_this.primitiveShader.attributes.aColor, 4, _this.gl.FLOAT, false, 0, 0);
// set uniforms
gl.uniformMatrix4fv(_this.primitiveShader.uniforms.uMatrix._location, false, cameraMatrix);
gl.drawArrays(gl.TRIANGLES, 0, 6 * _this.rectangleCount);
For my surprise, the second attempt is getting worst results. Using the first approach I get a solid 60 fps on a 320 rectangles drawing and on the second only 40 fps.
So, my questions specifically are:
- Why is the batcher having worst results?
- What can be optimized to have an optimal drawing performance?
Best Regards.