0

こんにちは、角の丸い長方形を描く必要がありました。 角丸長方形の描画手順

上記の画像の手順に従いました。最初に緑色の長方形を描きました。次に、2 つの黒い長方形を描きました。次に、角を丸くするために、端に円を描きました。これを行った後に得られるのは、下の画像です。

ここに画像の説明を入力

コーナーサークルは、長方形と重なる部分の透明度が低くなっていることがわかります。ただし、長方形と重ならない場合は透明度が高くなります。長方形のアルファは 0.5f に設定されています。円にも 0.5f アルファがあります。そのため、重なっている部分は白く、重なっていない部分は透明になっています。重なった円の部分が見えないように、重なった部分を長方形と同じ透明度にしたいのですが、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
};

drawCircle 関数は、円の点を生成して描画します。その関数の描画部分は

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

誰でも問題を解決するのを手伝ってもらえますか? ありがとう。

編集: これは、これら 2 つのブレンド関数を使用した後の外観です。 ここに画像の説明を入力

4

1 に答える 1

1

私はあなたがこれでどこに向かっているのかを見て、マスク(3つの長方形と4つの円)を描画しているときにブレンドを無効にするだけでよい結果を見て、glBlendFunc(GL_DST_ALPHA, GL_ZERO). ただし、これはシーンにまだ何も描画されていない場合にのみ機能します。

あなたが何をしたかを説明するには、.5 アルファで白い色を描画し、それをブレンドしています。最初に、ピクセルの色の「宛先」が (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 つのパラメーターが何を意味するかを理解していただければ幸いです。1 つ目はソース (入力) カラーを乗算するために使用する係数を示し、2 つ目は宛先カラーを乗算する方法を示します。最後に、それらは一緒に合計されます。

したがって、あなたのケースでは、これらのプリミティブを描画するすべての場所で、アルファ チャネルを強制的に値に設定したいと考えています。これを実現するには、必要なS*1.0 + D*.0パラメーターとそのためのパラメーターがありますがglBlendFunc(GL_ONE, GL_ZERO)、これは単にブレンドを無効にすることと同じです。このプリミティブを記述するだけで、透明度が の白 (グレー) の丸みを帯びた四角形が生成され.5、残りはすべて完全に透明になります。この後、ブレンド関数を設定して、着信色を宛先アルファで乗算する必要がありますglBlendFunc(GL_DST_ALPHA, GL_ZERO)

編集:

あなたが何を達成したいのか、今まで完全には理解できませんでした。上で述べたように、すでにいくつかのシーンが描かれている場合、これは機能しません。

既存のシーンを複雑なオブジェクト (この場合、オブジェクトはいくつかの部分でオーバーラップしています) でオーバーレイするには、ステンシル バッファーを使用するのが最も確実です。作成は深度バッファによく似ていますが、別のカラー チャネルと考えることができます。簡単に描画して後で使用できるので、後で確認したくなるかもしれません。

あなたの場合、これはメイン バッファであり、表示用であると言っても過言ではありません。その場合、アルファ チャンネルを使用できます。

アルファチャンネルのみに描画するには、設定glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE)する必要があり、完了したら、すべてのパラメーターを true に設定します。

  1. アルファチャンネルをクリアするには、希望のアルファを持つ色でフルスクリーンの四角形を描画し(使用することをお勧めします(1,1,1,1))、アルファチャンネルのみに描画する必要があります
  2. そのマスク (3 つの四角形と 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 システムでは、別のフレーム バッファを作成してテクスチャをアタッチし、そこにラベル オブジェクト全体を描画してから、バインドされたテクスチャを使用してメイン画面に描画します。

于 2013-05-22T13:31:57.063 に答える