Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在opengl上为两个重叠对象设置混合函数_C++_Opengl Es_Alphablending_Opengl Es 1.1 - Fatal编程技术网

C++ 如何在opengl上为两个重叠对象设置混合函数

C++ 如何在opengl上为两个重叠对象设置混合函数,c++,opengl-es,alphablending,opengl-es-1.1,C++,Opengl Es,Alphablending,Opengl Es 1.1,嗨,我需要画一个圆角矩形。 我按照上图的步骤进行操作。我首先画了绿色的长方形。然后我画了两个黑色的长方形,然后在边上画了圆圈,使角变圆。现在我做了这件事后得到的是下图 可以看出,角圆与矩形重叠部分的透明度较低。但当不与矩形重叠时,透明度更高。矩形的alpha设置为0.5f。圆也有0.5fα。这就是为什么重叠部分为白色,非重叠部分为透明。我希望重叠部分具有与矩形相同的透明度,这样就看不到重叠的圆形部分。我的混合函数是glBlendFunc(GL_SRC_ALPHA,GL_ONE_减去_SRC_

嗨,我需要画一个圆角矩形。

我按照上图的步骤进行操作。我首先画了绿色的长方形。然后我画了两个黑色的长方形,然后在边上画了圆圈,使角变圆。现在我做了这件事后得到的是下图

可以看出,角圆与矩形重叠部分的透明度较低。但当不与矩形重叠时,透明度更高。矩形的alpha设置为0.5f。圆也有0.5fα。这就是为什么重叠部分为白色,非重叠部分为透明。我希望重叠部分具有与矩形相同的透明度,这样就看不到重叠的圆形部分。我的混合函数是
glBlendFunc(GL_SRC_ALPHA,GL_ONE_减去_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
};
drawCircle函数为圆生成点并绘制它。该函数的绘图部分是

glVertexPointer(2, GL_FLOAT, 0, vertices);
 glColorPointer(4, GL_UNSIGNED_BYTE, 0, color);
 glDrawArrays(GL_TRIANGLE_FAN, 0, triangleAmount+2);
有人能帮我解决这个问题吗?谢谢

编辑:这是使用这两个混合函数后的效果。

我知道你要做什么,看到你的结果,你可能只需要在绘制遮罩(3个矩形和4个圆)时禁用混合,然后使用
glBlendFunc(GL_DST_ALPHA,GL_ZERO)
。不过,只有在场景中没有绘制任何内容时,此操作才会起作用

为了解释你在那里做了什么,你正在用.5 alpha绘制一个白色并将其混合。 在开始时考虑像素颜色“目的地”是(0,0,0,0),传入的“源”总是在你的情况下(1,1,1,5)。假设源颜色为“S”,目标颜色为“D”,而组件为(r、g、b、a),因此源alpha为“S.a”,您在混合函数中编写的是:

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)
导致阿尔法差异。因此,我希望您能够理解混合函数中的两个参数的含义:第一个参数告诉您使用什么因子来乘以源(传入)颜色,第二个参数告诉您如何乘以目标颜色。最后,它们被汇总在一起

因此,对于您的情况,您希望在绘制这些基本体的任何地方强制alpha通道为某个值。要实现这一点,您需要
S*1.0+D*.0
,其参数为
glBlendFunc(GL\u ONE,GL\u ZERO)
,尽管这与禁用混合相同。只有编写此原语才能生成一个透明度为
.5
的白色(灰色)圆形矩形,而其余的都是完全透明的。现在,在此之后,您需要设置混合函数,以将输入颜色与目标alpha相乘
glBlendFunc(GL_DST_alpha,GL_ZERO)

编辑:

到现在为止,我还没有完全理解你想要实现什么。正如我上面提到的,如果您已经绘制了一些场景,这将不起作用

要用一些复杂对象覆盖现有场景(在本例中,对象在某些部分上重叠),使用模具缓冲区将是最安全的。创建它很像深度缓冲器,但是你可以把它看作另一个颜色通道,很容易画出来,然后再使用它,所以你可能需要在某个时间点看它。 在您的情况下,可以安全地说这是您的主缓冲区,用于显示。在这种情况下,您可以使用alpha通道:

要仅绘制到alpha通道,必须设置
glColorMask(GL\u FALSE,GL\u FALSE,GL\u FALSE,GL\u TRUE)
,完成后,将所有参数设置为TRUE

  • 要清除alpha通道,您必须绘制一个带有所需alpha颜色的全屏矩形(我建议您使用
    (1,1,1,1)
    ),并仅绘制到alpha通道
  • 要绘制遮罩(3个矩形和4个圆),请使用
    glBlendFunc(GL_ONE,GL_ZERO)
    和颜色
    (1,1,1-desiredAlpha)
  • 要绘制圆形标签,请使用
    glBlendFunc(GL_ONE_减去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系统将创建另一个帧缓冲区并向其附加纹理,将整个标签对象绘制到该缓冲区,然后使用绑定的纹理将其绘制到主屏幕。

    您好,谢谢您的解释。很好:)但我对最后一段有点困惑。我理解为什么我需要做
    glBlendFunc(GL\u ONE,GL\u ZERO)
    。我知道我需要在绘制矩形之后和绘制圆之前编写
    glBlendFunc(GL\u ONE,GL\u ZERO)
    。因此,矩形通常以0.5 alpha绘制,但绘制圆时,矩形的alpha不会产生任何影响。还有为什么我需要做
    glBlendFunc(GL_DST_ALPHA,GL_ZERO)
    ?我应该把它放在哪里?谢谢。但是我想我遗漏了一些东西,因为这样做之后,圆圈就没有透明度了。但矩形是透明的。我把
    glBlendFunc(GL\u ONE,GL\u ZERO)
    放在我画矩形之后和画圆之前。在画完之后,我又把这个
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_减去SRC_ALPHA)
    。谢谢。不用了,你可以用(GL_ONE,GL_ZERO)来画矩形和圆形,然后用(GL_DST_ALPHA,GL_ZERO)来画图像。第一个混合模式不会对重叠产生影响,因为目标值不存在