OpenGL:“消しゴム”の実装方法ツール?
-
08-07-2019 - |
質問
描画/ペイントの仕組みが関係するiPhone向けのゲームに取り組んでいますが、すでにペイントされたものを消去するツールを作成しようとして問題があります。
主な問題は、ペイントされる背景が無地ではなく、静止画像またはアニメーションであることです。描画でさまざまなブレンドオプションと論理演算を使用してみましたが、何も機能していないようです。私はOpenGLが初めてなので、何かが足りないはずです。
ヒントはありますか
編集:もう少し情報を与えるために、ブラシにテクスチャを使用し、glVertexPointer()およびglDrawArrays()を使用してそれらをレンダリングしています。例:
glBindTexture(GL_TEXTURE_2D, circleBrush);
glVertexPointer(3, GL_FLOAT, 0, verts);
glTexCoordPointer(2, GL_FLOAT, 0, coords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
編集2:残念ながら、ステンシルバッファはiPhoneでは使用できません。 :(
編集3:フレームバッファオブジェクトはiPhoneで利用でき、それが私がした道です。まだ完全には実装していませんが、今のところ、私が望んでいた方法で機能しているようです。みんなありがとう!
解決
シーン全体にテクスチャ付きのフルスクリーンクワッドを描画します。ユーザーがブラシストロークを描いたら、 glTexSubImage2D
を使用してテクスチャを更新します。
glReadPixels / glDrawPixelsは遅いです。
FrameBufferObjectsを使用することはさらに優れていますが、この拡張機能がiPhoneで利用できるとは思えません(繰り返しますが、確かではありませんので、試してみてください)。 FBOを使用すると、別のレンダリングコンテキストであるかのようにテクスチャに直接描画できます。
他のヒント
ステンシルバッファーは、これに確実にアプローチするための最良の方法です...時間、CPU、および潜在的な問題を節約できます..、これらはIphoneで利用できます。OpenGlES2.0サーフェス(gles 1.0ではなく)を作成するだけです。または1.1)。
//Turn off writing to the Color Buffer and Depth Buffer
//We want to draw to the Stencil Buffer only
glColorMask(false, false, false, false);
glDepthMask(false);
//Enable the Stencil Buffer
glEnable(GL_STENCIL_TEST);
//Set 1 into the stencil buffer
glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
//CALL YOUR DRAWING METHOD HERE
//Turn on Color Buffer and Depth Buffer
glColorMask(true, true, true, true);
glDepthMask(true);
//Only write to the Stencil Buffer where 1 is set
glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
//Keep the content of the Stencil Buffer
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
//CALL OUR DRAWING METHOD AGAIN
この例を調べてください: http://www.opengl.org/resources/code/samples /glut_examples/examples/stenciltst.c
視覚的な結果は次のとおりです。 http://www.opengl.org/resources/code/samples /glut_examples/examples/stenciltst.jpg
AndroidとiPhoneの両方で、これを使用して同じ種類の消しゴムツールを実装しました。
がんばって!
乾杯!
多くの情報は提供しませんが、「ペイント」するものは何でも保存すると仮定します。バッファに入れて、次のように画面に描画します:
glWindowPos2i(X, Y);
glDrawPixels(drawing->Width, drawing->Height, drawing->Format,
GL_UNSIGNED_BYTE, drawing->ImageData);
drawing-> ImageDataがバッファの場合。できることは、別のバックグラウンドバッファを用意して、最初にそれを描画することです。次に、消去ツールは、描画バッファを単純に白抜きにします(アルファを含むすべての値を完全に上げます)。
このソリューションを機能させるには、ブレンドを有効にし、深度テストを無効にする必要があります。
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glWindowPos2i(X, Y);
//background never changes
glDrawPixels(background->Width, background->Height, background->Format,
GL_UNSIGNED_BYTE, background->ImageData);
glWindowPos2i(X, Y);
glDrawPixels(drawing->Width, drawing->Height, drawing->Format,
GL_UNSIGNED_BYTE, drawing->ImageData);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
それはあなたが探しているものですか?
この操作にはステンシルバッファを使用できます。ステンシルバッファーは、深度バッファーと同様に、すべてのピクセルの情報を保持する特別なバッファーです。デプスバッファーとは異なり、描画中にステンシルバッファーを変更する方法と、カラーバッファーに描画するかどうかの決定にどのように影響するかを決定します。そのためには、描画操作の前に特定の状態を設定できます。あなたがすることは次のとおりです。
-
ユーザーが消去した時点で、「消去済み」を描画します。への地域 ステンシルバッファ(StencilOpを使用、以下を参照)。任意のGL図面を使用できます そのための関数。
-
すべてのレンダリングパスで、最初の描画 背景(必要に応じて、 ここでネガティブステンシルテストを使用して 「消去済み」のみを描画します。の一部 背景-増加する可能性があります パフォーマンス)。
-
次に、すべてのステンシルテストを有効にします その他の描画操作。 OpenGL その後にのみ描画します 「消去なし」リージョン。
ステンシルバッファが描画に影響する(またはしない)方法を設定する関数: glStencilFunc()
ステンシルバッファ自体が描画によってどのように影響を受けるかを設定する関数: glStencilOp()
これらの引数も含む詳細な説明: http://www.opengl.org/resources/ code / samples / sig99 / advanced99 / notes / node117.html
glBlendFunc(GL_ONE、GL_ZERO)モードを使用すると、初期化できます。