Sign in to follow this  

Draw mixed geometry

This topic is 412 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi All

 

I'm looking for more appropriate API calls for:

 

- model can have different faces (with 1, 2, 3, or 4 vertices)

- model can have different faces' colors

- model can have different materials assigned by user to arbitrary set of polygons

 

Now I just call glDrawElements for each part/piece of drawing and sometimes it becomes much slower. Please suggest better solution(s)

 

Thank you

Share this post


Link to post
Share on other sites

dont call gldrawelements every face you draw

 

you need to draw the same set of polygons only onvce if you can GL_TRIANGLE_STRIP is cool.

 

 

either way you prepare the scene as sending whole buffer to gpu first, then you draw,

Share this post


Link to post
Share on other sites
dont call gldrawelements every face you draw

Not every, example:

 

there are, say, 2 blue triangles, their indices start from 0. And there are another 3 blue triangles at indices 100. Now I use 2 calls glDrawElements to draw first 2 then second 3. How can I draw them with one call?

 

Thx

Edited by Tommato

Share this post


Link to post
Share on other sites

there are, say, 2 blue triangles, their indices start from 0. And there are another 3 blue triangles at indices 100. Now I use 2 calls glDrawElements to draw first 2 then second 3. How can I draw them with one call?
Put the indices next to each other in the index buffer, then you can make one call.

Share this post


Link to post
Share on other sites

Yes, set up the index buffer so that the indices are 0|1|2|3|4|5|100|101|102|103|etc then issue a single glDrawElements call.  There's absolutely nothing in the spec for glDrawElements that forces the values to be consecutive.

 

glDrawElements with GL_TRIANGLES is infinitely more useful than glDrawElements with GL_TRIANGLE_STRIP.  Only worry about strips if you're on hardware that requires them; otherwise strips are 1998 technology.  Every primitive type (strip/fan/quad/poly/etc) can be expressed in terms of triangles and indices; it may not satisfy strict OpenGL invariance rules, but so long as you don't mix types in a multipass renderer you'll be OK.  From there it should be obvious that glDrawElements with GL_TRIANGLES can be used to concatenate primitives of different types so that multiple draw calls become single.

Share this post


Link to post
Share on other sites

What you may looking for is the restart-index value. It marks the beginning of a new primitive in a index list.

 

core since 3.1 (And even before that with GL_NV_primitive_restart, but with a different API I think)

glEnable(GL_PRIMITIVE_RESTART);

glPrimitiveRestartIndex(X); //for easy of use and consistency I would just use the highest value of the index type, e.g. 0xFFFF or 0xFFFFFFFF (Don't use a byte index type! They are very slow on modern hardware)

 

Or with ARB_ES3_compatibility (Core since 4.3)

glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); //this always uses the highest value of the index type

 

So with a GL_UNSIGNED_SHORT index with this values:

 

0|1|2|3|4|5|65535|100|101|102|103

 

You get this two index primitives:

 

0|1|2|3|4|5

100|101|102|103

Share this post


Link to post
Share on other sites

Put the indices next to each other in the index buffer, then you can make one call.
In my case it doesn't work well. I can't change topology as it's better for me/drawing, e.g. p?lygons should follow in their original order, they are used in many ways besides drawing. Creating another one indices (just for drawing) is often counter-productive because it can't be done once for example when a new geometry arrives at every frame

 

Yes, set up the index buffer so that the indices are 0|1|2|3|4|5|100|101|102|103|etc then issue a single glDrawElements call. There's absolutely nothing in the spec for glDrawElements that forces the values to be consecutive.
I meant "face offset" (not "vertex index"). It looks like

 

v0|v1v|2|v3|v4|v5|..............|vx|vx|vx|

Share this post


Link to post
Share on other sites

I've rebuilt my code to use glMultiDrawElements. This call looks appropriated but I see no any speedup - same fps as with multiply glDrawElements ;-( It was unexpected, I hoped one call should be faster than hundreds (sometimes even thousands). 

 

So now I make a copy of "indices" and sort it, then pass the copy to VBO. It's twice faster although works well for static geometry only

 

Thx

Share this post


Link to post
Share on other sites
I've rebuilt my code to use glMultiDrawElements. This call looks appropriated but I see no any speedup - same fps as with multiply glDrawElements ;-( It was unexpected, I hoped one call should be faster than hundreds (sometimes even thousands). 

 

I heard some IHV's drivers implement Multidraw using multiple draw calls, so maybe thats why you saw no speedup.

The other thing is how big are the clusters of geometry you are rendering, you might be running into occupancy issues.

 

edit - Also it should be mentioned that reducing draw call count is a CPU optimization, and not changing state between draw calls supposedly gives you more draw calls per frame to work with.

Edited by Infinisearch

Share this post


Link to post
Share on other sites

The other thing is how big are the clusters of geometry you are rendering, you might be running into occupancy issues.
I'm testing with user's project 4.6 millions of polys, approx same vertices. 130 objects, a half of them have intensive triangles/quads mix.

 

I heard some IHV's drivers implement Multidraw using multiple draw calls
Is there a way(s) to transform this "some" into something more concrete that I could use in runtime? For example (pseudocode)

 

if (SomeTest())

    // use glMiltiDrawElements

else

 // rebuild indices

 

Th?

Share this post


Link to post
Share on other sites

I'm testing with user's project 4.6 millions of polys, approx same vertices. 130 objects, a half of them have intensive triangles/quads mix.

Thats not what i meant, I mean the clusters as in first draw 20 triangles, then another 60, then another... and so on.  If the clusters are too small you're not using the gpu as efficiently as possible leaving performance on the table.

 

Is there a way(s) to transform this "some" into something more concrete that I could use in runtime? For example (pseudocode)   if (SomeTest())     // use glMiltiDrawElements else  // rebuild indices   Th?

 I don't know/remember the specifics of which IHV does what and moreover I don't know if it depends on hardware generation.  So basically I can't help you here, besides the dynamic index buffer is a good solution which also solves the occupancy issue.

Share this post


Link to post
Share on other sites

This topic is 412 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this