Mikhail Sidorov
Mikhail Sidorov

Reputation: 43

pyglet: blit a texture with specified alpha mask

How to blit a texture with additional alpha mask specified? Simply speaking, I want to make something like this:

example

Upvotes: 4

Views: 2984

Answers (3)

John C
John C

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

PeterT
PeterT

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

datenwolf
datenwolf

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

Related Questions