Need help with masking

Started by
6 comments, last by kauna 16 years, 3 months ago
Hello, I want to be able to composite one image (the "object" image) onto another (the "background" image) using a third grayscale image (the "mask" image) as the alpha channel. ImageMagick has a command for this: composite image1 image2 mask result Unfortunately I don't know how to post images here, but I've zipped up an example of what I want to do at http://cpmaker.mameprojects.com/files/images.zip I have seem some examples of masking in OpenGL, but they usually involve a zero or one mask, not a grayscale image. What I have done so far is loading the object image as a texture, then copying the bytes from the mask image into the object's alpha channel, then blending the background and object images with GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA. That is slow and it also depends on the object and mask images being the same size. What I want to do is to load the object and mask images as textures and somehow render them as quads and have OpenGL do any necessary resizing of the images. I would appreciate any help, links to examples, or any kind of code I can use. Regards, Cakemeister
Advertisement

Hi,

So your problem is that your alpha mask isn't always the same size as the images ? Also, is the performance a concern ? I mean, what is the purpose of this program ?

Practically, you could create 3 different textures (the background, the foreground and the alpha). With the correct texture operations you should be able to make the system to use the separate alpha texture for the texture blending. This would work even with 3 different sized textures.

Usually alpha map has all the shades of grey available rarely/never just black or white.

Cheers!
My program is a front end application. It takes a list of items, displays them, and launches programs based on the users's input.

The program is meant to be used in a MAME cabinet. MAME is an arcade game emulator, which runs the exact code which ran on Pacman, Centipede, and other arcade games. When the user selects a game, my frontend launches MAME or another emulator.

My front end application can take an arbitrary set of images, text, and whatever and display them according to what the user has selected in the skin file. This "external alpha blending" is a feature that I want to add.

The background in the frontend is the default framebuffer. I could create a texture from it with glReadPixels, but I want to avoid that if possible, too slow.

If you want to check out my frontend there is a demo, which is a hefty 100+ megabytes: http://cpmaker.mameprojects.com/files/khdemo_full.zip

Hi,

So your application is totally OpenGL based and you want to blend nicely some images over a background image?

At this point I am not totally sure what is the trouble here. I mean, you draw your front end background first, then you'll draw another image on top of it with an alpha map. It doesn't require any complex render states, and it should be rather efficient.

I am not sure why you'd need glreadpixels or why do you need to manipulate texture alpha channel.

Can you show a little bit of some code? or point out a problematic solution?

Cheers!

Quote:Original post by kauna

Hi,

So your application is totally OpenGL based and you want to blend nicely some images over a background image?

At this point I am not totally sure what is the trouble here. I mean, you draw your front end background first, then you'll draw another image on top of it with an alpha map. It doesn't require any complex render states, and it should be rather efficient.

I am not sure why you'd need glreadpixels or why do you need to manipulate texture alpha channel.

Can you show a little bit of some code? or point out a problematic solution?

Cheers!


Alpha map? What's that?

Basically, my code does something like:

1) ... sort objects by z coordinate...
2) glBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3) for (all objects)
{
glBegin(GL_QUADS);
... standard map texture to screen coordinates
glEnd();
}

Is there a glBlendMode that copies only the alpha channel?

When I last tried just a standard masking operation, which was:
glBlendMode(GL_SRC_ALPHA, GL_ZERO);
--- draw mask image ---
glBlendMode(GL_ONE, GL_ONE);
--- draw object image ---

This would leave black areas around the masked area where the background should have shown through.

I can post some real source code if you need something more specific.

glBlendMode(GL_SRC_ALPHA, GL_ZERO);--- draw mask image ---glBlendMode(GL_ONE, GL_ONE);--- draw object image ---


Hi, yeah now I figure out your problem. You'll need to draw the mask and the texture in one pass (ie. have both textures binded at the same time with the required render states).

//ie.glBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);-- draw object image with alpha map


An Alpha map is the same as your mask, it is usually a gray scale image, since alpha information needs only one channel.

I don't know the OpenGL syntax for setting up the correct texturing parameters, but practically you'll need to use multitexturing, get diffuse color from the texture, and alpha from the mask image. That should be all, and your texture map and mask can have different pixel resolutions.

Best regards!
I'm very close. After studying the Nehe tutorials 6 and 22, I came up with this display code:

   // clear screen   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   glLoadIdentity();   glPushMatrix();   glTranslatef(0.0, 0.0, -5.0);   // first draw the background (image 1)   glBindTexture(GL_TEXTURE_2D, image_1_texture);   glBegin(GL_QUADS);   glTexCoord2f  (0.0f, 0.0f);   glVertex3f( -1.0f, -1.0f, 1.0f);   glTexCoord2f(0.0f, 1.0f);   glVertex3f( -1.0, 1.0f, 1.0f);   glTexCoord2f(1.0f, 1.0f);   glVertex3f( 1.0f,1.0f,  1.0f);   glTexCoord2f(1.0f, 0.0f);   glVertex3f(1.0f, -1.0f,  1.0f);   glEnd();   #if 1   // now draw the object image (image 2) masked by the mask image   glActiveTextureARB(GL_TEXTURE0_ARB);   glEnable(GL_TEXTURE_2D);   glBindTexture(GL_TEXTURE_2D, image_2_texture);   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);   glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);   glActiveTextureARB(GL_TEXTURE1_ARB);   glEnable(GL_TEXTURE_2D);   glBindTexture(GL_TEXTURE_2D, mask_texture);   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);   glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_BLEND);   glBegin(GL_QUADS);   glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0f, 0.0f);   glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0f, 0.0f);   glVertex3f( -1.0f, -1.0f, 1.1f);   glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0f, 1.0f);   glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0f, 1.0f);   glVertex3f( -1.0f, 1.0f, 1.1f);   glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1.0f, 1.0f);   glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0f, 1.0f);   glVertex3f( 1.0f,1.0f,  1.1f);   glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 1.0f, 0.0f);   glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0f, 0.0f);   glVertex3f(1.0f, -1.0f, 1.1f);   glEnd();   #endif   glPopMatrix();   glFlush();


If the ifdef is changed to a zero, the background image displays as expected. When the ifdef is a one, the bottom half of the image shows the object image (image #2) as expected, also, but the top half is blacked out.

I think the problem is somewhere in the multitexturing calls.

Hi,

I think that you are very close to the solution too, but too bad I cannot help you with the required OpenGL calls.

Good luck!

This topic is closed to new replies.

Advertisement