2012-03-01 10 views
2

私は、VBOを使って数百万(最大10個)の三角形に基づいてモデルをレンダリングしています。ユーザーがクリックする可能性のある三角形を検出する必要があります。何百万ものプリミティブのマウスピッキング戦略はありますか?

"名前スタック"と "ユニークカラー"の仕組みを読んで理解しようとします。 名前スタックに最大128個の名前を入れることができますが、ユニークカラーは2 ^(8 + 8 + 8)= 16777216個の可能な異なる色を持つことができますが、いくつかの近似があることもあります。

私の場合にはどの戦略が最適ですか?

+1

おそらく適切な境界線ボリューム階層を使用したレイピッキング? – Bart

+0

名前/色は本当に遅いです...私はどんな目的でもお勧めしません。バートが言ったことをしてください。 – Rookie

答えて

8

基本的には、オプションの2つのクラスがあります:あなたはすべての三角形にIDを添付して、別々のレンダーターゲットにidを行うレンダリングを意味し、

1)「三角形ごとに固有の色の道を」。それは32ビット(rgbの場合は8、aの場合は8)でもかまいませんが、さらに多くのアイデアのために2番目のビットを追加することができます。三角形ごとにIDを取得するのは面倒ですが、実装するのは比較的簡単です。パフォーマンスにはかなり悪影響を及ぼすことがあります(フィルレート)。

2)適切な光線追跡。あなたはほぼ確実に加速構造(オクトリー、kd、...)を持ちたいと思っていますが、すでに錐台のカリングのためのものがあります。 1本の線は本当にたくさんありませんが、この方法は非常に速くなければなりません。

3)ハイブリッド。おそらく実装するのが最も簡単です。頂点バッファID(バッファあたりの固有の色:)をレンダリングし、どの頂点バッファが選択されたかを知ると、すべての三角形に対して線をトレースするだけです。

通常の場合、私は2)が最良の選択肢だと言います。すぐに何かをしたい場合は、3)に進みます。 1)おそらくかなり役に立たないでしょう。

+0

合意。空間的な加速構造を持つレイトレーシングが最良の方法です。 – kevintodisco

+0

私はOpenGLには比較的新しいと思うので、簡単に(大体は^^)実装してみたいと思いますので、1または3です。実際には、主に1つのVBOだけが含まれています。 10億の三角形と私は、あなたが「すべての三角形に対して線」と言えば、それはこのような大きな三角形で実現可能ではないかもしれないと怖がっていると思います。別のもの、いくつかの良いチュートリアルへのリンクがありますかレイトレーシングのために? 1ピクセルで深度を読み取ってgluUnProjectに渡すと、x座標とy座標も取得できますか? – elect

+0

@elect、名前/色を使用しないでください。gluUnProject()を使用してそこから任意の半径の三角形を取得し、各三角形の交差点をテストします。しかし、私はあなたに警告します:あなたはモデルに対する距離/角度に応じて正しいx/y位置を得られないかもしれません。とにかく、この方法にはオクトリーが必要な場合があります。 – Rookie

5

GPUカードにOpenGL 4.2が搭載されている場合は、GLSLでimageStore()という関数を使用して、画像内の三角形IDをマークすることができます。私の場合は、画面上の定義済みのウィンドウの背後にあるすべての三角形を検出する必要があります。ピッキング(ウィンドウ上でレンダリングされた三角形を選択)は同様に機能します。選択は私のためにリアルタイムで実行されます。

イメージ(またはテクスチャ)の最大サイズは、8192x8192 = 64M以上である必要があります.64Mまでのプリミティブ(最大で2枚、3枚のイメージを使用する場合)を使用できます。スクリーンの後ろ

保存するすべてのtrianges Idは、このフラグメントシェーダで行うことができます。

uniform uimage2D id_image; 

void main() 
{ 
    color_f = vec4(0) 
    ivec2 p; 
    p.x = gl_PrimitiveID % 2048; 
    p.y = gl_PrimitiveID/2048; 
    imageStore(id_image, p, uvec4(255)); 
} 

Idは画面に描画すべてtrianges保存するには:その後、わずかに異なるフラグメントを使用して、まず、我々は深度バッファを事前に計算しますシェーダ:

uniform uimage2D id_image; 

**layout(early_fragment_tests) in;** //the shader does not run for fragment > depth 

void main() 
{ 
    color_f = vec4(0) 
    ivec2 p; 
    p.x = gl_PrimitiveID % 2048; 
    p.y = gl_PrimitiveID/2048; 
    imageStore(id_image, p, uvec4(255)); 
} 
+0

今、私はOpenGL 2に取り組んでいますが、近い将来に変更される可能性があります。あなたの興味深い投稿の+1 – elect

関連する問題