Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 380
Mikhail Sidorov Avatar asked Oct 12 '25 06:10

Mikhail Sidorov


2 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()
like image 153
PeterT Avatar answered Oct 14 '25 18:10

PeterT


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.

like image 39
datenwolf Avatar answered Oct 14 '25 20:10

datenwolf