A moving texture layer with a transparent background?

Started by
3 comments, last by canary40 14 years, 4 months ago
Hello, I have not been able to find a solution to my somewhat unique problem on the internet. If anyone finds interest in this problem, I would greatly appreciate any help. The problem that I am about to describe is a little complicated. I hope I can make myself clear enough- if not, please ask for clarification. I am trying to program a simple little game in C++ where you can move a 2D doughnutshape (some PNG) around with arrow keys. However, there is a complicated graphics requirement. The doughnut must take its texture from another texture file (another PNG). However, the when the doughnut moves, the texture should change it's appearance. IMAGINE that the texture is sheet, and then another background sheet is placed over this sheet. If you could cut a hole in the background sheet and move the hole around, you would see different parts of the texture sheet underneath it. It is somewhat like a moving window. This is the effect that I hope to achieve. The biggest problem I am encountering is how to deal with the texture of the doughnut as well as how to keep the irregular shape of doughnut sprite's/PNG 's background transparent at the same time. In some sense, my problem how to reveal different backgrounds on different parts of the doughnut. I am using the Allegro and LoadPNG libraries, but I am open to new ideas as long as they are implementable. I realize that despite my best efforts to explain, there will still be much confusion regarding to what my problem still is. I will try my best to answer any questions if there are. The code looks something like this: ... set_color_depth(32); set_alpha_blender(); ... if (key[KEY_RIGHT]) x+=5; bmp = create_bitmap(SCREEN_W, SCREEN_H); blit(background, bmp, 0, 0, 0, 0, SCREEN_W, SCREEN_H); blit(texture, bmp, x, 0, x, 0, doughnut->w, doughnut->h); draw_trans_sprite(bmp, doughnut, x, 0); blit(bmp, screen, 0,0,0,0, SCREEN_W, SCREEN_H); ... The doughnut PNG has a transparent hole, but an opaque background. This will produce the effect of a moving window, but there is still the opaque background.
Advertisement
I don't know how to do this in Allegro [as I have never used allegro], but what you're looking for is the use of a stencil buffer. The application process would effectively be the reverse of what you've described. You would draw everything but the doughnut. You would then draw the doughnut to the stencil buffer, and then draw the texture you want the doughnut to reveal with the stencil in place [thus only drawing that texture where the doughnut was present in the stencil buffer], either over the entire screen, or over just the doughnut region with adjusted texture coordinates. You may need to invert your doughnut png, so that it is an opaque hole with a transparent background, depending on how you do things.

A quick search of your allegro docs should reveal a fair bit about this process. It would make sense that allegro would call it the same thing, as this is what it is pretty consistently referred to as in graphics.
First of all, thank you for your prompt reply.

Stencil buffering seemed like a really interesting idea to solving my problem. However, after some hours of fruitless searching for simple 2D examples, it seemed that I would have to learn some OpenGl at the very least to use it. This is not a bad thing, but perhaps there is another way.

Inspired by the stencil buffer concept, I tried processing the bitmap pixel by pixel. If a a certain specified colour of pixel (e.g. HOT PINK) is identified, the program will put a pixel from the texture bitmap to the doughnut bitmap. This method, however requires a lot of looping through bitmaps. I have achieved the desired result, but am worried about optimization. Is this a valid way to do this? If I am making a more complex game with more sprites and textures, will I be able to keep the framerate of the game up?
Here is some updated code.

...
for (int x = 0; x <= blit(buffer, screen, 0,0,0,0, SCREEN_W, SCREEN_H);->w; x++){
for (int y = 0; y <= doughnut->h; y++){
if (getpixel(doughnut, x, y) == -65281){ //hot pink
putpixel(bmp, x, y, getpixel(texture, xx+x, y)); //the xx+x is //just a way to move the texture accordingly when the dougnut moves
}
else if (getpixel(doughnut, x, y) == -16711681){ //cyan
putpixel(bmp, x, y, getpixel(bg, xx+x, y));
}
}
}
...
blit(bmp, buffer, 0,0,xx,0, bmp->w, bmp->h);
blit(buffer, screen, 0,0,0,0, SCREEN_W, SCREEN_H);
...

Hot pink pixels will be replaced by texture pixels, while cyan pixels will be replaced by background pixels. But is there a more efficient method? I am willing to learn some OpenGl to implement this (but will have to use AllegroGl if I do decide to use OpenGL)

A side Allegro-specific question: Will set_draw_mode(); have any uses to solving this problem? I'm not quite sure how to use it, but it seems to have some relevant uses.
Sorry I didn't read all your post.
So you want to move the hole before the background?
One way I can think:
1.render the scene that you want to see through the hole
2.render the hole |with alpha testing enabled and disabling color writes| in front of the scene (so you wont notice anything, but the depth buffer is set properly)
3.render the background between the hole and the scene.

Since the depth test is enabled all the time, the background won't be drawn in the hole
2   ----      hole3---    ----- occluder background1------------ scene to be seen through the hole

I'm sure it's simple to do in allegro.

An other idea (which is a lot harder)
1.render the scene |that you want to see through the hole| to an offscreen texture
2.render the occluder background onscreen
3.use multitexturing (with multiplication) and blending to render the hole:
the hole is a white texture but with the hole texture in its alpha channel, and openGL multiplies it with the scene texture |created in 1st pass|, so if alpha=0, scene is fully transparent( = not visible ).

This way you can have smooth transition at the edges of the hole.
Thanks very much for your replies. I am currently taking a look at SDL and OpenGL. I believe I will be able to solve my problems thanks to your inputs.

This topic is closed to new replies.

Advertisement