OpenGL:在背景图像上用遮罩绘制颜色

时间:2019-09-03 09:56:36

标签: opengl

我需要在图像上绘制某种形状的颜色。我的想法是提供具有给定形状(例如心形)的蒙版,然后用颜色填充矩形区域,然后使用该蒙版在最终图像上进行渲染。

Color 掩盖:

Mask  加号

Base  等于:

Final

矩形颜色是在运行时决定的-这就是为什么我不自己绘制彩色心形的原因。

除了心脏(alpha为255)以外,黑色心脏图像都是透明的(alpha为0)。 我尝试使用:

glBlendFunc(GL_DST_ALPHA, GL_ZERO)

其中源是纯色,目标是Alpha通道图像。 我用https://www.andersriggelsen.dk/glblendfunc.php寻求帮助。

但是底部图像(树)被用作DST图像... 似乎我需要一个中间缓冲区来首先渲染蓝色心形,然后再对树进行第二个渲染。

这是怎么做的?

2 个答案:

答案 0 :(得分:1)

如果树是之前绘制的,它将以目标颜色显示并更改最终结果。

您是对的,您需要一个中间缓冲区来存储应该渲染的部分内容,并具有您的心形。

OpenGL为此提供了一个完美的工具,称为模具缓冲区。

在您的情况下,我将像平常一样渲染场景(树)

然后我将启用模板缓冲区glEnable(GL_STENCIL_TEST);

禁止写入colorBuffer glColorMask(false, false, false, false);

仅用适当的面膜绘制心脏。 glStencilMask(0xFF);

然后使用glStencilFunc(GL_EQUAL, 1, 0xFF)

的模版测试启用功能绘制彩色四边形

别忘了glClear(GL_STENCIL_BUFFER_BIT);每帧都要清除模板缓冲区

您可以在线找到一些不错的教程:https://learnopengl.com/Advanced-OpenGL/Stencil-testing

答案 1 :(得分:1)

这是不需要模板缓冲区的传统OpenGL(我假设您正在使用)中执行此操作的一种非常简单的方法:

public void render() {
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);

    glLoadIdentity();
    glOrtho(0, 1, 1, 0, 1, -1);

    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    // Regular blending
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glEnable(GL_ALPHA_TEST);
    // Discard transparent pixels. Not strictly necessary but good for performance in this case.
    glAlphaFunc(GL_GREATER, 0.01f);

    glColor3f(1,1,1);
    glBindTexture(GL_TEXTURE_2D, treeTexture);
    drawQuad();

    glColor3f(1,0,1); // Your color goes here
    glBindTexture(GL_TEXTURE_2D, maskTexture);
    drawQuad();
}

private void drawQuad() {
    glBegin(GL_QUADS);
    glTexCoord2f(0,0);
    glVertex2f(0,0);
    glTexCoord2f(0,1);
    glVertex2f(0,1);
    glTexCoord2f(1,1);
    glVertex2f(1,1);
    glTexCoord2f(1,0);
    glVertex2f(1,0);
    glEnd();
}

在这里,treeTexture是树的纹理,maskTexture透明白色的心形。

结果:

enter image description here

原理是,在旧版OpenGL管道中,可以在glColor*之前使用glVertex*来指定一种颜色,该颜色将纹理颜色(在这种情况下为白色或透明)乘以逐分量。

请注意,使用这种方法,您可以轻松地以多种不同的颜色渲染多种颜色的形状,而无需清除(相对昂贵的)模板缓冲区。我建议将蒙版纹理裁剪到实际蒙版形状的边界,以节省GPU丢弃所有透明片段的工作量。