2

OpenGL ES 2.0(Android上)を使用して、画像が少ない単純な2Dシーンを描画しています。背景画像とアルファチャネルを持つ他の画像があります。

シェーダープログラムのみを使用して、テクスチャの不透明なピクセルの周りに輪郭を描きたいと思います。やや広範囲にわたる検索の後、サンプルコードを見つけることができませんでした。GLES2.0はまだそれほど人気が​​ないようです。

サンプルコードを提供するか、これを行う方法の詳細を見つけることができる正しい方向に私を向けてください。

4

3 に答える 3

3

これを行うには、a)品質、およびb)必要な速度に応じていくつかの方法があります。一般的な検索用語は次のとおりです。

  • 「グローアウトライン」
  • "咲く"
  • 「トゥーンシェーダー」または「トゥーンシェーディング」
  • "エッジ検出"
  • 「シルエット抽出」
  • "マスク"

1)従来のアプローチは、ステンシルバッファを使用し、テクスチャにレンダリングすることです。

  • ステンシルバッファをクリアします(通常はフレームごとに1回実行されます)

    glClear( GL_COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT )
    
  • テクスチャにレンダリング

  • 深度書き込みを無効にする

    glDepthMask( 1 );
    
  • カラーバッファ書き込みを無効にする

    glColorMask( 0, 0, 0, 0 );
    
  • ステンシルバッファを有効にするステンシルを常に通過させて置き換えるように設定します

    glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
    glStencilFunc( GL_ALWAYS, 1, 1 );
    
  • オブジェクトをテクスチャに描画します

  • ステンシルを無効にする
  • カラーバッファ書き込みを有効にする
  • 深度書き込みを有効にする
  • 垂直方向と水平方向の両方でそれ自体にレンダリングすることでテクスチャをぼかす5または7パスタップなどのNパス「タップ」を実行します(別のオプションは、テクスチャ画像を拡大して描画することです)
  • 正投影に切り替えます
  • テクスチャ画像を描画してフレームバッファにブレンドします
  • 透視投影を復元

2)追加の頂点、つまり適切な巻き順序で隣接する頂点を通過させ、追加の輪郭三角形を動的に生成します。

参照:http ://www.gamasutra.com/view/feature/1644/sponsored_feature_inking_the_.php?print = 1

3)安価なエッジ検出を使用します。頂点シェーダーで、ビューで法線の内積を確認します。間にある場合:

-epsilon < 0 < epsilon

次に、あなたはエッジを持っています。

4)cheap-o-ramaオブジェクトスケーリングを使用します。もちろん凹面のオブジェクトには機能しませんが、品質のニーズによっては「十分に良い」場合があります

  • 「フラット」シェーダーに切り替えます
  • アルファテストを有効にする
  • 少し拡大したモデルを描画します
  • アルファテストを無効にする
  • モデルを描画しますが、通常のサイズで描画します

参照:

関連するSOの質問:

于 2013-10-29T15:10:48.547 に答える
2

ピクセルシェーダーに何かを描画させるには、ジオメトリが必要です。私が理解している限り、これらの画像の周囲に境界線を描画したいのですが、生成される最も外側のフラグメントは基本的な実装では画像ピクセルになるため、任意の境界線でそれらを上書きします。

「線の境界線」が必要な場合は、画像の三角形/四角形(GL_TRIANGLES、GL_QUADS)を描画する以外に何もできません。さらに、単一の四角形の頂点を共有できるアウトラインを(GL_LINESを使用して)呼び出します。多くのGPUでは線を効率的に描画できないことを考慮してください)

それ以外の場合は、以下の解決策を参照してください。

解決策1:

  • 画像+境界線と同じ大きさの長方形を描画し、画像のテクスチャ座標を調整して、長方形内に適切に配置されるようにします。このように、追加のジオメトリや描画呼び出しは必要ありません。
  • テクスチャボーダープロパティ(単一の4コンポーネントカラー)を設定します。余分なフラグメントシェーダーの計算を行う必要はなく、テクスチャユニット/サンプラーがすべての作業を行います。

テクスチャプロパティ:

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER)
glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_BORDER_COLOR,borderColor4f)

単一チャネルテクスチャにカラーボーダーを使用したことがないため、このアプローチを検証する必要があります。

解決策2:解決策2:

1と似ていますが、フラグメントシェーダーで計算を行い、テクスチャの座標がテクスチャの境界ではなく境界領域内にあるかどうかを確認します。変更を加えない場合、テクスチャ座標のスカラーの範囲は0.0〜1.0です。

テクスチャのプロパティは次のとおりです。

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP)

フラグメントの色は、次のいずれかの方法で決定できます。

  • 長方形の追加の境界線の色属性。ここで、テクセルまたはその境界線の色のいずれかが選択されます(頂点属性の場合もありますが、均一または一定である可能性が高くなります)。

  • アルファテクスチャと長方形全体の背景としての2番目のテクスチャ(額縁など)の組み合わせ。ここでも、どちらかのテクセルが選択されます。

  • 他の数学関数

もちろん、画像/境界線のグラデーションの色の値を混在させることもできます。

編集:

このようなアウトラインセグメントの数、長さ、および位置はさまざまであり、凹型の形状を形成することもあるため、ES2.0コアでは使用できないジオメトリシェーダーを使用してこれを行う必要があります。あなたができる最善のことは、CPU上の各画像のラインループを事前に計算することです。シェーダーでこのようなテストを行うことは、画像サイズ、実際に実行するハードウェアなどによっては、かなり非効率的であり、やり過ぎです。一定量の線分を描画し、頂点シェーダーを使用してそれらを変換する場合、適切に行うことはできません。少なくとも多大な労力とGPUワークロードなしではなく、すべてのケースをカバーします。

対応するテクセルのカラー値を変更する場合は、他のすべての実装と同様に、フラグメントシェーダーは、隣接するピクセルごとにテクスチャエッジに向かって大量のさまざまな量のテクセルをフェッチする必要があります。このようなブルー​​トフォース手法は、通常、再帰的で反復的なアルゴの代わりになります。CPUの方が適しています。したがって、テクスチャを変更するか、フラグメントシェーダーで組み合わせるために、2番目のテクスチャを生成することによってそれを行うことをお勧めします。

基本的に、パスファインディングアルゴリズムを実装する必要があります。これは、不透明なピクセルを任意のエッジに向かって「回避」しようとします。

于 2012-12-04T11:39:10.930 に答える
0

アルファチャネルはグレースケール画像として表示されます。エッジ検出/描画アルゴリズムを探します。たとえば、Cannyエッジ検出器(http://en.wikipedia.org/wiki/Canny_edge_detector)。あるいは、画像が手続き型でない場合は、エッジを事前に計算することをお勧めします。

さまざまな画像をブレンドし、そのブレンドの結果から輪郭を適用することが目標である場合は、テクスチャにレンダリングしてから、そのテクスチャを画面上に再度レンダリングして、エッジ検出アルゴリズムを実行します。

于 2012-12-04T20:05:30.820 に答える