PDA

View Full Version : Custom mesh performance tips



milos1290
09-30-2015, 10:17 AM
Hi everyone,
I have a question and i would also like to hear some tips and trick regarding this problem.



I'm currently generating a 2d mesh and drawing it as triangle strip.

It looks something like this

2126

and i have two arrays that i populate with data


float [] vertices;
float [] uv;


Code drawing this looks something like this



glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferVertices->getVBO());
glVertexAttribPointer(VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(Vec2), 0);

glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferTexCoords->getVBO());
glVertexAttribPointer(VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(Tex2F), 0);

glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei) _vertexBufferVertices->getVertexNumber());

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);


I was wondering if this is a good solution, should i use indices also ? How can i optimize more ?

malexander
09-30-2015, 10:40 AM
If you're using triangle strips, you probably don't need indexed rendering unless those strips are part of a larger connected mesh (in which case indexed drawing with GL_TRIANGLES is probably easier to set up).

You might consider reducing the uvs to a more packed format than float32, such as float16. But without knowing what the bottleneck might be in your application, it's a bit premature to suggest much.

milos1290
09-30-2015, 10:43 AM
If you're using triangle strips, you probably don't need indexed rendering unless those strips are part of a larger connected mesh (in which case indexed drawing with GL_TRIANGLES is probably easier to set up).

You might consider reducing the uvs to a more packed format than float32, such as float16. But without knowing what the bottleneck might be in your application, it's a bit premature to suggest much.

The mesh has around 200-300 vertices. I'm using a single texture that tiles. I'm testing it on various android and ios devices it works good. But on some older devices fps is low.

Alfonse Reinheart
09-30-2015, 10:50 AM
I'm using a single texture that tiles.

See, now you're not talking about rendering a strip; you're talking about rendering a tilemap. That's a rather different thing.

In a tilemap, each individual tile needs to have texture coordinates that are different from the neighboring tiles. So even though they share positions, they need unique texture coordinates. So there is no vertex sharing between tiles.

So you're not going to be getting much out of a strip this way.

Unless I'm misinterpreting your "mesh" being a tilemap.

malexander
09-30-2015, 10:52 AM
Ok. Try fp16 or normalized-int16 formats for the vertex arrays, depending on your coord system. If vertices is bounded by [0,1], you can use norm-int16 for vertices; fp16 can be used for 2D values on a high-res screen without much precision loss.

You can also try interleaving vertices and uv in a single buffer, rather than using 2 buffers. Also, try using indexed triangles instead of a triangle strip, see if that makes any difference on older devices.

Edit: Also try running a trivial fragment shader to ensure it's not fragment-shading limited before optimizing the geometry.

milos1290
09-30-2015, 11:08 AM
Sorry if i explained wrong,

here is how it looks

2128

It's not a classic tilemap. I'm spawning meshes after traveled distance to make an endless world.

I've just tried with interleaved array, so i'm gonna profile now.

milos1290
09-30-2015, 01:09 PM
I would also like to try to use indices to try out but i'm unsure how to map it. Can anyone explain a bit ?

This is how my vertices looks like in array both position and texture coordinates.



0-----2-----4
| /| /|
| / | / |
| / | / |
1-----3-----5


[(0,0), (1,1), (2,2), (3,3), (4,4), (5,5)]

GClements
09-30-2015, 05:07 PM
See, now you're not talking about rendering a strip; you're talking about rendering a tilemap.
I don't think he is. Saying that a texture "tiles" means that you can set the wrap mode to GL_REPEAT without having a visible seam between repetitions.

GClements
09-30-2015, 05:20 PM
I would also like to try to use indices to try out but i'm unsure how to map it. Can anyone explain a bit ?
If the vertices are ordered for rendering with glDrawArrays(), then you'd get the same result when using glDrawElements() with an index array of {0,1,2,3,....}.

But for drawing a continuous track, you'd be better off ordering the vertices like so:


0 --- 1 --- 2 --- 3
| | | |
4 --- 5 --- 6 --- 7
| | | |
8 --- 9 ---10 ---11
| | | |
12---13 ---14 ---15
| | | |

then using indices: {{0,4,1,5,2,6,3,7}, {4,8,5,9,6,10,7,11}, {8,12,9,13,10,14,11,15}., ...}.

In the simplest case, each row would need one call to glDrawElements(). You can avoid that by using primitive restarting (with glEnable(GL_PRIMITIVE_RESTART) or glEnable( GL_PRIMITIVE_RESTART_FIXED_INDEX)) or by using glMultiDrawElements().

milos1290
10-01-2015, 03:09 AM
If the vertices are ordered for rendering with glDrawArrays(), then you'd get the same result when using glDrawElements() with an index array of {0,1,2,3,....}.

But for drawing a continuous track, you'd be better off ordering the vertices like so:


0 --- 1 --- 2 --- 3
| | | |
4 --- 5 --- 6 --- 7
| | | |
8 --- 9 ---10 ---11
| | | |
12---13 ---14 ---15
| | | |

then using indices: {{0,4,1,5,2,6,3,7}, {4,8,5,9,6,10,7,11}, {8,12,9,13,10,14,11,15}., ...}.

In the simplest case, each row would need one call to glDrawElements(). You can avoid that by using primitive restarting (with glEnable(GL_PRIMITIVE_RESTART) or glEnable( GL_PRIMITIVE_RESTART_FIXED_INDEX)) or by using glMultiDrawElements().


But i only have one row like in a image above. I've implemented interleaved array and VAO, and i've noticed improvements when profiling. Shame that it doesn't work properly on some of the Android devices.