gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS homebrew announcements > Easy GL2D(A Fast & Easy to use 2D lib)

#175458 - relminator - Thu Nov 25, 2010 7:45 am

A very small, simple, yet very fast DS 2D rendering lib using the DS' 3D core.

[Images not permitted - Click here to view it]
[Images not permitted - Click here to view it]


Download:

http://rel.phatcode.net/junk.php?id=117


Quote:
Notice:
* glColorTable() has been deprecated since the release of libnds 1.5.0.
Because of the it, stencil effects are not possible w/o some hacks so I just disabled it altogether. However, rendering sprites in any palette is a lot easier now since palettes are automatically managed by libnds.

* You also need to tell libnds what VRAM bank you want allocate for
texture palettes. See the example files.


Quote:
Update 02/17/2011

* Code overhaul for libnds 1.5.0 compatibility
* Added 2 parameters to glSpriteLoad() and glSpriteLoad()
* Fixed the examples to reflect changes
* Doxygen generated reference
* Bug fixes(reported by Enay, Mhaun, Alex Sinclair, etc)

Update 11/25/2010

* Documentation and user's guide done. (User's guide is also a mini-tutorial of sorts)
* Added a dual_screen example.
* Updated the sprites example

Update 11/23/2010

* Fixed a bug where drawing primitives messed up the sprite colors. (missing currenttexture = 0 call)



Reasons to use Easy GL2D:

1. Library size is very small (less than 10 kb)
2. Very fast
3. Easy to maintain and refactor existing code
4. Abstracted interface
5. Code is easily portable to other platforms
6. Can combine 2D and 3D seamlessly
7. Almost unlimited palette usage in a single frame
8. Can handle non-power of 2 sprites
9. 3 types of translucency (2 via textures and 1 via polygon format)
10. Lots of sprite effects (colors, alpha, rotation, scaling, shearing, etc.)
11. Optimum VRAM use
12. Paletted(almost limitless) and high-color mode can be used together.


Limitations:

1. Emulators are slower in emulating the 3d hardware than the OAM.
2. glPutPixel, glLine and glBox only works on a real DS and No$GBA and not on deSmuMe.
3. You still have to learn how to use the sub OAM and sub BG since this lib is main engine
only. You can use the video capture to render on both screens but that would limit your
FPS and would use valuable VRAM.



Installation:

1 . Copy the distributable/libnds folder to your devkitPro directory.
or you can copy the /include and /lib folders under the /libnds directory of devkitPro.
ie.
*Assuming you installed devkitPro in c:/devkitPro/

c:/devkitPro/libnds/include/gl2d.h
c:/devkitPro/libnds/lib/libgl2d.a

2. Edit this line in your makefile and add gl2d before libnds
ie.
LIBS := -lnds9


to


LIBS := -lgl2d -lnds9




4. Add #include <gl2d.h> to your source.

5. Done! You can now use gl2d


Note:

Easy GL2D DS works perfectly on a Real DS.

However, if you are running this on an emulator...
No$GBA - works perfectly.
deSmuMe - use the soft rasterizer instead of OpenGL
_________________
http://rel.betterwebber.com


Last edited by relminator on Fri Feb 18, 2011 3:32 am; edited 1 time in total

#175618 - sverx - Wed Jan 05, 2011 4:56 pm

I've read the docs (and the source!) and it's very interesting!
Thanks for sharing it with us :)

#175621 - SchmendrickSchmuck - Fri Jan 07, 2011 10:12 pm

Relminator, I've tried using parts of your code in a 'framework' I've been working on, but I notice a severe slowdown when 500 sprites are shown simultaneously, and with 700+ the framerate slows down to what looks like 30 or even 15 fps. Do you experience similar slowdowns in your original version? Also, on an actual DS, when there's several sprites overlapping each other, they tend to 'clear out' some parts of the image, where on emulators they display just fine. Is this a depth issue, or a blending issue? I'm not at all familiar with openGL or 3D on the DS in general, so I was hoping you could help me out with that.

EDIT
I've tried auto-incrementing the depth for each sprite draw call, but it doesn't seem to fix anything. Please see GameFramework.nds on http://temp.dennisvanzwieten.com/ if I'm not making any sense.

#175624 - relminator - Mon Jan 10, 2011 3:34 am

sverx: No prob. It's just my small way of contributing to this community. BTW, I like your game. ;*)

SchmendrickSchmuck: Pretty nice demo. Slowdowns are certainly apparent on emulators as they emulate the 2d engine much better than the 3d engine. However on a real DS, I've never really gone down to 30 FPS even with more than 1000 sprites on screen. The only time I had slowdowns on a real DS is when I combined lots of vertex heavy 3d BG with 2d sprites.. I would assume your collision code is not well optimized. Try not to use floats (if you are using them) for collisions.
As for the overlap issue, the way I fixed them is to use a static global depth value resetted every frame and incremented every glSprite call. You will also notice that I pump 3 coords on my first glVertex call and just 2 on the other 3 verts for speed.

If all else fails, try to send your source on my e-mail and I'll see what I can do.
_________________
http://rel.betterwebber.com

#175626 - sverx - Mon Jan 10, 2011 11:23 am

relminator wrote:
[...] a static global depth value resetted every frame and incremented every glSprite call.


I saw that when watching the sources... and I was curious about the fact that you started from the back coming to the foreground... will this mean that if somebody tries to put too many objects in there there will be objects not appearing on top of others? Is there any other reason why you choosed to start from back and increment instead of starting from front and decrement?

Thanks :)

#175632 - relminator - Tue Jan 11, 2011 1:50 am

OpenGL uses the "right-handed" cartesian coordinate system where -z is farther than +z. So we add instead of subtract from that global depth buffer.

Edit: Oh you might want to use -2048 for znear in this statement:

Code:
glOrthof32( 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1024, 1 << 12 );


I made the mistake of setting z-near to -1024. Setting it to -2048 instead of -1024 would set Z = 0 to -2048 so you can blit 1500 sprites with no worries.
_________________
http://rel.betterwebber.com

#175635 - sverx - Tue Jan 11, 2011 10:23 am

I don't get what you mean (I'm sorry, it's my English that isn't as good as I'd like)...

Should we call the drawing functions from front to back, then? :|

#175639 - SchmendrickSchmuck - Tue Jan 11, 2011 8:19 pm

It can't be my collision, it slows down around 500 sprites even without. The collision code is just a couple of array index lookups anyway. I'm not using any floats as far as I know, unless dividing by 100 implicitly turns ints into floats before casting them back to ints.. I'll send you my source later, maybe you can find things I can further optimize.

Also, I think what sverx wants to know is why you chose back-to-front sprite rendering as opposed to front-to-back, and whether it has anything to do with sprites hiding others.

#175642 - DiscoStew - Wed Jan 12, 2011 4:44 am

Using floats on a device without an FPU uses up more CPU time because code for handling them is done via software instead of hardware, just as a reference.

When dividing, are you using '/', because if you are, then that's more cycles used up. Use the divide functions from libnds, as they reference the hardware divide and such.
_________________
DS - It's all about DiscoStew

#175644 - sverx - Wed Jan 12, 2011 11:21 am

if you use '/' between two ints, this won't turn them into float, of course. BTW if you want it to be faster just don't divide by 100, divide by 128 for instance, or just don't divide (multiply, if possible...)

#175652 - relminator - Thu Jan 13, 2011 9:37 am

sverx wrote:
I don't get what you mean (I'm sorry, it's my English that isn't as good as I'd like)...

Should we call the drawing functions from front to back, then? :|


When the system is "right-handed" (OpenGL is right-handed and D3D is left-handed), increasing the value of Z positively makes the vertex nearer.

ie. 100 is nearer than 50 in a right-handed system.

So by increasing that global depth buffer, We essentially draw our polygons from the far to near mimicking what is called the "painter's algorithm".

This could have been a non-issue if the DS hardware can disable depth-testing but Nintendo somehow didn't include it.


SchmendrickSchmuck: For a real 3D rendering engine, front to back is faster since it reduces fillrate(though I'm not sure if the DS's 3D hardware implements this optimization). Easy GL2D is a 2d renderer so, we cannot do front to back rendering. I tried that on my first attempts and as you already know, fragments don't get drawn correctly.

As sverx and DiscoStew already mentioned, divide only if possible by 2^n values as GCC can optimize it into a shift.
_________________
http://rel.betterwebber.com

#175657 - sverx - Thu Jan 13, 2011 11:16 am

relminator wrote:
[...] We essentially draw our polygons from the far to near mimicking what is called the "painter's algorithm".
[...] Easy GL2D is a 2d renderer so, we cannot do front to back rendering. I tried that on my first attempts and as you already know, fragments don't get drawn correctly.


This is curious. So you mean if I change your code and start painting near to far (the inverse of what I would do with the so called "painter's algorithm"), would I get into trouble? :| What issues I'd encounter?

#175658 - relminator - Thu Jan 13, 2011 11:22 am

sverx wrote:
relminator wrote:
[...] We essentially draw our polygons from the far to near mimicking what is called the "painter's algorithm".
[...] Easy GL2D is a 2d renderer so, we cannot do front to back rendering. I tried that on my first attempts and as you already know, fragments don't get drawn correctly.


This is curious. So you mean if I change your code and start painting near to far (the inverse of what I would do with the so called "painter's algorithm"), would I get into trouble? :| What issues I'd encounter?


One issue I faced was that far fragments in a polygon won't get drawn if they share the same location on the screen.
_________________
http://rel.betterwebber.com

#175659 - sverx - Thu Jan 13, 2011 12:14 pm

relminator wrote:
One issue I faced was that far fragments in a polygon won't get drawn if they share the same location on the screen.


...and you mean you get this behavior only when drawing in 'reverse' order? It's very curious... do you imagine any reason behind this?

#175660 - relminator - Thu Jan 13, 2011 12:47 pm

sverx wrote:
relminator wrote:
One issue I faced was that far fragments in a polygon won't get drawn if they share the same location on the screen.


...and you mean you get this behavior only when drawing in 'reverse' order? It's very curious... do you imagine any reason behind this?


Reverse or equal actually.

The only reason I could think of is that the DS 3d hardware optimizing to reduce fillrate (like almost all current PC GFX hardware).

ie. Only draw a fragment(pixel) if the said fragment is nearer than the value in the depth buffer.
_________________
http://rel.betterwebber.com

#175661 - sverx - Thu Jan 13, 2011 1:40 pm

I see, but I really think if it's so it's like a bug. I mean... shouldn't I be free to describe a 3D scene by describing everything that's in there in whatsoever order I want and obtain the same result? Really, I'm completely a newbie speaking about 3D, maybe there's something I miss...

#175662 - relminator - Thu Jan 13, 2011 2:47 pm

sverx wrote:
I see, but I really think if it's so it's like a bug. I mean... shouldn't I be free to describe a 3D scene by describing everything that's in there in whatsoever order I want and obtain the same result? Really, I'm completely a newbie speaking about 3D, maybe there's something I miss...


Yes on the PC side of things, you can disable depth-testing(usually done for z-sorted smoke effects or anything translucent). But the DS does not have that functionality. I wish it had since it would make implementing a 2D lib easier.

But if you are using some sort of depth-testing(or even a software z-buffer), that's just the way it works. Front-to-back is faster than back-to-front because it reduces the number of fragments drawn on the framebuffer.
_________________
http://rel.betterwebber.com

#175666 - sverx - Thu Jan 13, 2011 4:56 pm

I see. I was thinking that there wasn't any elaboration started before the end of the list of objects, so I was really thinking that it wouldn't change.
Good to know, thanks. :)

Does Grit or your texture packer supports texture formats 1 and/or 6? (those A3I5/A5I3 textures)

#175667 - relminator - Thu Jan 13, 2011 5:23 pm

sverx wrote:
I see. I was thinking that there wasn't any elaboration started before the end of the list of objects, so I was really thinking that it wouldn't change.
Good to know, thanks. :)

Does Grit or your texture packer supports texture formats 1 and/or 6? (those A3I5/A5I3 textures)


My texture packer certainly does not support that(I don't know a good image lib that supports those formats). Though you could texturepack then convert to any format you like in your own fav image editor.

I'm not sure about grit though.


In fact, I've never tried those formats yet. I don't even know where to start. Tell me if you find an image editor that supports it. I'd really love to use per-pixel alpha blending.

;*)
_________________
http://rel.betterwebber.com

#175668 - Rajveer - Thu Jan 13, 2011 7:44 pm

Tex Mex from Sausage Boy supports converting alpha images to formats 1 and 6, the latest version that I'm aware of is 0.04. There is a small bug, where if you are using a paletted texture without transparency, you have to use it with it's threshold command (-th) set to 0.

Here's a link http://blog.dev-scene.com/gaspcubed/2007/10/06/texmex-004/

#175673 - sverx - Fri Jan 14, 2011 10:29 am

I will try this Tex Mex, thanks, I didn't know about that. Actually the only test I've done with a A5I3 texture was done by using a 32-level grayscale bitmap (thus giving me a single color - per pixel alpha - texture. Quite simple, but not bad, really)

Oh, it even worked with per pixel blending with 2D backgrounds behind the 3D layer :)

#175845 - relminator - Fri Feb 18, 2011 3:37 am

I had just updated the lib.

Quote:
Notice:
* glColorTable() has been deprecated since the release of libnds 1.5.0.
Because of the it, stencil effects are not possible w/o some hacks so I just disabled it altogether. However, rendering sprites in any palette is a lot easier now since palettes are automatically managed by libnds.

* You also need to tell libnds what VRAM bank you want allocate for
texture palettes. See the example files.


Quote:
Update 02/17/2011

* Code overhaul for libnds 1.5.0 compatibility
* Added 2 parameters to glSpriteLoad() and glSpriteLoad()
* Fixed the examples to reflect changes
* Doxygen generated reference
* Bug fixes(reported by Enay, Mhaun, Alex Sinclair, etc)


also, go vote in the poll WinterMute set on devkitPro.org - http://devkitpro.org/viewtopic.php?f=25&t=2333
_________________
http://rel.betterwebber.com