Dark Bit Factory & Gravity

PROGRAMMING => General coding questions => Topic started by: Phoenix on September 03, 2007

Title: OpenGL texturing
Post by: Phoenix on September 03, 2007
Hey all DBF members!

I know there has to be some OpenGL users out there, Rbraz at least! I haven't visited you for a long time, which is a shame. Especially because of the atmosphere of this community, which is awesome :cheers:

Anyways, onto the question. I have drawn a nice little image in paint to illustrate the problem.

(http://randomuploads.sitesled.com/texture.png)

I have a quad, and also a texture. I can easily draw a texture onto the quad, making it cover the whole rectangle, but I want to draw multiple instances of my texture onto the quad, as seen at the rightmost part of the image. Can't really figure out how to do it though :-\ At the moment, I have one quad for each texture I want to draw, but that's not really performance efficient when having 500 textures on screen. (500*4=2000 vertices. If I had one rectangle it would be 1*4=4, quite a difference!)

Any help is greatly appreciated!
Martin
Title: Re: OpenGL texturing
Post by: Shockwave on September 03, 2007
No doubt that the Opengl experts here will tell you a better solution than this, but it sounds to me like you need two textures, one to have the image you want to copy and one target texture.

you could try using glCopyTexImage2D to draw multiple instances of the source texture to the target texture?
Title: Re: OpenGL texturing
Post by: Stonemonkey on September 03, 2007
Yep, that's pretty much it except you can only draw to the framebuffer so you:

set the viewport to match the size of your target texture
draw your texture to it
copy from the framebuffer with glcopyteximage2d to your target texture
reset viewport to original size.

I think that's how it's done anyway.
Title: Re: OpenGL texturing
Post by: Jim on September 04, 2007
Hi Phoenix, you can't get the image on the right with a single quad and just that texturemap.  Either you need to use more quads, one for each squished circle, or you need to use a texture with that image on it.  Don't worry too much about having lots of geometry, that can be fixed up later if it's too slow.

Jim
Title: Re: OpenGL texturing
Post by: taj on September 04, 2007
Phoenix,

Jims right, dont worry about speed yet. 2000 texture mapped quads is nothing. In fact, depending on cards, you may find its faster than making a new texture and drawing one quad. Even worse, if you make one new texture that is not square (the obvious thing to do from your diagram) and you are not very careful with opengl state, your program will drop to 1-2 frames a second.

Personally until I know its too slow, I'd simply draw all the quads.

Chris
Title: Re: OpenGL texturing
Post by: ferris on September 04, 2007
I think this would be a good test - try it both ways and compare framerates. It would probably only be about your card's performance but now I'm curious as to which is actually faster.

But I'd take the easy way out and make lots of quads if you really want my opinion.
Title: Re: OpenGL texturing
Post by: Phoenix on September 04, 2007
I had a test program with 50 spinning balls, 50 quads. It ran at ~100 fps on my computer. But at my big computer, it ran at 1000 fps. So performance shouldn't be much of a problem if you have a decent computer. My laptop isn't decent, and it had 100 fps.

But let's say we have a 800x600 screen, filled with tiles. The tiles are 32x32, making the screen 25x19 tiles. 25*19=475 quads, which is way too slow on my laptop (~7 fps). Jim, you say that speed can be fixed, could you explain how? If there is no way to optimize it, is there another method that can handle many images on screen at the same time? Blitz could handle lots of images on screen at the same time, and it's generally considered to be slow, so surely there must be an effective approach.
Title: Re: OpenGL texturing
Post by: stormbringer on September 04, 2007
drawing tons of quads should not be a problem.... geometry in OpenGL is very very fast (and even if explicit calls show some slowdown, there are then other ways to optimize)..

one thing to avoid, especially in this case (as far as I understood) is that if you use the same texture, then avoid making calls to glBindTexture() before drawing each quad. Or if you can have a loop that looks like this:

glBindTexture()
glBegin(GL_QUADS)

for (c=0; c < NUM_QUADS; c++)
{
    glTexCoordXXX()
    glVertexXXX()
}
glEnd()

it should be pretty fast...

You cannot have a quad filled in with several textures (unless you use multi-texture extensions, which are not great at all and if this is the case, the you should switch to shaders)
Title: Re: OpenGL texturing
Post by: Phoenix on September 04, 2007
After stripping the code down a lot, there aren't many lines left. This is called 500 times:
Code: [Select]
Gl.glBegin( Gl.GL_QUADS );
Gl.glVertex3f( X, Y, 0.0f );
Gl.glVertex3f( (Width + X), Y, 0.0f );
Gl.glVertex3f( (Width + X), (Height + Y), 0.0f );
Gl.glVertex3f( X, (Height + Y), 0.0f );
Gl.glEnd();
Without any textures, colors or anything, and I get 15-20 fps. Is that normal? Should I stop using glBegin/glEnd?
Title: Re: OpenGL texturing
Post by: taj on September 04, 2007
Tell us processor and graphics card, but I'd say thats definitely not normal. 500 quads at less than 20fps? I'd call that a WTF the mid 90s called and asked for their performance back?

It almost sounds like you are dropping back to software. That might be happening if you are asking for a pixel format that is unsupported. What pixel format are you using?

Thats only a wild guess but really this is very unusual.


Chris
Title: Re: OpenGL texturing
Post by: Phoenix on September 04, 2007
1.5 GHz Intel processor, 64mb graphics card. Runs at more than 1000 fps with 2.54 GHz Intel/256mb video memory.
Title: Re: OpenGL texturing
Post by: taj on September 04, 2007
No way its that slow so either the pixel format is screwed or somehow its finding a SW implementation fo OGL not hardware. Please post your windowing code...
Title: Re: OpenGL texturing
Post by: Phoenix on September 04, 2007
I'm using a SimpleOpenGLControl (found in the Tao framework), with C#, and it's attached to  a Windows Form. Pixel format seems to be normal:
Code: [Select]
Gdi.PIXELFORMATDESCRIPTOR pfd = new Gdi.PIXELFORMATDESCRIPTOR();// The pixel format descriptor
            pfd.nSize = (short) Marshal.SizeOf(pfd);                        // Size of the pixel format descriptor
            pfd.nVersion = 1;                                               // Version number (always 1)
            pfd.dwFlags = Gdi.PFD_DRAW_TO_WINDOW |                          // Format must support windowed mode
                        Gdi.PFD_SUPPORT_OPENGL |                            // Format must support OpenGL
                        Gdi.PFD_DOUBLEBUFFER;                               // Must support double buffering
            pfd.iPixelType = (byte) Gdi.PFD_TYPE_RGBA;                      // Request an RGBA format
            pfd.cColorBits = (byte) colorBits;                              // Select our color depth
            pfd.cRedBits = 0;                                               // Individual color bits ignored
            pfd.cRedShift = 0;
            pfd.cGreenBits = 0;
            pfd.cGreenShift = 0;
            pfd.cBlueBits = 0;
            pfd.cBlueShift = 0;
            pfd.cAlphaBits = 0;                                             // No alpha buffer
            pfd.cAlphaShift = 0;                                            // Alpha shift bit ignored
            pfd.cAccumBits = accumBits;                                     // Accumulation buffer
            pfd.cAccumRedBits = 0;                                          // Individual accumulation bits ignored
            pfd.cAccumGreenBits = 0;
            pfd.cAccumBlueBits = 0;
            pfd.cAccumAlphaBits = 0;
            pfd.cDepthBits = depthBits;                                     // Z-buffer (depth buffer)
            pfd.cStencilBits = stencilBits;                                 // No stencil buffer
            pfd.cAuxBuffers = 0;                                            // No auxiliary buffer
            pfd.iLayerType = (byte) Gdi.PFD_MAIN_PLANE;                     // Main drawing layer
            pfd.bReserved = 0;                                              // Reserved
            pfd.dwLayerMask = 0;                                            // Layer masks ignored
            pfd.dwVisibleMask = 0;
            pfd.dwDamageMask = 0;

Complete window code, if needed.
Code: [Select]
windowForm = new Form();
windowForm.ClientSize = new Size( ScreenWidth, ScreenHeight );
windowWidth = windowForm.Width;
windowHeight = windowForm.Height;
windowForm.Icon = null;
windowForm.Text = windowTitle;
windowForm.FormClosing += new FormClosingEventHandler( windowForm_FormClosing );
windowForm.Resize += new EventHandler( windowForm_Resize );

// Window mode specific settings
// Changes borders/control boxes/etc
switch( mode )
{
case WindowMode.Windowed:
windowForm.FormBorderStyle = FormBorderStyle.FixedSingle;
windowForm.MaximizeBox = false;
windowForm.MinimizeBox = false;
break;
case WindowMode.Fullscreen:
Resolution.CResolution changeRes = new Resolution.CResolution( screenWidth, screenHeight );
windowForm.FormBorderStyle = FormBorderStyle.None;
windowForm.WindowState = FormWindowState.Maximized;
windowForm.TopMost = true;
break;
case WindowMode.WindowScalable:
windowForm.FormBorderStyle = FormBorderStyle.Sizable;
break;
case WindowMode.BorderlessWindow:
windowForm.FormBorderStyle = FormBorderStyle.None;
break;
}

// Initialize the OpenGL graphics device
glDevice = new SimpleOpenGlControl();
glDevice.Location = new Point( 0, 0 );
glDevice.Size = new Size( screenWidth, screenHeight );
glDevice.InitializeContexts();

windowForm.Controls.Add( glDevice );

// Set up OpenGL
Gl.glMatrixMode( Gl.GL_PROJECTION );
Gl.glOrtho( 0, screenWidth, screenHeight, 0, -1, 1 );
Gl.glMatrixMode( Gl.GL_MODELVIEW );
Gl.glClearColor( 1, 1, 1, 1 );

// Enable transparency
Gl.glBlendFunc( Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA );
Gl.glEnable( Gl.GL_BLEND );

// We're done setting up, so the program is running
running = true;

// Show the created window
windowForm.Show();
Title: Re: OpenGL texturing
Post by: taj on September 04, 2007
OK so check that accumBits is 0, depth bits is 32, colorBits is 32 and stencilBits is 0. I dont know what SimpleOpenGlControl() is ...
Title: Re: OpenGL texturing
Post by: Phoenix on September 04, 2007
No luck, I changed them but the FPS still sits at 15-20.
Title: Re: OpenGL texturing
Post by: stormbringer on September 04, 2007
do not remove glBegin()/glEnd() calls. They control the geometry definition => removing them will ruin the GL geometry pipeline
Title: Re: OpenGL texturing
Post by: Rbz on September 04, 2007
1.5 GHz Intel processor, 64mb graphics card. Runs at more than 1000 fps with 2.54 GHz Intel/256mb video memory.
Seems to me that you have a problem with your gfx driver, have you tried to update it ?
Title: Re: OpenGL texturing
Post by: Jim on September 04, 2007
Perhaps it's PB itself that's slowing it down?
I was going to suggest using glDrawBuffers and friends, but only if your poly count was in the order of 10,000 or so.  500 is nothing.

Jim