Jump to content

WebGL Primitive Batching unexpected performance


RedHawk96
 Share

Recommended Posts

Hello,

I'm kinda new to WebGL in general, I've started to make some batching experiences on primitives (just drawing 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?
  3. Isn't it weird I'm having so low FPS with so few triangles?

Best Regards.

Link to comment
Share on other sites

Thanks a lot, that was the exact kind of information I was looking for. I improved several parts and now I'm getting much better results!

Basically changed all the positions/scaling to be made using matrices and used a base rectangle structure:

 

	var rectangleData = [
				0.0, 1.0, 0.0,                                              // TOP LEFT
				0.0, 0.0, 0.0,                                              // BOTTOM LEFT
				1.0, 0.0, 0.0,                                              // BOTTOM RIGHT

				1.0, 1.0, 0.0,                                              // TOP RIGHT
				0.0, 1.0, 0.0,                                              // TOP LEFT
				1.0, 0.0, 0.0                                               // BOTTOM RIGHT
			];


Besides that, I've modified to color attribute, which is now an uniform, and other particularities of the rendering process as said in the article.

Link to comment
Share on other sites

  • 5 weeks later...

Are you creating 2 new float32arrays on every frame? You should reuse them as much as possible. Create them someplace outside the scope of your drawing call, and reference them over and over again. Creating new float32arrays is really slow, and surely killing your memory load.

Link to comment
Share on other sites

16 hours ago, ericjbasti said:

Are you creating 2 new float32arrays on every frame? You should reuse them as much as possible. Create them someplace outside the scope of your drawing call, and reference them over and over again. Creating new float32arrays is really slow, and surely killing your memory load.

That's one of the changes I've made later on, it helped to improve the performance too :)

Thanks! 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...