1
\$\begingroup\$

I'm making an Android app and I need to draw some polygons using OpenGL ES. I'm able to render them but I'm disappointed with performance. I updated the code to use VBO but I didn't notice any improvement. I want to render at 60 frames per second (16 ms per frame).

I have a test project where I render several triangles on the screen. When I render 1000 triangles it takes about 20 ms per frame (depending on the device).

I want to keep the rendering under 10 ms because I need the rest (6 ms) to perform other calculations (e.g. update positions, detect collisions, etc.).

Here is the code where I render a triangle:

public void render(int positionLocation, int colorLocation)
{
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.bufferIndex);
    GLES20.glVertexAttribPointer(positionLocation, Polygon.POSITION_COMPONENT_COUNT, GLES20.GL_FLOAT, false, Polygon.STRIDE, 0);
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

    GLES20.glUniform4f(colorLocation, this.red, this.green, this.blue, this.alpha);
    GLES20.glDrawArrays(this.mode, 0, this.length);
}

https://github.com/mauriciotogneri/test/blob/master/src/com/testopengl/Polygon.java#L51-66

Here is the code where iterate over the triangles:

private void renderTriangles()
{
    long start = System.nanoTime();

    for (int i = 0; i < COLUMNS; i++)
    {
        for (int j = 0; j < ROWS; j++)
        {
            float x = (i * TRIANGLE_SIZE) + (TRIANGLE_SIZE / 2);
            float y = (j * TRIANGLE_SIZE) + (TRIANGLE_SIZE / 2);

            moveTo(x, y);

            this.triangles[i][j].render(this.positionLocation, this.colorLocation);
        }
    }

    long stop = System.nanoTime();

    this.totalTime += stop - start;
    this.totalFrames++;

    Log.d("TEST", (this.totalTime / this.totalFrames) / 1000000 + " ms");
}

https://github.com/mauriciotogneri/test/blob/master/src/com/testopengl/MapRenderer.java#L117-139

(Change the value of NUMBER_OF_TRIANGLES to display more triangles)

For what I understand, the method GLES20.glDrawArrays(...) takes too much time if I need to call it 1000 times per frame (one per triangle).

Is there another way to render several polygons that doesn't take too much time?

Notes:

  • In the example all the triangles have a fixed position on the screen but in the real scenario they will move around
  • In the example I assign a random color to each triangle but in the real scenario each of them will have a fixed color
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

It's slow because you're sending a drawcall for every polygon. And each drawcall means communication with the drivers and the GPU, which is slow (I don't know exactly how it is the OpenGL ES. But on Desktops your target is to minimize the amount of drawcalls).

And that is, where vbo's come in. A Vbo stores all the vertices of an object in a buffer. If you do so, you can render this object with only one drawcall. This means your target should be to pack as many polygons as possible into one vbo.

You are passing a vertex array to the vbo by calling glBufferData. Here is some more detailed explanation: https://stackoverflow.com/questions/5091570/most-basic-working-vbo-example

If you need to render each polygon seperate, you can search for instanced rendering. By using this technique you can render alot of objects (which have the same geometry) and still use just one drawcall.

\$\endgroup\$
4
  • \$\begingroup\$ Thanks for the answer. However, using VBOs is not a problem. I'm already applying it in the example project. But like I said, using VBOs doesn't seem to improve performance. For what I read, Android uses shared memory with the GPU and that could explain why there is no speed difference. I'm afraid I won't be able to use instanced rendering since each polygon will have a different geometry. \$\endgroup\$ Commented May 6, 2015 at 21:27
  • \$\begingroup\$ The number of draw calls is the problem. even modern game engines try to minimize them as good as possible. And thousand draw calls are definitly to much for a mobile device. So you need to reduce them. Here are some links about it: infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0555c/… developer.apple.com/library/ios/documentation/3DDrawing/… stackoverflow.com/questions/4853856/… indiedevspot.azurewebsites.net/2014/03/12/… \$\endgroup\$
    – Tobias B
    Commented May 6, 2015 at 21:48
  • \$\begingroup\$ Clearly the number of draw calls is the problem but I don't know how to reduce it in my case. All polygons have different shapes, colors and positions (and they are moving). I'm surprised that even in modern devices I takes 10 ms to render 500 triangles. It's true that they are mobile devices but honestly 500 triangles is not that much. I was expecting a much better performance in such a simple scenario. \$\endgroup\$ Commented May 6, 2015 at 22:27
  • \$\begingroup\$ It is probably not fast, but you could try to generate one large (stream draw) vbo that contains all your Polygons and update it every frame. But this approach could be even slower. Or you could try to update their positions on the gpu, but this could get more complicated \$\endgroup\$
    – Tobias B
    Commented May 6, 2015 at 22:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .