6
votes

i have 170 objects to draw, each is build from 312 vertexes. I have one object and i am drawing it 170 times with diffrent martixes, i have figured out that i dont need to call some functions if i draw them one by one so i call them only at the begining, this gives me about 5fps, i am using non indexed triangles with drawArrays.

if(!started)
{
    glUseProgram( __programObject );
    glEnableVertexAttribArray(attPosition);
    glVertexAttribPointer(attPosition, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), vVertices);//3*sizeof(float)
    glEnableVertexAttribArray(attNormals);
    glVertexAttribPointer(attNormals, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), vNormals);//3*sizeof(float)
}

Is there any way to make it faster under es 2.0 ? i am getting about 23fps on sgx 540, lowering vertex detail to 36 per object does not increase frame rate, there are about 10fps in matrix calculations(scale, multiply, translate, transponse, invert) but they are made on cpu and i dont think that moving them into shaders is good idea. I know that most time is consumed on passing uniforms each time. I know that there is a way to instantiate objects and pass uniforms and draw it in one call but i cant find any tutorial describing it, do you know where i can find it?

2
Using a single VBO with interleaved data is supposed to help significantly. Some GPUs will also prefer a stride of 16.tc.
Sadly, gl_ext_draw_instanced and gl_ext_instanced_arrays are not available on the SGX540, only on the SGX543, 544, 554 (what's known as the 5XT series as distinct from the 5 series).Engineer

2 Answers

3
votes

try to inculde normals and vertices in one array like this:

sqTex.getVertexBuffer().position(sqTex.VERT_OFFSET);
GLES20.glVertexAttribPointer(
                                GLES20.glGetAttribLocation(programTextured, "aPosition"), 3,
                                GLES20.GL_FLOAT, false, 5 * 4, sqTex.getVertexBuffer());
GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(programTextured, "aPosition"));

sqTex.getVertexBuffer().position(sqTex.TEXT_OFFSET);
GLES20.glVertexAttribPointer(
                                GLES20.glGetAttribLocation(programTextured, "aTextureCoord"), 2,
                                GLES20.GL_FLOAT, false, 5 * 4, sqTex.getVertexBuffer());
GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(programTextured, "aTextureCoord"));

In this example i have one array for vertices and tex coords

quot from OpenGL ES 2.0 Programming Guide:

 How to store different attributes of a vertex
We described the two most common ways of storing vertex attributes—
array of structures and structure of arrays. The question to ask is which allocation
method would be the most efficient for OpenGL ES 2.0 hardware
implementations. The answer is array of structures. The reason is that the
attribute data for each vertex can be read in sequential fashion and so will
most likely result in an efficient memory access pattern. A disadvantage of
using array of structures is when an application wants to modify specific
attributes. If a subset of vertex attribute data needs to be modified (e.g., texture
coordinates), this will result in strided updates to the vertex buffer.
When vertex buffer is supplied as a buffer object, the entire vertex attribute
buffer will need to be reloaded. One can avoid this inefficiency by storing
vertex attributes that are dynamic in nature in a separate buffer.

That book also has examples of using in this manner

1
votes

You can try passing your per-instance data through attributes instead of uniforms. It helped sometimes on desktop OpenGL.

So, vertex shader will look like this:

attribute vec3 position;
attribute mat4 proj_view_matrix;
void main()
{
    gl_Position = proj_view_matrix * position;
}

And rendering code will look like this:

glUseProgram( programObject );
glEnableVertexAttribArray(attPosition);
glVertexAttribPointer(attPosition, ..., pPositions);
glDisableVertexAttribArray(attProjViewMatrix+0);
glDisableVertexAttribArray(attProjViewMatrix+1);
glDisableVertexAttribArray(attProjViewMatrix+2);
glDisableVertexAttribArray(attProjViewMatrix+3);

foreach( instance )
{
    glVertexAttrib4fv(attProjViewMatrix+0, instance.proj_view_matrix.column0);
    glVertexAttrib4fv(attProjViewMatrix+1, instance.proj_view_matrix.column1);
    glVertexAttrib4fv(attProjViewMatrix+2, instance.proj_view_matrix.column2);
    glVertexAttrib4fv(attProjViewMatrix+3, instance.proj_view_matrix.column3);
    glDrawArrays( ... );
}