textures vs lines and polygons

Member
Posts: 320
Joined: 2003.06
Post: #1
Hi all, hopefully a simple question this time.

Which is faster - one polygon with a texture, or a few polygons with no texture?

I am trying to grow a few virtual plants. At the moment each leaf is a texured triangle strip. When there are 6 plants and they have a hundred or so leaves each, the frame rate slows to about 4 frames a second.

display lists are'nt gonna help much because of the masses of variables involved, but I'm either going to do what I can with display lists, or invest some time in making 3d models of leaves. Which do you recommend?

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #2
That depends on the graphics hardware, the size and mode of the texture, whether blending and/or alpha testing are enabled, and how many polygons you'd have to replace it with.

I'd guess that it's not your bottleneck, though. Run your application through Shikari. What function do you spend most of your time in? Run your application through the OpenGL profiler. Which OpenGL functions take the most of your time? Which 3D resources do you spend most time waiting for?

Don't try to guess why your code is slow, you'll probably guess wrong and spend days optimizing something that was fast enough anyway.
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #3
Quote:That depends on the graphics hardware, the size and mode of the texture, whether blending and/or alpha testing are enabled, and how many polygons you'd have to replace it with.


graphics hardware == Rage 128 / 8mb which is the minimum required graphics card I am aiming for

texture == uncompressed 32 bit tga 32 x 32 pixels

blending/alpha both enabled // alpha could probably be disabled if it would help.

would have to replace it with about half a dozen lines and and a dozen or more polygons. But could then disable blending and alpha

the main time hoggers from opengl profiler are as follows (give or take a bit):
glBegin: 48%
glEnd: 36%
glVertex3f: 8%

thanks

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #4
at the risk of information overload,

Shikari came back 98.5% machine_idle_ret which I assume means the cpu aint doin much.

also here is what it does every leaf every frame

[SOURCECODE]- (void) drawLeaf
{
if(side != 3)
{
float width,theRotation,height;
float texX,texY;
float Vx = xPos;
float Vy = yPos;
float z = 0.6;

texX = ((prongs - 1) / 2) / 8;
if(prongs > 9) texX = 0.5;

switch(side)
{
case 0: // left
width = -size;
height = size;
theRotation = rotation;
texY = 0;
break;
case 1: // right
width = size;
height = size;
theRotation = -rotation;
texY = 0;
break;
case 2: // front
width = size;
height = -size * (rotation / maxRotation);
theRotation = 0;
texY = 0.5;
Vx -= width / 2;
Vy += 5;
break;
}



glLoadIdentity();

glTranslatef(Vx, Vy, 0.0f);
glRotatef(theRotation,0.0f,0.0f,1.0f);

glColor3f( 1.0f, 1.0f, 1.0f );

glBegin( GL_TRIANGLE_STRIP );
glTexCoord2f( texX + 0.125, texY + 0.5 ); // TR
glVertex3f( width, height, z ) ;
glTexCoord2f( texX, texY + 0.5); // TL
glVertex3f( 0, height, z );
glTexCoord2f( texX + 0.125, texY ); // BR
glVertex3f( width, 0, z );
glTexCoord2f( texX, texY ); // BL
glVertex3f( 0, 0, z );
glEnd();

}
}[/SOURCECODE]

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #5
What's the top function you wrote in Shikari's list? What's the top easily recognizable library function (ie sqrt, floor, malloc_zone, &c)?

My guess is, in order of ease-of-implementation:

* turn on alpha-testing if it isn't already. Disable blending if you don't need it for antialiasing.

* use aglMacro/cglMacro to ensure that immediate-mode calls have as little overhead as possible.

* do the rotation/translation yourself on the CPU. Use GL_TRIANGLES rather than GL_TRIANGLE_STRIP, and move glBegin/glEnd to outside the recursive function so that everything gets submitted in one batch.

* restructure your function so that rather than submitting everything in immediate mode you add the vertices to a vertex array and then when you're done, call drawarrays. you should be able to calculate an upper bound for the number of vertices before you start, so you shouldn't have to resize the array on the fly. This assumes you've already made the changes I suggested in the point above.
Quote this message in a reply
Moderator
Posts: 916
Joined: 2002.10
Post: #6
using lines and polygons instead of of texture will drastically reduce the size of your executable. BOB2 used models with 40-100 polygon and the entire executable compressed to 67k. Now, textures, even 32x32 ones, tend take a lot of space compared to ANYTHING else, but they do make some things easier. They can also make your... whatever... look prettier. I would only reccommend not using textures if:
1) size of your download/executable is crucial
2) you plan to use more than a couple megs of textures and thus could not run on low end machines (Don't abandon me!Sad )
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #7
thanks heaps

I will look into doing the things you have sudgested OSC. It could well take a few days cos you have mentioned some things I have never done or seen done before. Will let you know how I get on.

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #8
ok, problems already. And I thought it was going to be a simple question!

Quote:* turn on alpha-testing if it isn't already. Disable blending if you don't need it for antialiasing.

To be honest I kinda thought these were the same thing. My textures have transparent backgrounds, so when I disable blending (glDisable(GL_BLEND)) I just get lots of green squares. I'm not really sure if alpha-testing is inabled, and if not, how to do so.

Quote:* use aglMacro/cglMacro to ensure that immediate-mode calls have as little overhead as possible.

I had a look around for info on this and couldn't find much. It seems I have to initialize it with the context or something. Do I just do this in the initialization of openGL or is it more complicated than that?

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #9
Code:
glAlphaFunc(GL_GREATER, 0.0f);
glEnable(GL_ALPHA_TEST);

Assuming CGLMacro, AGL works similarly:

You need a CGLContextObj CGL_MACRO_CONTEXT; this should probably be a global variable.

As often as you need to, do CGL_MACRO_CONTEXT = CGLGetCurrentContext(); I wouldn't do this less than once per frame, but once per frame should be fine.

At the top of each file that makes OpenGL calls, #include <OpenGL/OpenGL.h> and <OpenGL/CGLMacro.h> in that order.
Quote this message in a reply
Member
Posts: 320
Joined: 2003.06
Post: #10
ok. So I've taken the glBegin/end calls outside of the loop and am now doing the (now slightly demented) rotation on the cpu. That perhaps increased the frame rate by 50% or so.

I am now using GL_TRIANGLES.

I've added the cglMacro stuff and it is compiling but doesn't seem to have sped it up noticably, but I don't understand what it does so may have implemented it wrongly.

When I disable blending and enable alpha testing the plants light up and sparkle like christmas trees so at the moment I need to have it on for antialiasing. However this did double the speed. I may edit the textures to allow for this if I get desperate.

Shikari says:

10% gldFreeVertexBuffer
5.9% gldUpdateDispatch
5.3% obj_msgSend
4.9% NO_SYMBOL_0x01856440-0x0185654
4.4% -[Leaf drawLeaf]

and so on.

I Didn't notice before that I had to change to the application in shikari to see the results for the app.

I cant believe that a graphics card can draw vast 3d worlds and play doom etc at decent frame rates but cant draw a few little plants!

Thanks for your help, overall it is slightly faster although still far from ideal.

Chopper, iSight Screensavers, DuckDuckDuck: http://majicjungle.com
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #11
Even if you do need blending, still enable alpha testing. You'll get most of the benefit as long as you have a significant number of 100% transparent pixels.

Don't use ObjC method calls for the recursion, do it in C functions. objc_messageSend does have significant overhead, as you've seen.

If your stuff with CGLMacro is compiling, you've probably done it properly Smile

One possibility is to make the CGL_MACRO_CONTEXT variable local to each function, and assign to it from a different global at the start of each function. That should give you a bit of a speedup.
Quote this message in a reply
Tycho
Unregistered
 
Post: #12
Maybe I'm going off topic here, but what does CGLMacro do? I've never seen it before.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #13
At the heart of Apple's OpenGL implementation, there's a great big structure which is a table of function pointers to the driver's implemenation of all the OpenGL functions.

Here's a segment; you can see the whole thing in gliDispatch.h:

Code:
typedef struct __GLIFunctionDispatchRec
{
    void (*accum)(GLIContext ctx, GLenum op, GLfloat value);
    void (*alpha_func)(GLIContext ctx, GLenum func, GLclampf ref);
    GLboolean (*are_textures_resident)(GLIContext ctx, GLsizei n, const GLuint *textures, GLboolean *residences);
    void (*array_element)(GLIContext ctx, GLint i);
    void (*begin)(GLIContext ctx, GLenum mode);
    void (*bind_texture)(GLIContext ctx, GLenum target, GLuint texture);
    ...

All that the OpenGL functions you're used to calling do is find the current context's dispatch table, and call the appropriate function through the pointer. This incurs an unnecessary function call, which is bad for speed &mdash; particularly if you're submitting a lot of geometry in immediate mode.

CGLMacro lets you bypass that function call overhead by redefining all the OpenGL functions as macros which do the same thing. You can see this all in CGLMacro.h:

Code:
/* Macro context name */
#define CGL_MACRO_CONTEXT cgl_ctx

#define glAccum(op, value) \
    (*cgl_ctx->disp.accum)(cgl_ctx->rend, op, value)

#define glAlphaFunc(func, ref) \
    (*cgl_ctx->disp.alpha_func)(cgl_ctx->rend, func, ref)

#define glAreTexturesResident(n, textures, residences) \
    (*cgl_ctx->disp.are_textures_resident)(cgl_ctx->rend, n, textures, residences)

#define glArrayElement(i) \
    (*cgl_ctx->disp.array_element)(cgl_ctx->rend, i)

#define glBegin(mode) \
    (*cgl_ctx->disp.begin)(cgl_ctx->rend, mode)

#define glBindTexture(target, texture) \
    (*cgl_ctx->disp.bind_texture)(cgl_ctx->rend, target, texture)

    ...

(The headers are in /System/Library/Frameworks/OpenGL.framework/Headers/).

The one restriction is that you need a pointer to the OpenGL context with a specific name to be in scope everywhere you call an OpenGL function. That's what the CGL_MACRO_CONTEXT variable is about.
Quote this message in a reply
henryj
Unregistered
 
Post: #14
Of course all of this hackery that OSC is confusing everyone with is still not going to be as fast as drawing your geometry properly ie not using immediate mode.

This is the answer to your question...why is quake so fast and my code is so slow. Often the best optimisation is to change your algorithm/ rendering method.
Quote this message in a reply
Moderator
Posts: 916
Joined: 2002.10
Post: #15
Quote:Originally posted by henryj
Of course all of this hackery that OSC is confusing everyone with is still not going to be as fast as drawing your geometry properly ie not using immediate mode.

This is the answer to your question...why is quake so fast and my code is so slow. Often the best optimisation is to change your algorithm/ rendering method.


because john carmack wrote a lot of graphic card specific things into it. That is the easiest explanation. He literally wrote a whole bunch of optimization for each graphics card... the newer graphics cards are so fast they didn't need them really... but I'm sure they added them in there in some of the patches.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  SLOW performance drawing multiple polygons per frame with stencil buffer clam61 7 4,137 Apr 27, 2013 11:53 AM
Last Post: clam61
  antialiasing polygons honkFactory 37 16,004 Apr 3, 2006 09:19 AM
Last Post: akb825
  n00b question: getting rid of lines along edges of polygons Andrew 2 2,756 Jun 5, 2005 05:57 PM
Last Post: Andrew
  Blending -&gt; Black Lines Through Textures (Wireframe like) hangt5 2 3,277 Apr 5, 2005 05:06 AM
Last Post: ThemsAllTook
  Weird lines on my display? AngelDaniel 1 2,273 Mar 12, 2005 08:55 AM
Last Post: AngelDaniel