2017-02-17 19 views
0

私は以下に説明するプログラムを開発しています。 深度の異なる2つの三角形を描きます。 以下の例では、緑色の三角形を表示部分と非表示部分に分割したいと思います。次に、最後にブレンド機能を使用して、緑色の三角形の隠れた部分が透明に着色され、目に見える部分が元の色に着色されます。OpenGL - ES図面とブレンディング

example

は今、私は(JNI付き)のOpenGL-ESを使用してコードを記述します。 そして2つの質問があります。

まず

:このコードから

glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 

glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 
glUseProgram(gProgram); 
glGetUniformLocation(gProgram, "vColor"); 


const GLfloat gTriangleVertices1[] = 
{ 
    -0.5f, -0.5f, -0.5f, 
    0.0f, 0.5f, -0.5f, 
    0.5f, -0.5f, -0.5f, 
}; 
float color1[] = {1.0f, 0.0f, 0.0f}; 
const GLfloat gTriangleVertices2[] = 
{ 
    -0.7f, 0.0f, 0.3f, 
    0.5f, 0.3f, 0.3f, 
    0.5f, 0.0f, 0.3f, 
}; 
float color2[] = {0.0f, 1.0f, 0.0f}; 



int mColorHandle1; 
int mColorHandle2; 

glEnable(GL_BLEND); 
glEnable(GL_DEPTH_TEST); 
glClearDepthf(1.0f); 
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 
glUniform4f(mColorHandle1, color1[0], color1[1], color1[2], color1[3]); 
glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0, gTriangleVertices1); 
glEnableVertexAttribArray(gvPositionHandle); 
glDrawArrays(GL_TRIANGLES, 0, 3); 
glDepthFunc(GL_GREATER); 
//glDepthFunc(GL_LESS); 
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
glUniform4f(mColorHandle2, color2[0], color2[1], color2[2], color2[3]); 
glDrawArrays(GL_TRIANGLES, 3, 3); 
glDisableVertexAttribArray(gvPositionHandle); 

、IはglDepthFunc(GL_LESS)にglDepthFunc(GL_GREATER)を変更した場合、結果が正しく可視および隠れた部分を示しています。 しかし、私はそれが正解を示す理由を理解していません。 頂点gTriangleVertices1を追加しましたが、gTriangleVertices2は追加しません。 でも、私は三角形2の頂点を追加しません、それは私に正しい答えを与えます。どうして?

2番目の質問では、ブレンド機能を使用するのが正しいと思います(glut/freeglutで動作することを確認しました)。なぜgl-esで動かないのか?

///////////////////////// visible part ///////////////////////// 
glEnable(GL_BLEND); 
glEnable(GL_DEPTH_TEST); 
glClearDepthf(1.0f); 
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 
glUniform4f(mColorHandle1, color1[0], color1[1], color1[2], color1[3]); 
glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0, gTriangleVertices1); 
glEnableVertexAttribArray(gvPositionHandle); 
glDrawArrays(GL_TRIANGLES, 0, 3); 
glDepthFunc(GL_LESS); 
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
glUniform4f(mColorHandle2, color2[0], color2[1], color2[2], color2[3]); 
glDrawArrays(GL_TRIANGLES, 3, 3); 
glDisableVertexAttribArray(gvPositionHandle); 
glDisable(GL_DEPTH_TEST); 
glDepthFunc(GL_LESS); // same to initialize depth func 
///////////////////////// visible part ///////////////////////// 


///////////////////////// hidden part ///////////////////////// 
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
glEnable(GL_DEPTH_TEST); 
glClearDepthf(1.0f); 
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 
glUniform4f(mColorHandle1, color1[0], color1[1], color1[2], color1[3]); 
glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0, gTriangleVertices1); 
glEnableVertexAttribArray(gvPositionHandle); 
glDrawArrays(GL_TRIANGLES, 0, 3); 
glDepthFunc(GL_GREATER); 
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
glUniform4f(mColorHandle2, color2[0], color2[1], color2[2], 0.5f); 
glDrawArrays(GL_TRIANGLES, 3, 3); 
glDisableVertexAttribArray(gvPositionHandle); 
///////////////////////// hidden part ///////////////////////// 

ブレンド機能を追加しました。可視/隠し部分だけを使用すると、正しい結果が得られます。しかし、私がブレンド機能を使用すると、以下のように奇妙な結果が得られます。透明な非表示の緑色の三角形を与えます。 どうしたの?

enter image description here

答えて

0

最初の質問:

あなたは、これはあなたのバッファのオーバーフローを生成してglDrawArrays(GL_TRIANGLES, 3, 3);を言うことによって、主要なバグを作成しました。その結果は予想外であるが、あなたの場合には、あなたのコンパイラを使用すると、定義された2つの配列が密に充填されていることを決めたようだ:

const GLfloat gTriangleVertices1[] = 
{ 
    -0.5f, -0.5f, -0.5f, 
    0.0f, 0.5f, -0.5f, 
    0.5f, -0.5f, -0.5f, 
}; 
const GLfloat gTriangleVertices2[] = 
{ 
    -0.7f, 0.0f, 0.3f, 
    0.5f, 0.3f, 0.3f, 
    0.5f, 0.0f, 0.3f, 
}; 

そして

const GLfloat gTriangleVertices[] = 
{ 
    -0.5f, -0.5f, -0.5f, 
    0.0f, 0.5f, -0.5f, 
    0.5f, -0.5f, -0.5f, 
    -0.7f, 0.0f, 0.3f, 
    0.5f, 0.3f, 0.3f, 
    0.5f, 0.0f, 0.3f, 
}; 

だから、オーバーフローが実際にジャンプとして考えられています第2の頂点データがあるメモリの部分。あなたがしたことが間違って正しいと考えることを間違えないでください。それは正しくない、これは別のバージョンや他の理由、プラットフォーム、デバイスのために破ることができる...だからそれを修正します。

2番目の質問:

ブレンドし、デプスバッファが一緒に行っていません。この組み合わせを避ける必要があります。私はここでその理由を説明しません(それを少し探してください)が、結果は未定義であり、あなたはそれを使用しないかもしれません。どちらか一方を使用してください。

あなたがこれに取り組む方法をウェブで検索する場合、非常にユニークであるため、状況に応じて正しい答えを見つけることはできません。私があなたのケースの一般的な解決策として提案するのは、ステンシルバッファを追加することです。

また、最初の呼び出しはステンシルバッファに描画され、最後の呼び出しで描画される必要があります。したがって、最後の呼び出しでは、深さテストは無効にする必要がありますが、ステンシルを有効にする必要があります。しかし、そうすることで、単に深度を取り除き、ステンシルだけを使うべきです。

また、アルファチャンネルを使用することによって、この他にも解決策があると確信していますが、いずれの場合も、ブレンドと組み合わせた深度バッファは厳密に禁止されており、動作は未定義です。つまり、GPUによって異なることさえあります。

+0

ブレンドと深度テストを使用すると、異なるGPUで異なる結果が生じるのはなぜですか?半透明で透明なものを前面に描くと、それを背後に描くと問題はありませんが、深さのテストが始まります。 –

+0

@Bálint私もそう思っていましたが、深度バッファを破壊する。この質問の結果を確認してください:https://stackoverflow.com/questions/35893742/using-texture-image-with-alpha-makes-mesh-see-through/35912027#35912027 –