Quad-ren 2d Graphics Engine


hessiess

Member
Joined
Apr 26, 2008
Messages
219
Quad-Ren is a free, open source(LGPL), resolution independent 2D graphics
engine with the primary focuses being on simplicity and minimalism.
It was developed primarily for creating 2D games, with features such
as built in support for animations. Though there is nothing to
prevent it from being used for the development of other 2D applications
which rely heavily on bitmap images, and should function the same regardless
of screen resolution.

Quad-Ren implements a thin abstraction layer over OpenGL, to create an API
which should be more fermillier to developers used to using resolution dependent
tool kits such as SDL's blitting functions, but be totally resolution independent,
i.e. you can program a game, and it will run in a resizeable window, full screen
or on a portable platform like Pandora with absolutely no change to the source code.
(Though Pandora will probably require creating a lower res sprite set, but it will
still render at the same relative size).

Quad-Ren is programmed in, and usable from the C++ programming language,
though it is highly likely that future versions will also feature an
integrated scripting language for defining quad behaviours.It is primarily
intended for use on GNU/Linux, but because it only uses cross platform libraries,
compiling on other platforms should be possible.

Features
  • Resolution independence: Applications created with Quad-Ren will
    function the same regardless of screen resolution or aspect ratio.
    Aspect independence is achieved via the use of letter boxing, This is
    the only(IMO) way to achieve this, as stretching the image to fit looks
    ugly and simply showing more of the scene is likely to be an unfair advantage.
  • Bilinear filtered rotation: and scaling: Quads can be scaled and rotated
    smoothly, without the shimmering associated with nearest neighbour filtering.
  • Only alpha transparency: Only alpha transparency is supported, to allow for
    nice looking anti-aliased graphics and discourage the use of aliased images.
  • Free camera:Allows for easy scrolling around large scenes.
The current SDK can be downloaded here.

Quad-Ren is currently in fairly early development, so there are bound to be bugs,
so don't hesitate to report them, I will try to fix any issues as quickly as my limited
free time will allow. While I will be adding a lot more features in the future, most
notably collision detection, an event system and some kind of integrated scripting
language, the existing API should (crosses fingers) remain relativity unchanged.
This is *NOT* intended to become a visual point and click game building system.

Currently this is based on OpenGL and SDL, but all geometry transformations are done in
software, so it should be relativity easy to port to the pandora(although it is almost 100%
floating point internally), I am intending to re-wright the renderer to make it more modular,
alowing for easy multiple API support, i.e. OpenGL and OpenGL-ES.
 
Hi there,

I hope it's okay, if I criticize some points.

Your API relies on raw pointers, which shouldn't be used often in good C++ programs. I will give you an example:

CODE
qr_sprite *tux_s = qr_load_sprite("../media/tux.QRDD");
tux_s->do_something();
// ... more code
delete tux_s;


Imagine that in "more code" there is a "return 0;" or a "throw something;". This would result in a memory leak. Why don't you make it easier (and better) like this:

CODE
qr_sprite tux_s("../media/tux.QRDD");
tux_s.do_somthing();
// ... more code
// we don't need to free anything :)


I also dislike the idea of a new file format for animations. This forces developers to user your internal tool to create these files and they can't just overwrite them with GIMP or something similar. Why don't you use .tar files? Or just let accept paths to folders, which contain all the frames.

I also got a question, I'm sorry if the answer is obvious. What exactly is "letter boxing"? How do you avoid stretching on different aspect ratios?
 
Letter boxing means the engine automatically adds black bars either above / below or left / right of the image, so it can fit different aspect ratios without stretching.

Like when a widescreen movie has black bars on the top and bottom to display on a 4:3 television.
 
Jan-Nik said:
Hi there,

I hope it's okay, if I criticize some points.

Your API relies on raw pointers, which shouldn't be used often in good C++ programs. I will give you an example:

CODE
qr_sprite *tux_s = qr_load_sprite("../media/tux.QRDD");
tux_s->do_something();
// ... more code
delete tux_s;
Imagine that in "more code" there is a "return 0;" or a "throw something;". This would result in a memory leak. Why don't you make it easier (and better) like this:

CODE
qr_sprite tux_s("../media/tux.QRDD");
tux_s.do_somthing();
// ... more code
// we don't need to free anything :)


I also dislike the idea of a new file format for animations. This forces developers to user your internal tool to create these files and they can't just overwrite them with GIMP or something similar. Why don't you use .tar files? Or just let accept paths to folders, which contain all the frames.

I also got a question, I'm sorry if the answer is obvious. What exactly is "letter boxing"? How do you avoid stretching on different aspect ratios?


To be perfectilly honest, the API is inspired largely by Irrlicht, which also uses 'raw pointers'. I like this because it enables data to be re-used easily, instead of creating multiple copies of everything. If the sprites were stored on the stack as you are suggesting, ram usage would become a major problem, as every quad would
have a copy of the data, instead of just referencing the same data.

And because the renderer stores a pointer to all of the quads so it can render them, it would be easy to extend to clean up all of the quads and sprites automatically anyway.

The reason I created my own file format was so that all of the frames of an animation could be packed together into a single file, along with an animated collision mesh(probably in next release), scripting and anything else that becomes necessary. It is only intended as a archive format, not for editing. The PNG format, which is the input format is easily editable, this would then be packed into a QRDD file for use in the engine.

In my last game I used separate images, and the whole thing was turning into a giant mess, as it had arround 800 odd images. Which incedentilly were orgonided into files pritty well.

Try compileing the sample program to see what letterboxing is ;)
 
Last edited by a moderator:
Hessiess said:
To be perfectilly honest, the API is inspired largely by Irrlicht, which also uses 'raw pointers'. I like this because it enables data to be re-used easily, instead of creating multiple copies of everything. If the sprites were stored on the stack as you are suggesting, ram usage would become a major problem, as every quad would
have a copy of the data, instead of just referencing the same data.
That's where handle objects come in handy, which would allow you to use lazy evaluation/generation and data sharing much easier than manual create/destroy of the actual "core" data everywhere. Plus, that type of architecture lets you cache things much better and is a centralized location for inserting instrumentation hooks for profiling and debugging.
 
Last edited by a moderator:
White Flame said:
Hessiess said:
To be perfectilly honest, the API is inspired largely by Irrlicht, which also uses 'raw pointers'. I like this because it enables data to be re-used easily, instead of creating multiple copies of everything. If the sprites were stored on the stack as you are suggesting, ram usage would become a major problem, as every quad would
have a copy of the data, instead of just referencing the same data.
That's where handle objects come in handy, which would allow you to use lazy evaluation/generation and data sharing much easier than manual create/destroy of the actual "core" data everywhere. Plus, that type of architecture lets you cache things much better and is a centralized location for inserting instrumentation hooks for profiling and debugging.
I look into it. Would you say that Irrlicht has a bad design then?
 
Last edited by a moderator:
Hessiess said:
I look into it. Would you say that Irrlicht has a bad design then?
Not having used Irrlicht, I can't say. It pretty much depends on how low-level you want your APIs to be. Many commercial game devs still like having the barest features available to squeeze the most FPS they can with a lot of technical design.

If you're going to have your library be a simple wrapper on top of drawing rectangles, with the intent that any game abstractions will be above that, then yeah you might keep it as bare as possible. But if you want it to do more for the user, especially if it has to generate data itself that will affect the OpenGL state or require memory management, then creating a layer of indirection can let your code be much smarter and faster.
 
Last edited by a moderator:
White Flame said:
Hessiess said:
I look into it. Would you say that Irrlicht has a bad design then?
Not having used Irrlicht, I can't say. It pretty much depends on how low-level you want your APIs to be. Many commercial game devs still like having the barest features available to squeeze the most FPS they can with a lot of technical design.

If you're going to have your library be a simple wrapper on top of drawing rectangles, with the intent that any game abstractions will be above that, then yeah you might keep it as bare as possible. But if you want it to do more for the user, especially if it has to generate data itself that will affect the OpenGL state or require memory management, then creating a layer of indirection can let your code be much smarter and faster.
Currently its just intended to be an API for drawing textured rectangles with OpenGL. Collision detection will be implemented as another thin layer on top of this.
 
Last edited by a moderator:
Hessiess said:
To be perfectilly honest, the API is inspired largely by Irrlicht, which also uses 'raw pointers'. I like this because it enables data to be re-used easily, instead of creating multiple copies of everything.

That's true, but you should use smart-pointers for that or a global resource manager. AFAIK Irrlicht uses something like this.

QUOTE
If the sprites were stored on the stack as you are suggesting, ram usage would become a major problem, as every quad would
have a copy of the data, instead of just referencing the same data.

The data of sprites is stored into the graphic card's memory with glTexImage2D. You shouldn't keep a copy of that data after you've created the OpenGL texture. But you're right, you need some kind of resource manager to keep track of the created sprites.

QUOTE
And because the renderer stores a pointer to all of the quads so it can render them, it would be easy to extend to clean up all of the quads and sprites automatically anyway.

Okay, that's a good point. I would implement that as soon as possible.

QUOTE
The reason I created my own file format was so that all of the frames of an animation could be packed together into a single file, along with an animated collision mesh(probably in next release), scripting and anything else that becomes necessary. It is only intended as a archive format, not for editing.

But when I'm testing my application I might need to edit often, don't I?

QUOTE
In my last game I used separate images, and the whole thing was turning into a giant mess, as it had arround 800 odd images. Which incedentilly were orgonided into files pritty well.

What about putting all the frames of one animation in a folder?
 
Last edited by a moderator:
Yeah, if the mess of hundreds of images was organized well, doesn't that make it not a mess?
Also, I think there's something called sprite sheets, where you put several frames of animation into one image and modify texture coordinates to display different parts of the image. It keeps things organized, anyway.
 
Jan-Nik said:
To be perfectilly honest, the API is inspired largely by Irrlicht, which also uses 'raw pointers'. I like this because it enables data to be re-used easily, instead of creating multiple copies of everything.
That's true, but you should use smart-pointers for that or a global resource manager. AFAIK Irrlicht uses something like this.
The renderer is effectivly a global resource manager, as it directly or indirectly stores pointers to everything, and will handle object deletion when the renderer is destroyed.

If the sprites were stored on the stack as you are suggesting, ram usage would become a major problem, as every quad would
have a copy of the data, instead of just referencing the same data.
The data of sprites is stored into the graphic card's memory with glTexImage2D. You shouldn't keep a copy of that data after you've created the OpenGL texture. But you're right, you need some kind of resource manager to keep track of the created sprites.
Il probably make it store pointers to all created sprites as well as all of the quads.

The reason I created my own file format was so that all of the frames of an animation could be packed together into a single file, along with an animated collision mesh(probably in next release), scripting and anything else that becomes necessary. It is only intended as a archive format, not for editing.
But when I'm testing my application I might need to edit often, don't I?
Edit the source images and re-pack the QRDD, it only tackes one command, or hust use the PNG loader.

In my last game I used separate images, and the whole thing was turning into a giant mess, as it had arround 800 odd images. Which incedentilly were orgonided into files pritty well.
What about putting all the frames of one animation in a folder?
[/quote]
Works fine until you start adding additional stuff like collision meshes, then it gets hard to manage;)
 
Last edited by a moderator:
White Flame said:
Hessiess said:
To be perfectilly honest, the API is inspired largely by Irrlicht, which also uses 'raw pointers'. I like this because it enables data to be re-used easily, instead of creating multiple copies of everything. If the sprites were stored on the stack as you are suggesting, ram usage would become a major problem, as every quad would
have a copy of the data, instead of just referencing the same data.
That's where handle objects come in handy, which would allow you to use lazy evaluation/generation and data sharing much easier than manual create/destroy of the actual "core" data everywhere. Plus, that type of architecture lets you cache things much better and is a centralized location for inserting instrumentation hooks for profiling and debugging.

Welcome to Java! :lol:

Jan-Nik said:
The data of sprites is stored into the graphic card's memory with glTexImage2D. You shouldn't keep a copy of that data after you've created the OpenGL texture. But you're right, you need some kind of resource manager to keep track of the created sprites.

Can't video memory be overwritten with other crap? Or is that just on Windows?

I know that DirectDraw had to reload/verify textures when locking the screen and re-granting exclusive access(say, after alt+tabbing and re-entering).
 
Last edited by a moderator:
Kramy said:
White Flame said:
Hessiess said:
To be perfectilly honest, the API is inspired largely by Irrlicht, which also uses 'raw pointers'. I like this because it enables data to be re-used easily, instead of creating multiple copies of everything. If the sprites were stored on the stack as you are suggesting, ram usage would become a major problem, as every quad would
have a copy of the data, instead of just referencing the same data.
That's where handle objects come in handy, which would allow you to use lazy evaluation/generation and data sharing much easier than manual create/destroy of the actual "core" data everywhere. Plus, that type of architecture lets you cache things much better and is a centralized location for inserting instrumentation hooks for profiling and debugging.

Welcome to Java! :lol:

Jan-Nik said:
The data of sprites is stored into the graphic card's memory with glTexImage2D. You shouldn't keep a copy of that data after you've created the OpenGL texture. But you're right, you need some kind of resource manager to keep track of the created sprites.

Can't video memory be overwritten with other crap? Or is that just on Windows?

I know that DirectDraw had to reload/verify textures when locking the screen and re-granting exclusive access(say, after alt+tabbing and re-entering).
I think OpenGL handles this automatically.
 
Last edited by a moderator:
Jan-Nik said:
Your API relies on raw pointers, which shouldn't be used often in good C++ programs. I will give you an example:
It's statements like this that make people think C++ programmers are stupid.

Pointers are a part of C++ for a reason. They are the right tool for the job in situations like this. If said code throws an exception (which should only ever happen in EXCEPTIONAL circumstances, especially in a performance-sensitive game engine), then the code should be written with that in mind, for example by having the user use the standard library auto_ptr<> (and make sure you understand its behavior, because it is NOT identical to a pointer) or use the improved TR1/C++0x alternatives.

Asking developers to use custom wrappers is BAD BAD BAD and you should not even begin to recommend that kind of crap if you have a clue of good taste and design. Writing a pointer wrapper that has both zero overhead and which has correct and non-surprising behavior is very hard to do... which is half the reason why one wasn't part of the standard library until very recently (in TR1).

Exceptions don't happen at random times. They happen at very specific, well-defined times in clearly documented code paths, unless the code was designed by the kind of idiots I get to clean up after on a daily basis. Like the people who advocate pointer wrappers and avoiding pointers at all costs because their academia-focused professors lectured about exceptions causing memory leaks and decided to over-engineer a half-assed solution instead of just using the kind of proper design an actual experienced professional would use.

If you want a language that doesn't require you to think and makesuse of magic low-performance abstractions and safety guards everywhere, DO NOT USE C++. It's not the language you're looking for. You're just going to saddle yourself with the complexities of a language that demands very detailed low-level knowledge of the system, OS, and hardware with the platform design of a language that tries to hide the details of the system, OS, and hardware. You'd be better off using Java or C#, which in modern engines get more than adequate performance for games and are far closer to the level of skill and knowledge you're willing to work for.
 
Last edited by a moderator:
elanthis, well said.

people often don't realize what the strengths and weakneses of the abstractions they try to use actually are, and go for this or that just out of sheer prejudice, or because authority X told them so (where X is an arbitrary figure).

for the record, there are _much_ worse things to debug than memory leaks in a complex system. particularly when people decide they're 'too smart' to deal with such 'lowly' concepts as object ownership. ever been in cycle-referenced strong-pointer hell?
 
Ive started working on collision detection, and have a simple test program running which can detect a collision with a line segment and calculate the collision point.

collide_test.png


Quad-Ren is meant to be simple and minimalist, So I wont be using handles or other abstractions over the pointers. If you want these features, the source code is available ;)

Quad-Ren is now available on sourceforge https://sourceforge.net/projects/quad-ren/
 
Hessiess said:
[*] Bilinear filtered rotation: and scaling: Quads can be scaled and rotated
smoothly, without the shimmering associated with nearest neighbour filtering.
Ok so this means that instead of getting a pixelly looking image you get a blurry one.

That may be an ok tradeoff for some but to me using native resolution for a game (especially 2D hand drawn art) still looks much nicer than a bilinear blurred out one.
 
Last edited by a moderator:
DaveC said:
Hessiess said:
[*] Bilinear filtered rotation: and scaling: Quads can be scaled and rotated
smoothly, without the shimmering associated with nearest neighbour filtering.
Ok so this means that instead of getting a pixelly looking image you get a blurry one.

That may be an ok tradeoff for some but to me using native resolution for a game (especially 2D hand drawn art) still looks much nicer than a bilinear blurred out one.

Second.
 
Last edited by a moderator:
Back
Top