ogl 2d quads performance issue

Started by
6 comments, last by Elrinth 12 years, 2 months ago
Hi!
I'm having troubles with poor performance with drawing of sprites.

I create a sprite sheet from each texture. (a vbo for each texture, which contains position and texcoords for each sprite inside the texture)

Code to draw a letter (from font):

GraphicsManager::GetInstance()->Draw("data\\gfx\\fonts\\ansi-thin.png", letter, iPos, iScale, iColor);


Code in graphics manager to draw a sprite

void GraphicsManager::Draw( string i_fileName, int i_index, Vector3D iPos, Vector2D iScale, ColorF iColor )
{
if (!_isInitialized)
return;
TextureManager::GetInstance()->BindTexture(i_fileName);
glColor4f(iColor.R, iColor.G, iColor.B, iColor.A);
glPushMatrix();
glTranslatef(iPos.X, iPos.Y, iPos.Z);
GetSpriteSheet(i_fileName)->Draw(i_index);
glPopMatrix();
}


Code in SpriteSheet for drawing

void SpriteSheet::Draw( int i_index )
{
if(!isAlreadyBound)
Bind();
glDrawArrays(GL_QUADS, i_index*4, 4);
}


Drawing only a mouse cursor sprite: 4000+ fps.
Drawing mouse cursor AND a letter from font (two texture binds, two vbo binds, two glDrawArrays calls): 2400+ fps
Draw a string of text "Mouse Screen Pos:[1,319]" and the cursor takes me down to: 680 fps.
Filling screen(800x600) with 16x16 tiles, drawing the string of text and mouse cursor makes: 20 fps.

You see that performance drops pretty damn quickly. I'd like to know what I'm doing wrong.

I did also try with ONE universal VBO created with 160 000 vertices before this code. Which had like 3-4 draw calls to that vbo. (one for each texture). Then I drew only parts of that giant VBO for each texture. depending on how many sprites we're drawn.
That didn't give me any performance either. It was because I was constantly changing the VBO (GL_DYNAMIC_DRAW).
Advertisement
Does 16 x 16 tiles mean 256 quads?
That is basically nothing even for a GPU from 2000.
Are you perhaps not using mipmaps and getting poor texture cache performance?
Are you perhaps making too many state changes?
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
16x16 tiles means 16 pixels wide and 16 pixels high per tile. Resultion is 800x600. That makes 50 tiles in X and 37.5 (37) tiles in Y. which in total makes 1850 tiles for a screen (resolution will be 640x480 or low later, right now I'm still in testing stage). But this will call the function glDrawArrays (1850 times)


As you can see.. there is barely any state changes. I'm doing glTranslate and glDrawArrays per tile and that's it, they're all using the same texture. I will bind between max something like 5-6 different textures each frame. I'll use sprite sheets for everything.

I might not be using mipmaps. I'm using DevIL to load images. If I set: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
then the textures don't appear.

My computer is decent. i5 processor, 4gb ram, nvidia 560ti. So seeing poor performance already means I'm doing something very wrong, and I'd like some guidence on where the error is and the proper way to get it running faster than the furious :)
With that kind of spec you should be getting much higher performance, even with almost 2000 draw calls and even without using a VBO (I half suspect that even immediate mode would run much faster than the times you're getting).

What looks hellishly suspicious to me is that you're passing a file name to your draw and bind (and GetSpriteSheet) routines. Are you certain that you're not reloading an image and recreating a texture each time?

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Indeed seems what's eating my fps isn't any GL stuff.. I tried commenting out all draw code and FPS remains the same... It's either me allocating memory every frame or it's something else. smile.png

Seems what's eating fps is cause I'm not passing references of variables everywhere smile.png

16x16 tiles means 16 pixels wide and 16 pixels high per tile. Resultion is 800x600. That makes 50 tiles in X and 37.5 (37) tiles in Y. which in total makes 1850 tiles for a screen (resolution will be 640x480 or low later, right now I'm still in testing stage). But this will call the function glDrawArrays (1850 times)


As you can see.. there is barely any state changes. I'm doing glTranslate and glDrawArrays per tile and that's it, they're all using the same texture. I will bind between max something like 5-6 different textures each frame. I'll use sprite sheets for everything.

I might not be using mipmaps. I'm using DevIL to load images. If I set: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
then the textures don't appear.

My computer is decent. i5 processor, 4gb ram, nvidia 560ti. So seeing poor performance already means I'm doing something very wrong, and I'd like some guidence on where the error is and the proper way to get it running faster than the furious smile.png


So why don't you use mipmaps?
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

[quote name='Elrinth' timestamp='1328483316' post='4909965']
16x16 tiles means 16 pixels wide and 16 pixels high per tile. Resultion is 800x600. That makes 50 tiles in X and 37.5 (37) tiles in Y. which in total makes 1850 tiles for a screen (resolution will be 640x480 or low later, right now I'm still in testing stage). But this will call the function glDrawArrays (1850 times)


As you can see.. there is barely any state changes. I'm doing glTranslate and glDrawArrays per tile and that's it, they're all using the same texture. I will bind between max something like 5-6 different textures each frame. I'll use sprite sheets for everything.

I might not be using mipmaps. I'm using DevIL to load images. If I set: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
then the textures don't appear.

My computer is decent. i5 processor, 4gb ram, nvidia 560ti. So seeing poor performance already means I'm doing something very wrong, and I'd like some guidence on where the error is and the proper way to get it running faster than the furious smile.png


So why don't you use mipmaps?
[/quote]

i'm assuming that his tile engine is done in ortho mode, so i don't really see why mipmaps are neccessary, it's not like his textures are changing sizes.(although this is just an assumption, i may be wrong.)

@Elrinth: i have to agree with mhagain, any moderate, or even low end pc, should be able to handle something like this easily(and i agree with him, that your binding by filename is a bit suspicious, although mapping strings to binded id's isn't unheard of.).

one last point, to improve your actual draw performance(although with something as simple as just drawing a bunch of tiles, it's probably not needed), is to build a large plane, and subdivide it to the number of tiles that you are drawing, and map the uv coordinates for each tile accordingly.)
Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.
like you guys suspect. I was doing other stuff which was eating alot of FPS. Still haven't figured everything out. It's still eating quite alot of FPS. But I started with replacing all variables in the draw functions to reference objects rather than copy objects. It's still not quite there yet tho. Filling a screen with tiles and drawing 3 lines of text and drawing mouse cursor still sets me at 240 fps. The moment I don't call the draw methods for all tiles I go back up to 1600 fps. I also tried modifiying the code by removing the glDrawArrays in runtime. It did not affect the FPS at all. Meaning it's calling the methods which is costly. Right now all variables sent thru all "draw"-methods are reference variables.

240~260 fps @ ~0.004 sec per frame with screen filled with tiles @ resolution 800x600.

This topic is closed to new replies.

Advertisement