Original Post
I want to optimise how I'm rendering my 2D game, since I'm not happy with how little (a few hundred on screen objects) it takes to cause the frame rate to drop noticebly on some of my hardware.
Currently I just draw stuff in a strict back to front order with the graphics layers not really knowing much about what is coming, I just go like "frigateImg->draw(x,y,angle,etc); lights->draw(); turrets->draw(); etc"...
This results in almost no opportunity to batch stuff since the draw order might be like:
As a result there is a lot of texture switches, and even if I batched draws of the same texture/etc, I would onyl be getting a few sprites in at most...
Ive been considering two approaches to improving this:
[subheading]Create a sprite sheet for as much as possible[/subheading]
The idea here is to put lots of sprites into a single image. However I'm not sure if it will be realistic to put some of the bigger sprites (upto 512*512 for stations, asteroids, and that, background is even bigger but I'm not counting it) given limitations on the maximun texture size (At least in D3D, I assume it s ahardware thing and OpenGL would have the same limits).
However I think this would still easyily give me like
[subheading]Reorder draws to be more optimimal[/subheading]
The idea here is to do the rendering in a more optimal order. Unfortunatly 99% of my stuff uses alpha blending so it must be back to front, however only in respect to things that actually overlapp, so I think it would be practical to end up with like the following since the event all ships are stacked ontop of each other is fairly low... However I assume this is how basically every 3D game must do it, since they likly have even more issues with the concept of packing everything into a single texture, vertex buffer, index buffer, etc, and I'm not sure its really possible to do anything at all in regards to shaders...
this one requires somwhat of a major change though and I havnt found much in the way of resources on how to do it
What I'm considering is making a bunch of "Drawable" objects which include everything needed to draw the object, position, angle, z order, etc, etc...
Somthing like:
Of course the Drawable classes need some more fleshing out, like for example keeping the bounds thingupto date...
The problem is I'm not sure how to go from the "std::vector scene;" to the "std::vector stuffToDrawThisFrameInOrder;"..
I'm thinking that scene could then be sorted by depth, but then I'm not sure on the process of grouping things together
EDIT:
I'm also wondering now if just doing the first will be enough for my case. I'm thinking it will, and natually I'll do one first and test it before moving onto the other, however I'm still intrested in this ordering thing, and I also guess it has some relevance in 3D games (eg particle effects have lots of alpha stuff, and still need to be done in order relative to other things, like say windows).
Currently I just draw stuff in a strict back to front order with the graphics layers not really knowing much about what is coming, I just go like "frigateImg->draw(x,y,angle,etc); lights->draw(); turrets->draw(); etc"...
This results in almost no opportunity to batch stuff since the draw order might be like:
frigate
blinking_blue_light
blinking_blue_light
heavy_turret
plasma_muzzle_effect
heavy_turret
med_turret
missile_turret
missile_launch_effect
missile_turret
missile_launch_effect
radar_dish
frigate
blinking_blue_light
blinking_blue_light
heavy_turret
plasma_muzzle_effect
heavy_turret
med_turret
missile_turret
missile_launch_effect
missile_turret
missile_launch_effect
radar_dish
...
As a result there is a lot of texture switches, and even if I batched draws of the same texture/etc, I would onyl be getting a few sprites in at most...
Ive been considering two approaches to improving this:
[subheading]Create a sprite sheet for as much as possible[/subheading]
The idea here is to put lots of sprites into a single image. However I'm not sure if it will be realistic to put some of the bigger sprites (upto 512*512 for stations, asteroids, and that, background is even bigger but I'm not counting it) given limitations on the maximun texture size (At least in D3D, I assume it s ahardware thing and OpenGL would have the same limits).
However I think this would still easyily give me like
frigate
--new batch--
blinking_blue_light
blinking_blue_light
heavy_turret
plasma_muzzle_effect
heavy_turret
med_turret
missile_turret
missile_launch_effect
missile_turret
missile_launch_effect
radar_dish
--new batch--
frigate
blinking_blue_light
blinking_blue_light
heavy_turret
plasma_muzzle_effect
heavy_turret
med_turret
missile_turret
missile_launch_effect
missile_turret
missile_launch_effect
radar_dish
...
[subheading]Reorder draws to be more optimimal[/subheading]
The idea here is to do the rendering in a more optimal order. Unfortunatly 99% of my stuff uses alpha blending so it must be back to front, however only in respect to things that actually overlapp, so I think it would be practical to end up with like the following since the event all ships are stacked ontop of each other is fairly low... However I assume this is how basically every 3D game must do it, since they likly have even more issues with the concept of packing everything into a single texture, vertex buffer, index buffer, etc, and I'm not sure its really possible to do anything at all in regards to shaders...
frigate
frigate
blinking_blue_light
blinking_blue_light
blinking_blue_light
blinking_blue_light
heavy_turret
heavy_turret
heavy_turret
heavy_turret
med_turret
med_turret
missile_turret
missile_turret
missile_turret
missile_turret
plasma_muzzle_effect
plasma_muzzle_effect
missile_launch_effect
missile_launch_effect
missile_launch_effect
missile_launch_effect
radar_dish
radar_dish
...
this one requires somwhat of a major change though and I havnt found much in the way of resources on how to do it
What I'm considering is making a bunch of "Drawable" objects which include everything needed to draw the object, position, angle, z order, etc, etc...
Somthing like:
class Drawable
{
int depth;
Vector2F pos;
RectF bounds;
bool backToFront;//must be rendered backToFront relative to all other backToFront objects, likly tobe 90% of my stuff, but I guess some things are "solid"
enum Type
{
SPRITE,
TEXT
};
Type type;
};
class Sprite : public Drawable
{
RectF uvs;
Texture *texture;
Vector2F centre;
Vector2F scale;
Vector2F
};
class Text : public Drawable
{
Font *font;
String text;
enum Align
{
LEFT = 0,
RIGHT = 1,
CENTRE_H = 2,
FIRST_LINE = 0,
TOP = 4,
BOTTOM = 8,
CENTRE_V = 16,
CENTRE = 2 | 16
};
int align;
};
class DrawGroup
{
enum Type
{
SPRITE,
TEXT;
};
Type type;
/**Draws the entire group in order from first to last*/
vitual void draw()=0;
std::vector<Drawable*> items;
};
class DrawSpriteGroup : public DrawGroup{...};
class DrawTextGroup : public DrawGroup{...};
std::vector<Drawable*> scene;//all the objects in the scene
std::vector<DrawGroup*> stuffToDrawThisFrameInOrder;//"how" the scene will be drawn
Of course the Drawable classes need some more fleshing out, like for example keeping the bounds thingupto date...
The problem is I'm not sure how to go from the "std::vector
I'm thinking that scene could then be sorted by depth, but then I'm not sure on the process of grouping things together
EDIT:
I'm also wondering now if just doing the first will be enough for my case. I'm thinking it will, and natually I'll do one first and test it before moving onto the other, however I'm still intrested in this ordering thing, and I also guess it has some relevance in 3D games (eg particle effects have lots of alpha stuff, and still need to be done in order relative to other things, like say windows).