PDA

View Full Version : What's faster : 1 quad or 2 triangles ???



Morglum
01-09-2002, 01:07 AM
Hi !

On geforce 2&3 boards, suppose I've got 4 vertices A, B, C, D, lying on the same plane. What's faster to render : the quad ABCD or the two triangles ABC and ACD ? And is the same true about quad strips and triangle strips ?

Thanks in advance !
Morglum

jide
01-09-2002, 01:26 AM
it depends.

anyway, if you do the same way for triangle and quad, quad would be better i think.

but it exists strip and fan which are special ways to avoid redundant vertices.
So drawing strip/fan triangles would be better than drawing simple quad... you can do strip for quad.
Your quads must be convexe quads.
Triangles are most used than quads (which grow up then).

So, do strip with quad would be same way as doing strip with triangles.
Care, too, of the number of vertices. If your quads models's got more vertices, it may be less powerful.

Morglum
01-09-2002, 01:35 AM
Thanks jide ! I'm writing an ASE loader and all quads are converted into triangles in the ASE file. So I wondered whether it would be worth writing some code to detect when two tris are part of one convex quad, and then convert these two tris into one quad.

Rob The Bloke
01-09-2002, 01:50 AM
also bear in mind that by treating all poly's as triangles you can draw all of them in one go (say vertex arrays) without having to deal with seperate polygon types which will save you a lot of time....

Morglum
01-09-2002, 02:00 AM
Yes, it's true, but I planned to split my original vertex array into strips and fans. So I would have many vertex arrays anyway. I hope to improve rendering speed by this, but I might be mistaken... what do you think ?

jide
01-09-2002, 04:26 AM
from Rob The Bloke:
also bear in mind that by treating all poly's as triangles you can draw all of them in one go (say vertex arrays) without having to deal with seperate polygon types which will save you a lot of time....

i think sometime, quads must be converted into triangles. But you can do as well vertex arrays with triangles, or quads by using glDraw*(); The first parameter is the parameter you give generally to glBegin();

As far, i got an Ase loader (i've taken it from an existed program), and i failed on loading all the objects. It only load the bigger object and the last (so i have strange things). I think it's due to that i didn't separate the different objects. That make me tired to think again about it. So, i may use another opened, free ASE loader (when i'll find it).

Morglum
01-09-2002, 04:36 AM
I can give you mine, if you don't find anything better, although it's not finished and it handles memory very unefficiently.

Morglum

mikael_aronsson
01-09-2002, 05:41 AM
Hi !

I think most OpenGL implementation breaks down the quad to two triangles anyway in the end so you would not gain much from it compared to a two triangle strip for example.

Compared to GL_TRIANGLES you would have two less vertices to send down the pipeline which might be worth the trouble.

Mikael

jide
01-09-2002, 05:50 AM
morglum,
let's see, why not !

mickael, that's may be possible. Most of graphic cards only do triangles that are most sure to draw than quads which maybe difficult to delimitate, and fill. Then, that's what i think !

Tom Nuydens
01-09-2002, 06:01 AM
I already pointed this out in another thread not so long ago, but I'll repeat it here: I would advise against using quads.

Even if sending a quad is faster than sending two triangles (which I'll believe when I see it), you can get a similar effect by using triangle strips.

By sticking with triangles, you also avoid a lot of potential problems down the road. You may encounter models with concave quads in them, for example, or you may get Z-fighting when doing multipass because the quad's triangulation changes for some reason.

-- Tom

LordKronos
01-09-2002, 06:44 AM
Originally posted by Tom Nuydens:
I would advise against using quads.

Well, the reasons you give are all pretty sound, but I would finish your statement with "unless you have a very good reason". In some of the stuff I am working on right now, a large portion of my scene consists of quads (always perfectly flat), but a majority of it is not strippable (either as quads or tris) or results only in several relatively small strips. Given the chioce of 1 big quad list, 1 bigger tri list (50% more verts sent), or many small tri stips (roughly the same # of verts as quad list, but split over many more draw calls), the quad list ends up being the best performance.

However, on this same topic, it was you Tom that helped me out with just such a problem with quad triangulation almost a year ago (http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/002716.html). So your advice/warnings do make sense to me.

Morglum
01-09-2002, 08:08 AM
Ok, thank you for your advices ! I think that i'll stick to triangles, following mikael and tom. But this leads to another question : My vertex arrays are already very small (say, 10 triangles each), and they are not convertible into strips. However, I could split them into smaller strippable arrays. Is it worth it ?

MikeC
01-09-2002, 11:13 AM
Use quads when if each quad doesn't share any verts with the next, e.g. for billboarded particles. This is more efficient; 4 verts per quad instead of 6. In any context where you can use stripping or fanning, stick to triangles.


Originally posted by Morglum:
Yes, it's true, but I planned to split my original vertex array into strips and fans. So I would have many vertex arrays anyway. I hope to improve rendering speed by this, but I might be mistaken... what do you think ?

I think you're getting confused. You can render any number of strips and/or fans from one vertex array, and if the strips or fans border on each other (sharing vertices) you'll probably be wasting memory & bandwidth if you *don't* do this.

HTH
Mike

Alain
01-09-2002, 12:51 PM
If you have a flat quad ABCD, then it's the same as two triangles ABD and DBC. And if you put them in a triangle strip, then you'll have exactly the same number of vertices to send: 4, and not 6.
Note that if your quad vertices are in the order A,B,C,D counter-clockwise, then the equivalent triangle strip needs to be given vertices in the order A,B,D,C.
I remember one guy from nVIDIA (was it Matt ?) telling us that in the end all was splitted down into triangles anyway, so I would suggest using triangle strips in this case.

Qwylli
01-09-2002, 01:56 PM
I think it's faster drawing one quad instead of a triangle strip.
If there would be no advantages to use quads instead of triangles, they would not support them I think.
Now, the question I would like someone to answer is : How to build a quad fan? http://www.opengl.org/discussion_boards/ubb/biggrin.gif http://www.opengl.org/discussion_boards/ubb/biggrin.gif

kistompika
01-09-2002, 02:10 PM
Rendering a quad is not necessarily faster, but is never slower. Most of OpenGL implementations (&graphics hardware) simply tesselate quads to two triangles. This has the advantage that you pass only 4 vertices to the GL instead of 6, which you would do if you rendered two triangles instead. With this you can spare data transfer through the AGP bus, which can lead to performance gain in case of complex geometry.

There is no possibility to explicitly define a quad strip in GL, but there is no need of that. When you pass a triangle fan(or strip) to the GL you define each vertex only once, which is optimal.

kistompika

Tom Nuydens
01-09-2002, 03:27 PM
LordKronos, you say that your geometry consists mostly of unstrippable flat surfaces -- I can relate to that.

However, you should be optimizing your data for the vertex cache anyway. Hence, using a quad will result in four vertices being transformed, whereas using triangles will result in four vertices being transformed and another two being pulled from the cache. In this case, I would expect the performance difference to be rather small? Unless of course it's the bandwidth required for transferring the extra indices that makes the difference.

Mind you, I'm not saying that quads aren't faster than triangles, because I honestly wouldn't know -- I've never tried! Can you perhaps post some benchmark figures illustrating the speed difference you see between quads and triangles in your app?

-- Tom

Morglum
01-10-2002, 02:48 AM
Originally posted by MikeC:

I think you're getting confused. You can render any number of strips and/or fans from one vertex array, and if the strips or fans border on each other (sharing vertices) you'll probably be wasting memory & bandwidth if you *don't* do this.

Yes, of course you're right. So I would only have more than one call to glDrawElements. But there remains my question : does it make sense to build strips having 3 triangles each ?

gaby
01-10-2002, 02:56 AM
Yes, in most case, quad is faster than two alone triangles : it's becauss the pipeline transform 4 vertices, not 6. In other words, for a quad ABCD, first the ABC vertices are transformed, flagged and lit, then is drawen a ABC triangle, and next, only D is send to the pipeline, so you have only 4 T&L operation. If you do that with 2 triangles (ABC and BCD), you'll have 6 T&L operations : that's why it's slower. But if you do that with a tristrip, perf migh been similar than drawing a quad.

Gaby

Eric
01-10-2002, 03:50 AM
Originally posted by gaby:
Yes, in most case, quad is faster than two alone triangles : it's becauss the pipeline transform 4 vertices, not 6.


Originally posted by kistompika:
This has the advantage that you pass only 4 vertices to the GL instead of 6, which you would do if you rendered two triangles instead.

I agree with both of you: using GL_TRIANGLES should be slower than GL_QUADS if you are trying to draw a quad.

But am I the only one seeing that rendering a quad using GL_TRIANGLES is *DAMN STUPID* ?????

If you use GL_TRIANGLE_STRIP instead, you draw triangles and you still send only 4 vertices... and that's probably what your gfx card does anyway http://www.opengl.org/discussion_boards/ubb/wink.gif !

Regards.

Eric

Jurjen Katsman
01-10-2002, 03:57 AM
Tom: The big advantage of using quads is when you can use a quadlist. Say for a large particle system. It means you have to specify only 4 indices indices for each quad.

Using a trilist it would be 6 indices, using a tristrip it would be 6 each as well. This means the CPU will have 50% more work copying the indices across.

Now even better, why have indices at all? Each vertex might very well be unique anyway, and the cache certainly isn't going to help. So you could simply create a vertexarray with all your data, and the CPU will have to copy exactly 0 indices.

Since copying the indices is pretty much the only thing the CPU still has to do (when using VAR) this can be a huge speedup on the CPU side.

- Jurjen Katsman

Relic
01-10-2002, 04:06 AM
>>There is no possibility to explicitly define a quad strip in GL, but there is no need of that.<<

Huh? Of course there is a GL_QUAD_STRIP primitive. And one useful aspect for this is with flat glShadeModel(GL_FLAT) resulting in quads and look nicer than triangle strips in many cases.

>>If you use GL_TRIANGLE_STRIP instead, you draw triangles and you still send only 4 vertices<<

As said above GL_QUADS look diffferent with flat shading and furthermore GL_QUADS are independent primitives, which means you don't need to call glBegin-glEnd or your vertex arrays drawing command for each one but a batch of multiple which has a lot less overhead.

Yes, emulating GL_QUADS with GL_TRIANGLES is stupid http://www.opengl.org/discussion_boards/ubb/wink.gif, can result in different rendering results (flat), and any other primitive except real GL_QUAD_STRIPs has more calling overhead.

Eric
01-10-2002, 05:17 AM
Originally posted by Relic:
...you don't need to call glBegin-glEnd...

You know what: yesterday, I wanted to post the message I posted one hour ago and I thought: "you stupid crazy, strips need Begin/End so it is likely to be slower !".

Then, I re-read the thread this morning, think the same thing and ... forget to think about it twice !!!!

Thanks Relic, and sorry to the others for this non-post... http://www.opengl.org/discussion_boards/ubb/wink.gif

Regards.

Eric

P.S.: actually, I think I had this idea because I work with quads on a CFD post-processor, and in this case, I use quad strips... That's why my brain refused to work: for me, I can use quads strips or triangle strips indifferently...

[This message has been edited by Eric (edited 01-10-2002).]

Rob The Bloke
01-10-2002, 05:52 AM
The ideal solution is to create as many triangle strips from your model as possible (from all polygons). This however becomes pointless if your strips only contain a few vertices. The number of calls required to draw each strip in your model seems less sensible than making just a few calls with large amounts of geometry.

If your model does not appreciate strips that much, then the next best solution IMO is to treat all polys as triangles and use one call to draw the entire model with triangles and vertex arrays.

GL_POLYGONS should be avoided at all cost. GL_QUADS give you rendering errors if your polys are non-planar, so you may as well use triangles. Making a strip from a quad is fairly pointless. It's not going to make much difference in speed other than by enabling you to determine how the quad is split when it hits hardware. The other big issue is why do you want to send a single quad on its own to gl anyway? It's slow. If you really must use quads then batch them all together and send them in one go, splitting them into strips will just cause problems, and not allow you to do the same batching.

I personally batch polygons via material types. Each material is set, then the geometry is drawn. The main philosophy behind drawing them, is to then make as few calls to draw the geometry as possible. If the average number of verts per triangle strip is below a certain threshold then the entire vertex array is drawn in one go with triangles.

MikeC
01-10-2002, 11:16 AM
Originally posted by Alain:
If you have a flat quad ABCD, then it's the same as two triangles ABD and DBC. And if you put them in a triangle strip, then you'll have exactly the same number of vertices to send: 4, and not 6.

Aaarrghh... nooo...

The crucial difference is that in this case you can draw X thousand independent quads WITH ONE CALL. With triangle strips you could only draw one "quad" per call, so you'd need X thousand calls. That's insane.

There isn't a canonical metric for the "best" arrangement of a chunk of geometry, but minimizing the number of API calls is typically AT LEAST as important as minimizing the number of vertices.

MikeC
01-10-2002, 11:27 AM
Originally posted by Rob The Bloke:
The other big issue is why do you want to send a single quad on its own to gl anyway?

Drawing uniquely-textured billboards is an obvious example. Though in this case the GL_QUAD vs GL_TRIANGLE_STRIP issue is completely irrelevant when set against the cost of the texture bind.



If the average number of verts per triangle strip is below a certain threshold then the entire vertex array is drawn in one go with triangles.

If the average is low AND the distribution is fairly even, yes. If the distribution isn't even, it might well be better to draw any "good" strips you can make as strips, and just bundle up the small ones into one big GL_TRIANGLES batch.

Alain
01-10-2002, 01:17 PM
MikeC: I know it would be insane in case of X thousand calls. I was thinking about single quads as in your bill-boarding example.
Recently, I had to correct some code (written by somebody else) which tried to optimize rendering by converting all strips of 2 triangles into quads. The bug was that it did not check if the resulting quad was flat, which then produces weird effects.
My experience would make me advise against using quads. I have never seen them giving any advantage, except maybe if you have hardware specially optimized for quads, which is not the case of current PC boards like GeForce 2/3.

mcraighead
01-10-2002, 04:17 PM
You might as well use quads, seeing as they do exist and we have to support them.

Just keep in mind that the OpenGL spec makes amazingly few guarantees about how rasterization of polygons with >3 vertices works.

- Matt

dslater
01-11-2002, 11:56 AM
Originally posted by Relic:
>>
As said above GL_QUADS look diffferent with flat shading ...


I would have to disagree with you on this point. As long as you specify the same normals for both triangles, you'll get the correct shading.

Relic
01-14-2002, 12:37 AM
The difference is that for both primitives the last "subprimitive" vertex is taken for the filling color.
That is for four vertices the third and fourth for triangle strips and only the fourth for quads.
I didn't say anything about lighting. And supplying the same normals doesn't result in the identical flat shaded image either with non-directional lighting or local viewers.
You're right four Gouraud shading (and still then you have no control about the tesselation of quads into trinangles by the implementation, so your results may vary if the four colors don't end up to be planar in RGB-space.