Skip to main content
gamedev.net
🔒 Locked

Masking

Started by Geometrian 12 replies 2.1k views
Original Post
Geometrian
Geometrian
Hi, I received a document from someone when I last talked here with them on masking. It turned out, however, that it was not self-explaining enough for me. (I'm somewhat new to OpenGL). I am using python and PyOpenGL. I need to know the code to mask part of a texture. I want to mask (see though) one color in the texture. I believe that there was something about using a black and white image and having the texture be drawn on the white part later. How exactly this translates into python code is my problem. Thx, Geometrian
[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]
Hodgman
Hodgman
I believe what you are referring to is called "colour-key transparency" - where you designate one colour to be the transparent parts of the image - like a blue-screen effect.

OpenGL (or Direct3D) won't do this for you. What you need to do is convert your RGB image to an RGBA image on the fly.

something like this psudocode:
srcPixels = Colour[width][height] //load RGB image from a file etc...dstPixels = new ColourWithAlpha[width][height] //make a new RGBA image in memorycolourKey = Colour(0,255,0) //green shall be our transparent colour//for each pixelfor x=0 ; x<width; ++x{	for y=0 ; y<height; ++y	{		//copy the RGB components to the new image		dstPixels[x][y].red   = srcPixels[x][y].red		dstPixels[x][y].green = srcPixels[x][y].green 		dstPixels[x][y].blue  = srcPixels[x][y].blue		//check if the pixel is a "transparent" pixel, and set the alpha		if( srcPixels[x][y] == colourKey )			dstPixels[x][y].alpha = 0		else			dstPixels[x][y].alpha = 255	}}
Geometrian
Geometrian
How would this work in python? Sorry, I'm terrible in C++.
[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]
Hodgman
Hodgman
Its been a few years since I touched python, and havent used PyOpenGL, so I probably can't help you much, but...

How are you loading your textures in the first place?

Is there somewhere in your code where you have access to an array which represents your texture? If so, then this is the place where you need to implement the above idea...

Your texture will be an array of bytes "3 x Width x Height" large (RGB), you need to make a new array that is "4 x Width x Height" large (RGBA). and for each pixel (group of 3 bytes) in the original array, copy them into the new array followed by an alpha value (which is determined by comparing the RGB values with the colour-key value). You can then throw away the original RGB array and use the RGBA one instead.

If you post some texture-loading code I might be able to help more :(
Geometrian
Geometrian
Here: (this is python)

File = os.path.join('Data/Final','Image.bmp')
Surface = pygame.image.load(File)
Data = pygame.image.tostring(Surface, "RGBX", 1)
[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]
Hodgman
Hodgman
ah, you're using pygame... It probably has a function to do this for you
something like:

key = pygame.color.Color('green')File = os.path.join('Data/Final','Image.bmp')Surface = pygame.image.load(File)Surface.set_colorkey(key)Surface = Surface.convert_alpha()

Geometrian
Geometrian
Thanks,
This code looks promising. I want to use (255,255,255) white. I substituted white in for green and it replaces all white parts of my texture with black- you still can't see through it. I set it up like this:

key = pygame.color.Color('white')
File = os.path.join('Data/Final','Image.bmp')
Surface = pygame.image.load(File)
Surface.set_colorkey(key)
Surface = pygame.Surface.convert_alpha(Surface)
Data = pygame.image.tostring(Surface, "RGBX", 1)

[Edited by - Geometrian on April 12, 2007 3:17:15 PM]
[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]
Hodgman
Hodgman
ok, sounds like you are creating the RGBA texture properly, but alpha blending isn't turned on when you render it..

Not sure how to enable alpha blending in pygame, but If i were to have a guess:
Surface = pygame.Surface((Surface.get_width(), Surface.get_height()), SRCALPHA, Surface)


in C i would write something like this before I drew the image...
glEnable( GL_BLEND );glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );//... draw somethingglDisable( GL_BLEND );
Geometrian
Geometrian
Question: How do I put in one of those scrolling subwindows in a post, like you do to show code?
OK... I put it in like this:

key = pygame.color.Color('white')
File = os.path.join('Data/Final','Image.bmp')
Surface = pygame.image.load(File)
Surface.set_colorkey(key)
Surface=pygame.Surface((Surface.get_width(Surface),Surface.get_height(Surface)),SRCALPHA,Surface)
Surface = pygame.Surface.convert_alpha(Surface)
Data = pygame.image.tostring(Surface, "RGBX", 1)

...I get a blank (black) screen? I think that the problem lies in the order of these three lines?:

Surface.set_colorkey(key)
Surface=pygame.Surface((Surface.get_width(Surface),Surface.get_height(Surface)),SRCALPHA,Surface)
Surface = pygame.Surface.convert_alpha(Surface)
[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]
Hodgman
Hodgman
Quote:
Original post by Geometrian
Question: How do I put in one of those scrolling subwindows in a post, like you do to show code?

[*source*] and [/source*] (without the *'s)

Hmm I'm not sure, maybe try:
Surface=pygame.Surface((Surface.get_width(Surface),Surface.get_height(Surface)),SRCALPHA,Surface)
Surface.set_colorkey(key)
Surface = pygame.Surface.convert_alpha(Surface)

maybe you should try the pygame mailing list, there doesnt seem to be any pygame experts around at the moment :(
Geometrian
Geometrian
Sorry, that didn't work either. Because of your help, I can now understand at least part of the documentation. I'm now writing a test program as a separate project. If I get this program to work, I'll let everyone know here. Thanks for your help! I'll check back a few times later in case you wanted to add anything.
[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]
Geometrian
Geometrian
Ok... That didn't take very long. Hodgman's instruction let me see what the basic idea of masking is. Thanks! Here is the winning code: (In the code format too!)

surface = pygame.display.get_surface()MaskFile = os.path.join('Data','Image.bmp')MaskSurface = pygame.image.load(MaskFile).convert()MaskSurface.set_colorkey( (color), 0 )MaskedSurface = MaskSurface.convert_alphasurface.blit( (MaskSurface), ((x1,y1),(x2,y2)) )


Note that these are just the basic lines of code. In reality, they would be spread out over your program. Thanks again Hodgman!

Geometrian
[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]
Geometrian
Geometrian
It doesn't appear to need this line of code...
MaskedSurface = MaskSurface.convert_alpha

so you get:
surface = pygame.display.get_surface()MaskFile = os.path.join('Data','Data1.bmp')MaskSurface=pygame.image.load(MaskFile).convert()MaskSurface.set_colorkey((255,255,255),0)surface.blit((MaskSurface), ((blitx),(blity)))


I'm rechecking my program because while a basic pygame program (like this one) works, PyOpenGL does not. I put the same code into it but it doesn't work. I think that it's because PyOpenGL requires images to be in string format. i.e. :
surface = pygame.display.get_surface()MaskFile = os.path.join('Data','Data1.bmp')MaskSurface = pygame.image.load(MaskFile).convert()MaskSurface.set_colorkey((255,255,255),0)Data = pygame.image.tostring(MaskSurface, "RGBA", 1)#Later:  PyOpenGL drawingglBindTexture(GL_TEXTURE_2D, textures[texturenumber])glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, MaskSurface.get_width(), MaskSurface.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, Data );glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)glBegin(GL_QUADS)glTexCoord2f(0.0, 0.0); glVertex3f( x, y, z) glTexCoord2f(1.0, 0.0); glVertex3f( x, y, z)glTexCoord2f(1.0, 1.0); glVertex3f( x, y, z)glTexCoord2f(0.0, 1.0); glVertex3f( x, y, z)glEnd();

Note the Data = pygame.image.tostring() command. I did all of this like in the nehe.gamedev.net tutorials but it looks the same as if I had never tried to do any masking.

[Edited by - Geometrian on April 13, 2007 11:02:40 AM]
[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]
Geometrian
Geometrian
Alright. Here's how it's done. If you want SIMPLIFIED code, here it is:

import osfrom OpenGL.GL import *from OpenGL.GLU import *import pygame, pygame.imagefrom pygame.locals import *textures = [0]def resize((width, height)):    if height==0:        height=1    glViewport(0, 0, width, height)    glMatrixMode(GL_PROJECTION)    glLoadIdentity()    gluPerspective(45, 1.0*width/height, 0.1, 100.0)    glMatrixMode(GL_MODELVIEW)    glLoadIdentity()def init():    glEnable(GL_TEXTURE_2D)    glShadeModel(GL_SMOOTH)    glClearColor(0.0, 0.0, 0.0, 0.0)    glClearDepth(1.0)    glEnable(GL_DEPTH_TEST)    glDepthFunc(GL_LEQUAL)    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)def main():    video_flags = OPENGL|DOUBLEBUF        pygame.init()    surface = pygame.display.set_mode((640,480), video_flags)    resize((640,480))    init()    BackgroundFile = os.path.join('Data','Background.png')    ImageFile = os.path.join('Data','Image1.png')        BackgroundSurface = pygame.image.load(BackgroundFile).convert()    ImageSurface = pygame.image.load(ImageFile).convert()    ImageSurface.set_colorkey((0,0,0), 0)        BackgroundData = pygame.image.tostring(BackgroundSurface, "RGBA", 1)    ImageData = pygame.image.tostring(ImageSurface, "RGBA", 1)    while 1:        glEnable(GL_BLEND)        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)        glLoadIdentity()        glTranslatef(0.0,0.0,-5.0)        glRotatef(xrot,1.0,0.0,0.0)        glRotatef(yrot,0.0,1.0,0.0)        glRotatef(zrot,0.0,0.0,1.0)        glBindTexture(GL_TEXTURE_2D, textures[0])        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, BackgroundSurface.get_width(), BackgroundSurface.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, BackgroundData );        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)        glBegin(GL_QUADS)        glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0,  -2.0)        glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0,  -2.0)        glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0,  -2.0)        glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0,  -2.0)        glEnd();        glBindTexture(GL_TEXTURE_2D, textures[2])        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, ImageSurface.get_width(), ImageSurface.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, ImageData );        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)        glBegin(GL_QUADS)        glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0,  2.0)        glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0,  2.0)        glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0,  2.0)        glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0,  2.0)        glEnd();        event = pygame.event.poll()        if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):            break        pygame.display.flip()if __name__ == '__main__': main()

That's your entire program! But remember this: It will ONLY WORK if you save you mask to the alpha channel! Do this when you create your image in a paint program. (I have 'Paint Shop Pro 6', so I go "masks->new->from image", then a window pops up and click OK. Then "masks->save to alpha channel". Save it as anything and you are good to go)! Thx to _neutrin0_for these lines:
glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


Geometrian
[size="1"]And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.
[size="2"]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.