How to blit a texture with additional alpha mask specified? Simply speaking, I want to make something like this:
-
Nice lady, do you know her? ;) Just kidding. You need to look into alpha blending. I haven't done it in pyglet yet, so I'm not able to provide valuable help. – Constantinius Jan 10 '12 at 11:00
-
unless you want to do it on the CPU or in a shader you need to do it this way: `... //draw the mask gl.glEnable(GL_BLEND); gl.glBlendFunc(GL_DST_COLOR, GL_ZERO) draw the second picture` And if you want to render it ontop of something else then do this with a texture as rendertarget. Also the lady is the famous "lena" picture that was used in a lot of image-processing papers – PeterT Jan 10 '12 at 12:12
-
@PeterT This seems to be close to what I want but could you explain how to perform this with a texture as rendertarget? I can't figure it out really. – Mikhail Sidorov Jan 11 '12 at 20:04
3 Answers
Somehow I doubt that your driver supports the FrameBufferObject extension if it doesn't provide shaders but it's worth a shot. Well this isn't quite what you want so, you'll probably have to use glTexEnv
after all or be a little more clever about it then me but this applies a mask to and image but doesn't actually add the alpha value:
import pyglet
from pyglet.gl import *
window = pyglet.window.Window()
image = pyglet.resource.image('pic.jpg')
mask = pyglet.resource.image('mask.jpg')
createdtex=False;
imagetex = 0
@window.event
def on_draw():
window.clear()
global createdtex
texfrmbuf =(GLuint*1)()
global imagetex
if createdtex!=True:
imagetex = image.get_texture()
glEnable(GL_BLEND)
glBlendFunc(GL_ZERO, GL_SRC_COLOR)
glGenFramebuffersEXT(1,texfrmbuf)
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT,texfrmbuf[0])
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT, imagetex.target,imagetex.id,0)
mask.blit(0,0)
glFlush()
glDisable(GL_BLEND)
glDeleteFramebuffersEXT(1,texfrmbuf)
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT,0)
createdtex=True
imagetex.blit(0,0)
pyglet.app.run()

- 7,981
- 1
- 26
- 34
-
Although your answer is not the exact solution, I'll accept it because you've really helped me to find the right way eventually. Here is the working code: http://paste.pocoo.org/show/534457/ Thank you and cocos2d's source code for help (: – Mikhail Sidorov Jan 13 '12 at 22:06
-
@Pevzi feel free to post that as your own answer and mark it as such. If you want to reward me then you can always just upvote me. – PeterT Jan 14 '12 at 08:58
-
Alas @MikhailSidorov your paste has disappeared from Net. Can you gist it maybe ? I have exact same problem. – Neon22 Jun 06 '18 at 20:43
This is most easy accomplished using a fragment shader:
uniform sampler2D image;
uniform sampler2D mask;
varying vec2 texcoord;
void main()
{
gl_FragColor.a = texture2D(mask, texcoord);
/* we use pre multiplied alpha */
gl_FragColor.rgb = texture2D(image, texcoord) * gl_FragColor.a;
}
Combine this with the glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
and you got what you want. If you can not or don't want to use shaders, this can be done using multitexturing and a texture combiner environment:
(it's been an awful long time since I used texture combiners the last time, so this may, no probably will have some mistakes):
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
And then you also have to juggle with texture units and other obscure state switches. Personally I prefer shaders.

- 159,371
- 13
- 185
- 298
-
Unfortunately, my netbook's video driver doesn't support any shaders at all, while the multitexturing is quite difficult for me so far. But if I don't find any other suitable solution I'll end up using a fragment shader. Thank you for your answer. – Mikhail Sidorov Jan 11 '12 at 19:50
There's a slightly easier way to add an alpha mask to an image, in Pyglet. Based on this sample code for displaying an image, there are two things you'd need.
First, these lines:
# Enable alpha blending, required for image.blit.
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
Second, you'd need to combine the image and mask, into one .png file. Put the mask into an Alpha Channel (which the .png format supports). Then when you blit the image, it will show up with transparency enabled. (It might work with two separate files, but when I tested it, I use a single combined image.)
Look at the sample code above for more details. In it, the author also draws a checkerboard background so the transparency effect is more obvious.

- 6,285
- 12
- 45
- 69