1
\$\begingroup\$

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:

  1. Why is the batcher having worst results?
  2. What can be optimized to have an optimal drawing performance?

Best Regards.

\$\endgroup\$
  • \$\begingroup\$ You can improve performance some by using gl.bufferSubData() instead of bufferData() to replace the vertices each time. It uses the same buffer without reallocating. \$\endgroup\$ – david van brink Apr 30 '16 at 18:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.