1

私の理解では、OpenGL のインデックス作成またはIBOs は主に、特定のジオメトリの描画に必要な頂点の数を減らすために使用されます。インデックス バッファを使用すると、OpenGL は指定されたインデックスを持つ頂点のみを描画し、他の頂点をスキップすることを理解しています。しかし、それはテクスチャリングを使用する可能性を排除しませんか? 私の知る限り、インデックス バッファで頂点をスキップすると、頂点属性もスキップされますか? 頂点属性が次のように設定されている場合:

attribute vec4 v_Position;
attribute vec2 v_TexCoord;

次に、インデックスバッファをglDrawElements(...)使用して、テクスチャリングの使用を排除しませv_Positionんか、それとも「再利用」されますか? そうでない場合、インデックス バッファを使用するときにテクスチャを作成するにはどうすればよいですか?

4

2 に答える 2

4

あなたはいくつかの重要な用語を誤解していると思います。

「頂点属性」は、個々の頂点を定義するデータです。これらにはテクスチャ座標が含まれますが、位置も含まれます。実際、少なくとも固定関数を使用していない場合、頂点属性の意味は完全に任意です。それらの意味は、頂点シェーダーがそれらをどのように使用したり、次のシェーダー ステージに転送したりするかによって定義されます。

そのため、位置、テクスチャ座標、およびその他の頂点属性が頂点シェーダーに転送される方法に違いはありません。インデックスがどのように使用されているか (または使用されていないか) に関係なく、それらはすべてまったく同じように解析されます。

頂点シェーダーの例:

layout(location = 0) in vec4 position;
layout(location = 1) in vec2 uvAttr;

out vec2 uv;

void main( )
{
    uv = uvAttr;
    gl_Position = position;
}

そして、上記がペアになっているフラグメント シェーダーの先頭:

in vec2 uv;

頂点シェーダーの出力は、ご覧のとおり、頂点属性に基づいています。その出力は、フラグメント シェーダーに送信される前に、プリミティブ アセンブリによって生成された面全体に補間されます。プリミティブ アセンブリは、インデックスが作用する主な場所です。インデックスは、頂点シェーダー出力を使用して実際のジオメトリを作成する方法を決定します。そのジオメトリはフラグメントに分割され、レンダリング出力に実際に影響します。頂点シェーダーからの出力は、フラグメント シェーダーへの入力になります。

頂点シェーダーの後、頂点属性は定義されなくなります。上記のように転送した場合にのみ、テクスチャリングなどで使用するためにアクセスできます。したがって、そもそも頂点属性自体をテクスチャ座標として使用していません。頂点シェーダーによって出力され、プリミティブ アセンブリ/ラスタライズで補間された変数を使用しています。

「インデックス バッファで頂点をスキップすると、頂点属性もスキップされます」

はい - 頂点を完全に無視します: テクスチャ座標、位置、およびその頂点に対して定義したその他のもの。ただし、スキップされた頂点のみ。残りは、スキップされた頂点が存在しなかったかのように、通常どおり処理され続けます。

例えば。議論のために、5 つの頂点があるとしましょう。以下に示すように、これらを蝶ネクタイの形に注文しました。各頂点には、位置 (x と y だけの 2 成分ベクトル) と、色として使用される 1 つの成分「明るさ」があります。蝶ネクタイの中心頂点は 1 回だけ定義されますが、インデックスを介して 2 回参照されます。

例 1

頂点属性は次のとおりです。

  1. [(1, 1), 0.5]、別名 [(x, y), 明るさ]
  2. [(1, 5), 0.5]
  3. [(3, 3), 0.0]
  4. [(5, 5), 0.5]
  5. [(5, 1), 0.5]

インデックスは、1、2、3、4、5、3 です。

この例では、「明るさ」が UV(W) 座標の代わりになることに注意してください。ベクトルとして、同様に補間されます。前に言ったように、頂点属性の意味は恣意的です。

ここで、頂点のスキップについて尋ねているので、インデックスを 1、2、4 に変更した場合の出力は次のようになります。

例 2

これは 1、2、3 になります。

例 3

ここにパターンがありますか?OpenGL は、それが生成する面を構成する頂点だけに関心があります。インデックスは、これらの面がどのように組み立てられるかを変更するだけです (また、計算される不要な頂点を完全にスキップできるようにすることもできます)。これらは、使用される頂点の意味に影響を与えず、面に入ります。黒の頂点 #3 がスキップされた場合、それはどの面の一部でもないため、どの面にも寄与しません。

余談ですが、標準では、実装が単一の描画呼び出し内で頂点シェーダー出力を再利用することを許可しています。そのため、同じインデックスを繰り返し使用しても、追加の頂点シェーダー呼び出しが発生することはおそらくないはずです。ドライバーが実際に行うことは常にブードゥーになるため、「おそらくそうではない」と言います。

ここでは、テッセレーション シェーダーとジオメトリ シェーダーを意図的に無視していることに注意してください。これらはこの質問の範囲外のトピックですが、頂点属性の処理方法に興味深い影響を与える可能性があります。また、頂点の順序付けはシェーダーである程度アクセスできるため、出力に影響を与える可能性があるという事実も無視しました。

于 2016-03-15T07:14:35.120 に答える
2

高速化のためにインデックス バッファが使用されます。

インデックス バッファでは、最近変換された頂点を格納するために頂点キャッシュが使用されます。変換中に、インデックスが指す頂点が既に変換されており、頂点キャッシュで使用できる場合は、再利用されます。それ以外の場合は、頂点が変換されます。インデックス バッファがないと、頂点キャッシュを利用できないため、頂点は常に変換されます。そのため、頂点キャッシュ ヒットを最大化するようにインデックスを並べ替えることが重要です。

インデックス バッファは、メモリ フットプリントを削減するためにも使用されます。

通常、単一の頂点データは非常に大きくなります。たとえば、位置データ (x、y、z) の単精度浮動小数点を格納するには、12 バイトが必要です (各浮動小数点数に 4 バイトが必要であると仮定)。頂点カラー、テクスチャ座標、または頂点法線を含めると、このメモリ要件は大きくなります。

各頂点が位置データのみ (x、y、z) で構成される 2 つの三角形で構成されるクワッドがある場合。インデックス バッファがない場合、クワッドを格納するには 6 つの頂点 (72 バイト) が必要です。16 ビットのインデックス バッファでは、4 つの頂点 (48 バイト) + 6 つのインデックス (6*2 バイト = 12 バイト) = 60 バイトだけでクワッドを格納できます。インデックス バッファを使用すると、多くの共有頂点がある場合、このメモリ要件は小さくなります。

于 2016-03-15T06:49:55.380 に答える