我需要在图像上绘制某种形状的颜色。我的想法是提供具有给定形状(例如心形)的蒙版,然后用颜色填充矩形区域,然后使用该蒙版在最终图像上进行渲染。
矩形颜色是在运行时决定的-这就是为什么我不自己绘制彩色心形的原因。
除了心脏(alpha为255)以外,黑色心脏图像都是透明的(alpha为0)。 我尝试使用:
glBlendFunc(GL_DST_ALPHA, GL_ZERO)
其中源是纯色,目标是Alpha通道图像。 我用https://www.andersriggelsen.dk/glblendfunc.php寻求帮助。
但是底部图像(树)被用作DST图像... 似乎我需要一个中间缓冲区来首先渲染蓝色心形,然后再对树进行第二个渲染。
这是怎么做的?
答案 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
是透明白色的心形。
结果:
原理是,在旧版OpenGL管道中,可以在glColor*
之前使用glVertex*
来指定一种颜色,该颜色将纹理颜色(在这种情况下为白色或透明)乘以逐分量。
请注意,使用这种方法,您可以轻松地以多种不同的颜色渲染多种颜色的形状,而无需清除(相对昂贵的)模板缓冲区。我建议将蒙版纹理裁剪到实际蒙版形状的边界,以节省GPU丢弃所有透明片段的工作量。