Sprite Rendering how-to?

Started by
5 comments, last by bluntman 12 years, 11 months ago
Im trying to create a sprite rendering class for opengl +3.X but I cant seem to get around it

Ive made my basic shaders and setup the context

What Im having trouble is the creation of vertices and assign them texture to them

Maybe would it be possible to have a function like:

Sprite.Draw();


where sprite has something like
{
float x , y;
int w, h;
rectangle texture_portion;
uint texture_id;
}


:S looks like Im really lost here
Advertisement

Im trying to create a sprite rendering class for opengl +3.X but I cant seem to get around it

Ive made my basic shaders and setup the context

What Im having trouble is the creation of vertices and assign them texture to them

Maybe would it be possible to have a function like:

Sprite.Draw();


where sprite has something like
{
float x , y;
int w, h;
rectangle texture_portion;
uint texture_id;
}


:S looks like Im really lost here


You could do it like that. Personally I like to separate my game data from my rendering method, so instead you would have something like:


struct Sprite
{
float x, y;
float w, h;
// blah blah
}



Then you would have:


struct Scene
{
Sprite[] sprites;
};

struct Renderer
{
void render(Scene scene)
{
foreach(Sprite sprite in scene.sprites)
{
draw_sprite(sprite);
}
}

void draw_sprite(Sprite sprite)
{
// draw sprite
}
}



The benefits of this are: keeping your sprite class clean and small, and keeping your rendering code all in one place. Later on you can easily write another class called Renderer2 that uses some other rendering API or renders sprites in a different way.
thanks

Im having trouble how to figure out the most efficient way to draw the sprites

Ive read that batching is the way to go but my textures are grouped by game objects (1 texture for player, 1 for each type of enemy, etc...)

I would like to add all my vertices in one array and send them to draw but it looks like it would be impossible because the way Ive planned my resources?
You should pack your sprites into sprite sheets, this should allow you to fit most sprites into a single texture. It also means you only need to bind a single texture, generate a single vertex buffer, use a default index buffer to draw your sprites. There are a few utilities for generating sprite sheets around, e.g. http://spritesheetpacker.codeplex.com/

So your code would look something like:

index_buffer indices;
indices = generate_index_buffer(); // makes a single index buffer you can use for drawing all your sprites, looks like: [0,1,2,3,4,5,6,7,8,9,...,n] where n is a big number (as many as you are going to have active sprites * 4, preferably).

vertex_buffer verts;
while(playing_this_awesome_game)
{
verts.clear();
foreach(Sprite sprite in activeSprites)
{
verts.add(Vertex(sprite.x, sprite.y, sprite.u, sprite.v));
verts.add(Vertex(sprite.x + sprite.w, sprite.y, sprite.u2, sprite.v));
verts.add(Vertex(sprite.x + sprite.w, sprite.y + sprite.h, sprite.u2, sprite.v2));
verts.add(Vertex(sprite.x, sprite.y + sprite.h, sprite.u, sprite.v2));
}
load_vertex_buffer(verts);
draw_index_array(indices, 0, activeSprites.count() * 4);
}


Obviously this is over-simplified, you need to do things like setting up your vertex format, stride etc, as well, or maybe load your sprite positions and sprite uvs into different buffers.
Also you might want to update active sprites directly into the vertex array instead and use a dynamic index buffer to only render the ones you are using.
I'm really no expert on sprite rendering though so you are best to look into this yourself more.
I assume for this to work I should previously bind a texture?


Do I really have to group all textures? I mean Im using sprite sheets dont get me wrong but Im not using ONE spritesheet, Im using one for each object in my game, as I said earlier ...

one sheet for the player one for each type of enemies etc


Ive tried this in XNA and no problem what so ever why is this so different under OGL?
Because opengl is not a game development framework. Opengl is the equivalent of DirectX. If you want to equivalent of XNA, look at something like unity.


1. You could bind multiple sprite sheets and do work in the pixel shader to choose which one is used.

2. You could just bind one sheet at a time and render all the things which use that sheet by putting their data in different sections of the input VBO.

3. Make bigger sprite sheets. Modern opengl is happy with them being 1000s of pixels on a side.

[color=#1C2837][size=2]Modern opengl is happy with them being 1000s of pixels on a side.
[color=#1C2837][size=2]

OpenGL is happy with it, but its the hardware/driver that decides how large a texture it will permit. Safest to stick to 2048 or 1024. I think (iirc) my HTC Hero will support 1024x1024 textures.
If you are making a game with sprites then I would guess that the sprites are usually a fixed size on screen. There is no point making the sprite texture larger than the sprite itself (I might be wrong here, but I think filtering not give better results if the texture is higher res, but will give optimal results if the texel/pixel ratio is close to 1). So unless all your sprites are massive on screen you should be able to pack a few into textures.
Still, as Katie mentioned, you could put all your 2D textures into a 3D texture, and use a w coordinate (so your uv is actually uvw) to specify which one to use.

This topic is closed to new replies.

Advertisement