Reputation: 43
How to blit a texture with additional alpha mask specified? Simply speaking, I want to make something like this:
Upvotes: 4
Views: 2984
Reputation: 6527
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.
Upvotes: 0
Reputation: 8284
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()
Upvotes: 4
Reputation: 162297
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.
Upvotes: 1