如何设置混合函数OpenGL的两个重叠的对象(How to set blend function o

2019-10-29 05:21发布

您好我需要绘制一个圆角矩形。

我遵循上述图像的过程。 我第一次提请绿色矩形。 然后,我画了两个黑rectangles.And然后我画的边缘圈子,让拐角处圆。 现在是什么这样做后,我得到的是如下图所示。

正如可以看出的是,角落的社交圈对在那里它们与矩形重叠的部分少透明度。 但是,当不与矩形重叠的透明度。 矩形有一个Alpha设置为0.5F。 和圆也有0.5F阿尔法。 所以,这就是为什么它的重叠部分白色和透明的非重叠部分。 我想重叠部分具有相同的透明度为矩形,使得重叠圆部分不能seen.My混合函数是glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 我想了解更详细的混合功能在这里 。 但我什么都听不懂。 我的代码如下,

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, (int) screenWidth, (int) screenHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0.0f, (double)screenWidth / screenHeight, 0.0f, 1.0f, -1.0f, 1.0f);

glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glEnable(GL_COLOR_MATERIAL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_TEXTURE_2D);
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
glEnableClientState(GL_COLOR_ARRAY);

glVertexPointer(3, GL_FLOAT, 0, bubbleMiddleRectStartCoord);
glColorPointer(4, GL_FLOAT, 0, rectColor);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glVertexPointer(3, GL_FLOAT, 0, bubbleTopRectStartCoord);
glColorPointer(4, GL_FLOAT, 0, rectColor);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glVertexPointer(3, GL_FLOAT, 0, bubbleBottomRectStartCoord);
glColorPointer(4, GL_FLOAT, 0, rectColor);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

//smooth edge of the bubble rectangle
drawCircle(triangleAmount,bubbleEdgeRadius,bubbleMiddleRectStartCoord->upperLeft.x+bubbleEdgeRadius,bubbleMiddleRectStartCoord->upperLeft.y,255,255,255,128);
drawCircle(triangleAmount,bubbleEdgeRadius,bubbleMiddleRectStartCoord->lowerLeft.x+bubbleEdgeRadius,bubbleMiddleRectStartCoord->lowerLeft.y,255,255,255,128);
drawCircle(triangleAmount,bubbleEdgeRadius,bubbleMiddleRectStartCoord->upperRight.x-bubbleEdgeRadius,bubbleMiddleRectStartCoord->upperRight.y,255,255,255,128);
drawCircle(triangleAmount,bubbleEdgeRadius,bubbleMiddleRectStartCoord->lowerRight.x-bubbleEdgeRadius,bubbleMiddleRectStartCoord->lowerRight.y,255,255,255,128);

glDisableClientState(GL_COLOR_ARRAY);
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glDisableClientState(GL_COLOR_MATERIAL);
glDisable(GL_TEXTURE_2D);
swapBuffers();

rectColor具有价值

GLfloat rectColor[]=
{
    1.0f,1.0f,1.0f,0.5,
    1.0f,1.0f,1.0f,0.5,
    1.0f,1.0f,1.0f,0.5,
    1.0f,1.0f,1.0f,0.5
};

画圆函数生成的分圈,并绘制它。 该函数的拉入部是

glVertexPointer(2, GL_FLOAT, 0, vertices);
 glColorPointer(4, GL_UNSIGNED_BYTE, 0, color);
 glDrawArrays(GL_TRIANGLE_FAN, 0, triangleAmount+2);

谁能帮我解决这个问题? 谢谢。

编辑:这是它的外观采用这两种混合功能后。

Answer 1:

我看到你与此去,看你的结果,你可能只需要禁用交融,而你正在绘制遮罩(3个矩形和4圈),然后用glBlendFunc(GL_DST_ALPHA, GL_ZERO) 虽然这个如果没有已经绘制了现场才有效。

要解释你做了什么,还有你是画一个白色与0.5 alpha和混合它。 考虑在年初的像素颜色“目的地”是(0,0,0,0),并进入“源”始终是你的情况(1,1,1,.5)。 比方说,源颜色为“S”,目的是“d”,而成分(R,G,B,A),使源阿尔法是“sa”你写在你的混合功能是:

output = S*S.a + D*(1.0-S.a) = 
(1,1,1,.5)*.5 + (0,0,0,0)*(1.0-.5) = 
(.5, .5, .5, .25) + (0,0,0,0) =
(.5, .5, .5, .25)

所以当你画你的圈子在已经绘制矩形:

output = S*S.a + D*(1.0-S.a) = 
(1,1,1,.5)*.5 + (.5, .5, .5, .25)*(1.0-.5) = 
(.5, .5, .5, .25) + (.25, .25, .25, .125) =
(.75, .75, .75, .375)

造成的α差。 所以从这个,我希望你能理解的2个参数中的混合功能是指:第一,一本讲述什么因素用来乘源(进入)色,第二个是如何乘以目标颜色。 最后,他们加在一起。

因此,对于你的情况,你想对Alpha通道迫使一些价值无处不在,你画的图元。 为了实现这一目标,你需要S*1.0 + D*.0和参数是glBlendFunc(GL_ONE, GL_ZERO)虽然这是一样的只是禁止混合。 只有写这个原语会产生白色(灰色)圆角的矩形的透明度.5 ,而所有的休息是完全透明的。 现在,在这之后你需要设置混合函数来增加你进入的彩色与目的地阿尔法glBlendFunc(GL_DST_ALPHA, GL_ZERO)

编辑:

我不完全理解你要实现到现在什么。 正如我上面提到的,如果你已经得出了一些场景,这将不起作用。

与一些复杂的对象(在这种情况下,对象被重叠本身上某些部分)这将是最防弹使用模板缓冲区重叠现有的场景。 创建它很像深度缓冲,但你可能会认为这是另一种颜色通道,很容易吸引到它,并在以后使用它,所以你可能想看看它在某个时候。

你的情况很可能是安全的,说这是你的主缓冲区,是为显示。 在这种情况下,你可以使用Alpha通道:

要绘制只有你必须设置alpha通道glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE)当你完成后,把所有的参数设置为true。

  1. 要清除你要画一些色彩与希望的阿尔法全屏矩形Alpha通道(我建议你使用(1,1,1,1)只画到Alpha通道
  2. 要绘制掩模(3个rects和4圈)使用glBlendFunc(GL_ONE, GL_ZERO)和颜色(1,1,1, 1-desiredAlpha)
  3. 请你圆润的标签使用glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA)

因此,程序是:

//your background is drawn, time to overly labels
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glColor(1.0f, 1.0f, 1.0f, 1.0f);
//draw fullscreen rect
glBlendFunc(GL_ONE, GL_ZERO);
glColor(1.0f, 1.0f, 1.0f, 1.0f-.5f);
//draw 3 rects and 4 circles
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
//draw the label as a normal rect (the rounded parts will be trimmed because of alpha channel)

并且你可以重复在for循环对所有的标签。

我知道事情变得有点复杂,但你正在尝试做的是不那么容易,因为它似乎。 我提出这个解决方案给你,因为这样你有最少的代码改变,一般我会建议使用模板缓存(已经提到)或FBO(帧缓冲区对象)。 的FBO系统将创建另一个帧缓冲器并附加纹理给它,绘制了整个标签对象,然后使用结合的纹理它绘制到主屏幕。



文章来源: How to set blend function on opengl for two overlapping objects