Sign in to follow this  
ToohrVyk

2D comic book effect

Recommended Posts

This is the effect I'm trying to achieve (more details below) : comic book image I have a list of rectangular sprites sorted by depth (they are represented by the blue and yellow patches above). I want to render them in a comic book fashion, so that there is a n-pixel gap between the borders of two such sprites, and a black one pixel border around each sprite. The problem happens when (as seen above) one rectangle overlaps another. In that case, I want to cut out a part of the deepest rectangle (I know which one is the deepest one as they are sorted by depth) so that the other sprite can be drawn entirely, AND there still remains a gap of n pixels between the border of the top sprite and the border of what is left of the bottom sprite. I still want there to be a one-pixel border around everything that is left of the bottom sprite. There are three useful things to know: - My API allows me to draw lines, rectangles and filled rectangles of any color, however it does not allow reading the pixels of the buffer (and drawing per-pixel would be very slow. - The sprites take a long time to be drawn, as they are generated every time I need to draw them. Although I could implement some kind of caching, that would require a serious rewrital of the system along with costly copies of a lot of data, which I cannot afford, so let's say I can only draw each sprite once. - You can safely assume that there is a "bottom" sprite that is below all the others, and that covers the entire screen. It would also be great if storing at least part of the computation results in order to reuse them if the positions of the rectangles do not change (but in some cases they might change a lot). Do you guys have any ideas about how this could be implemented?

Share this post


Link to post
Share on other sites
Well you will have to check sprites against one another if i understand you correctly with the API limitations. Either start at the bottom (simpler to implement) or the top (minimal overdraw).

I'll step through the start from bottom example

loop
draw current sprite

loop all sprites drawn before
if (this sprite overlaps sprite drawn before)
compute overlap rect area (x, y, widht, height) // should be trivial to get
draw borders (white n lines) // only inside the previous sprite (around this overlap area)
draw black line around borders drawn
end loop

next sprite
end loop


That looks like it would work, you might want to give the draw from top a try to minimize overdraw, it shouldn't be much harder to implement (before the sprite can be drawn you need to calculate out the area that it is drawn to which might end up having multiple small rects).

You can implement caching with the above, cache the rect that is the overlap area for the sprite for example and reuse it (plus other params to make it easier and faster).

HTH

Share this post


Link to post
Share on other sites
If all your sprites are actual rectangles (and if they're not, I wouldn't try solving this as if they are - tracing a 1-pixel border and so on is going to be a right ruddy pain), perhaps you can do something with a sort of subtractive 2D CSG? Starting with the top sprite, rendering it, then going through from top-to-bottom subtracting all already-rendered sprites from the current rect to end up with a (possibly concave) polygon at each step?

This'd be so much easier if you had a zbuffer...

Share this post


Link to post
Share on other sites
I think nts has it pretty much.
Top-down or bottom-up it doesn't really matter. This algorithm should take O(n-1^2 * 0.5) time, where n is the amount of objects being checked.

You'll have to do both vertex containment and edge intersection tests.
The results from these tests will tell you the corners of the new clipped boxes.

[Edited by - stevenmarky on February 11, 2005 2:18:42 AM]

Share this post


Link to post
Share on other sites
Fruny: I do have a stencil-bufferish option, but it's very limited: I can apply rectangular constraints on the buffer so that drawing only occurs in the (unique) rectangle I have selected. This kind of clipping can be trivially emulated with lines, rects and filled rects, and is not of a big use for sprites since I cannot draw them multiple times, and it won't happen very often that the sprite is clipped into another rectangular sprite.

nts: An excellent idea indeed, but it only applies to the white gap between images. I would still need to compute the black border of the clipped rectangles (since it requires knowledge from ALL clipping in order to be drawn).
Also, I cannot decide to draw the sprite "only" to a smaller area, unless that area is a rectangle (and I cannot afford drawing it multiple times for multiple rectangles).

superpig: my sprites are actual rectangles, and I guess that CSG would be a good solution. I'll have to look deeper into CSG algorithms though, because I don't know how to handle concave polygons and polygon splitting yet.

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
superpig: my sprites are actual rectangles, and I guess that CSG would be a good solution. I'll have to look deeper into CSG algorithms though, because I don't know how to handle concave polygons and polygon splitting yet.
If that's the case, full CSG is probably overkill (because you can take advantage of the fact that you're not dealing with arbitrary polys). You would need to preprocess all your rectangles, clipping topmost-rect-plus-white-border against lower-down-rectangles until you produce a set of structures something like this:


struct RenderableRect
{
int xMin, yMin;
int xMax, yMax;
bool bBorderLeft, bBorderTop, bBorderRight, bBorderBottom;
};

Share this post


Link to post
Share on other sites
SuperPig: that's a very interesting idea indeed! I just hadn't thought of making it this way. I'll use this method, as soon as I find a way to detect which sides of the rectangle should not be rendered.

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
SuperPig: that's a very interesting idea indeed! I just hadn't thought of making it this way. I'll use this method, as soon as I find a way to detect which sides of the rectangle should not be rendered.
Well, each of your sprites would start as one of those structures, with all border flags turned on.

You'd then repeatedly 'divide' rectangles - and the divided edge would have the border flags turned off - and then 'discard' pieces that are totally occluded - in which case you turn the border there back on.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this