Home » Community » Forums » » Rendering efficient 2D sprites in OpenGL using Texture Rectangles
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic


 Last Thread Next Thread 
 Rendering efficient 2D sprites in OpenGL using Texture Rectangles
Post Reply 
This is a great article. I can now start my game in OpenGL. I was making a game engine using SDL, but I couldn't rotate sprites in real-time without using either Dx, or OpenGL, so I was undecided. Now with what I've learned in this article I am sure to make the engine with OpenGL.

Great Article!

My Blog

 User Rating: 855   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
From the article
And there you have it! You can now render 2D sprites as efficiently as you would in Direct3D!


Unless I'm mistaking, Direct3D's ID3DXSprite interface uses some kind of batching (it most likely stores vertices in a vertex buffer and sort them by texture), so I'd be very surprised if you could get a comparable performance using immediate mode opengl.

Apart from this, the article is a good introduction to those who want to start using the power of opengl to build simple 2D games. I'd have loved a tutorial on 2D sprite batching though...

 User Rating: 1213   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Decent article, though a fully functional sample project would have been fitting.

One issue I have, though, is that you keep mentioning efficiency throughout yet you still use immediate mode rendering (glVertex and friends)? If you really want to be efficient (and match the D3DX interface better) you would be far better of using Vertex Buffer Objects or at the very least Display Lists. In fact, that would be pretty good advice for any modern OpenGL program...

Still, a nice little code blurb that serves as a decent example of how to use the the extension.

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Your color keying doesn't work so great -- that's why you have that purple halo around your sprite.

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by ReadTFM
Your color keying doesn't work so great -- that's why you have that purple halo around your sprite.


Color keying always causes trouble when used in combination with lossy file formats such as JPG. That is because some pixel colors are approximated, they do not remain pure RGB(255, 0, 255).

 User Rating: 1213   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by Trillian
Color keying always causes trouble when used in combination with lossy file formats such as JPG. That is because some pixel colors are approximated, they do not remain pure RGB(255, 0, 255).


Even with a lossless format, though, you will still end up with a very sharp, aliased edge. Really there's no reason not to use alpha channels for these things anymore, which can easily avoid these problems.



 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by Trillian
Quote:
From the article
And there you have it! You can now render 2D sprites as efficiently as you would in Direct3D!


Unless I'm mistaking, Direct3D's ID3DXSprite interface uses some kind of batching (it most likely stores vertices in a vertex buffer and sort them by texture), so I'd be very surprised if you could get a comparable performance using immediate mode opengl.

Apart from this, the article is a good introduction to those who want to start using the power of opengl to build simple 2D games. I'd have loved a tutorial on 2D sprite batching though...

I decided not to use any forms of batching to keep the article more simple for beginners to use. I'm sure anyone who knows how to add static/dynamic batching can do so themselves. Just wanted to make it noob friendly.

Quote:
Decent article, though a fully functional sample project would have been fitting.

One issue I have, though, is that you keep mentioning efficiency throughout yet you still use immediate mode rendering (glVertex and friends)? If you really want to be efficient (and match the D3DX interface better) you would be far better of using Vertex Buffer Objects or at the very least Display Lists. In fact, that would be pretty good advice for any modern OpenGL program...

Still, a nice little code blurb that serves as a decent example of how to use the the extension.

Thanks for pointing that out, but I left out such features for the reasons above :) I wanted to have the source code for the example available for the public to download, but it seems GameDev didn't post it. I need to host the file somewhere so you all can download it.

Quote:
Your color keying doesn't work so great -- that's why you have that purple halo around your sprite.

Yeah, I used a cheap method of color keying with this sprite. (http://www.codesampler.com/oglsrc/oglsrc_4.htm#ogl_color_key)

Quote:
Color keying always causes trouble when used in combination with lossy file formats such as JPG. That is because some pixel colors are approximated, they do not remain pure RGB(255, 0, 255).

True, but I used a .BMP file.

Thanks for your positive inputs on this article, I hope someone finds it useful and can use it to make great commercial games :)






 User Rating: 1039   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:

I decided not to use any forms of batching to keep the article more simple for beginners to use. I'm sure anyone who knows how to add static/dynamic batching can do so themselves. Just wanted to make it noob friendly.


I'm kind of an opengl noob, but im interested in how this batching would be implemented. Does opengl itself facilitate batched drawing calls somehow?

 User Rating: 1042   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Does this approach of GL_NV_texture_rectangle has any performance (or any other) advantages over using normal textured quads? I'm talking about immediate mode in both cases.


Koshmaar

Magic Pencil | SDL_Config (Homepage, Download) )


 User Rating: 1292   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by bitshit
Quote:

I decided not to use any forms of batching to keep the article more simple for beginners to use. I'm sure anyone who knows how to add static/dynamic batching can do so themselves. Just wanted to make it noob friendly.


I'm kind of an opengl noob, but im interested in how this batching would be implemented. Does opengl itself facilitate batched drawing calls somehow?


If you're an OpenGL noob, I'd recommend you learn more about how to use batching in OpenGL if you don't already. When you have experience in that area, adding it won't be a problem. Here's a nice thread I found on the subject: http://www.gamedev.net/community/forums/topic.asp?topic_id=395980&whichpage=1�

Quote:

Does this approach of GL_NV_texture_rectangle has any performance (or any other) advantages over using normal textured quads? I'm talking about immediate mode in both cases.

It depends on what you're using it for. For a power of 2 texture, the performance difference wouldn't be noticeable. But using GL_TEXTURE_2D when using a non-power of 2 texture created a noticeable impact on my framerate. When I use texture rectangles, the problem went away. It's totally up to you.

For more information on how this extension works and it's limitations, read this article on nvidia.com:

http://developer.download.nvidia.com/opengl/specs/nvOpenGLspecs.pdf

I hope this helps :)

 User Rating: 1039   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by Tojiro67445If you really want to be efficient (and match the D3DX interface better) you would be far better of using Vertex Buffer Objects or at the very least Display Lists.


My Dirk Dashing game uses essentially the same technique described in this article. My engine does lots of sorting and culling to limit the amount of data going to the card, and that works very well. The game runs fine on 1GHz or better desktops, but has some issues on laptops and older machines where OpenGL isn't well-supported in hardware. I would love to be able to speed up the game performance to better accomodate these machines.

I am unclear about how to effectively use VBOs or display lists in a 2D game, where there are lots of animated sprites that are always changing (e.g., the texture changes every frame or so as the characters run, jump, etc). I've read about VBOs and display lists and looked at code samples, but I don't see how these can help when my sprites only have 4 vertices each, they don't touch other sprites (so I can't blast a whole bunch of vertices to the renderer in one shot), and the texture is always changing.


 User Rating: 1034   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I’m currently designing my first 2D game in OpenGL (I have written only 3D application before...).
In my design every sprite that want to be rendered must be registered to a sprite manager class. That class keep track of the positions and write them to a dynamic VBO when needed. The sprite manager class will probably also sort the sprites based on the texture used (a texture will contains more than one frame of the animation - maybe also more than one object - to be able to write the maximum number of sprites in a single API call). I don’t know if it’s the best design.

 User Rating: 1106   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Nice article!

Quote:
Original post by GolfHacker
I am unclear about how to effectively use VBOs or display lists in a 2D game, where there are lots of animated sprites that are always changing (e.g., the texture changes every frame or so as the characters run, jump, etc). I've read about VBOs and display lists and looked at code samples, but I don't see how these can help when my sprites only have 4 vertices each, they don't touch other sprites (so I can't blast a whole bunch of vertices to the renderer in one shot), and the texture is always changing.


Perhaps a texture atlas can help here? It would require some intelligent grouping and sorting but it can reduce state changes for textures.

 User Rating: 1283   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by DeadXorAlive
Perhaps a texture atlas can help here? It would require some intelligent grouping and sorting but it can reduce state changes for textures.


Thanks for the good suggestion. I'm already doing this to a certain extent, at least for static background objects that are not animated. It's not too feasible for dynamic sprites that have their own unique animations.

I used gDEBugger to help me minimize state changes, so the state changes aren't really the bottleneck anymore. And applying various culling techniques has helped me minimize the amount of polygons I'm sending to the card per frame. So I think I'm about as optimized as an immediate-mode application can be. Everybody keeps telling me I shouldn't be using immediate mode, but I am unclear how to do a 2D game without using immediate mode.

@apatriarca: as I understand it, VBOs should be fine for geometry that doesn't change frequently. The idea behind a VBO is to minimize data transfer per frame by storing geometry that doesn't change often directly on the card, and just passing a reference to the VBO. If the geometry does change frequently, then you have to send the VBOs to the GPU every frame, so VBOs wouldn't help you save much bus traffic (if any). This whitepaper is one of the references I've been reading that explains it well: http://www.spec.org/gwpg/Mar2_06/opc.static/vbo_whitepaper.html.

 User Rating: 1034   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

You can use vertex arrays for a 2D game in a similar way to immediate mode. I haven't done benchmarks myself yet, but I remember a talk (can't find it, sorry) in which was said that immediate mode is very hard for the driver to optimize for and vertex arrays will provide better performance for this reaon alone. I think it's worth to try it, it's not much work, or did you already?

 User Rating: 1283   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by GolfHacker
Quote:
Original post by DeadXorAlive
Perhaps a texture atlas can help here? It would require some intelligent grouping and sorting but it can reduce state changes for textures.


Thanks for the good suggestion. I'm already doing this to a certain extent, at least for static background objects that are not animated. It's not too feasible for dynamic sprites that have their own unique animations.

I used gDEBugger to help me minimize state changes, so the state changes aren't really the bottleneck anymore. And applying various culling techniques has helped me minimize the amount of polygons I'm sending to the card per frame. So I think I'm about as optimized as an immediate-mode application can be. Everybody keeps telling me I shouldn't be using immediate mode, but I am unclear how to do a 2D game without using immediate mode.

@apatriarca: as I understand it, VBOs should be fine for geometry that doesn't change frequently. The idea behind a VBO is to minimize data transfer per frame by storing geometry that doesn't change often directly on the card, and just passing a reference to the VBO. If the geometry does change frequently, then you have to send the VBOs to the GPU every frame, so VBOs wouldn't help you save much bus traffic (if any). This whitepaper is one of the references I've been reading that explains it well: http://www.spec.org/gwpg/Mar2_06/opc.static/vbo_whitepaper.html.

When you use the immediate mode the driver knows nothing about what you want to do and can’t do any optimization. VBOs are mode driver-friendly and can also be used with dynamic scenes. In the link you gave me I have for example read the following sentence: “VBOs give applications the flexibility to be able to modify data without causing overhead in transfer due to validation.” Dynamic VBOs can also help to save memory traffic by allowing the update of subsets of the buffer. I think in OpenGL 3 VBOs will be the only way to send geometry to the GPU.

I really don’t see any reason to prefer immediate mode to other methods. Instead of calling several functions you write the data in an array and then call a function.

 User Rating: 1106   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I didn't see anyone else mention this, but with the presence of GL_ARB_texture_rectangle why did you use GL_NV_texture_rectangle in the tutorial? (also isn't texture rectangle core by now?)

cheers
-Dan

 User Rating: 1174   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Sorry for the slow reply, but you're right, I should have used the ARB instead of NV, but either one works fine.

 User Rating: 1039   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: