OpenGL頂点属性-正規化


8

悲しいかな、私は検索しましたが、決定的な答えは見つかりませんでした。

次のコマンドを使用して、OpenGLの頂点データをいつ正規化しますか。

glVertexAttribPointer(index, size, type, normalize, stride, pointer);

つまり、いつですかnormalize == GL_TRUE。どのような状況で、なぜGPUに前処理の代わりに計算をさせることにしたのですか?私が今まで見たすべての例では、これをGL_FALSEに設定しています。個人的にはその使用法を見ることができません。しかし、クロノスは愚かではないので、何か有用な(そしておそらく一般的な)もののために存在しているはずです。

回答:


9

「正規化」パラメーターは、固定小数点値の使用に影響します。

このドキュメントには、「固定小数点データ値を正規化するか(GL_TRUE)、または固定小数点値に直接変換するか(GL_FALSE)を指定する」というパラメーターが記載されています。

さらに、これは「glVertexAttribPointerの場合、正規化がGL_TRUEに設定されている場合、整数形式で格納された値が範囲[-1,1](符号付き値)または[0,1](符号なしの値の場合)アクセスされて浮動小数点に変換された場合。それ以外の場合、値は正規化されずに直接浮動小数点に変換されます。

要約すると、固定小数点値を使用しない場合は、気にする必要はありません。その場合、このフラグは(たとえば)バイト値128を0.5または128.0にするかどうかを制御します。


3
これは実際には質問の答えにはなりません。私はすでにそれが何をするのかを理解しましたが、実際に「一般的な」実装にいつ適用できるか知りたいと思っていました。
減速

2
多くのモバイルアプリケーションが主に固定小数点演算を使用していて、浮動小数点演算に触れたくなかったとき、それは関連性があったと確信しています。別の可能性として、精度が十分であれば、データをよりコンパクトな方法、たとえばバイト単位で格納し、OpenGLにバイトを0..1の範囲に変換させたい場合があります。
Jari Komppa、2011年

それはまだ関連しています。たとえば、UVコードについて考えてみます。スペースを無駄にしてfloat2として保存したくない場合があるので、最適化として2 uint8として保存し、正規化フラグを設定して、[0、256]ではなく[0、1]の範囲を取得します。プログラム。
void

128は0.5または128/255になりますか?
riv 2015

11

これは古い質問ですが、現在の回答では、それらを何に使用するのかを実際に説明していません。

スペースを節約することがすべてです。また、頂点属性を使用すると、スペースが少ないほどパフォーマンスが向上します(頂点転送に制限がある場合)。

色は通常、コンポーネントあたり8ビットをはるかに超えるものを必要としません。HDRライト値などの場合、16ビットが必要になることがあります。しかし、表面の特性(ほとんどの頂点属性はこの属性です)では、8ビットで十分です。したがって、符号なし正規化バイトは、優れた頂点フォーマットです。

テクスチャ座標は、32ビットの浮動小数点精度を必要としません。[0、1]からの16ビット値で十分です。したがって、正規化された符号なしshortは、妥当な頂点フォーマットです。

法線 32ビットの精度を必要としません。彼らは方向です。8ビットの符号化された正規化バイトは少し小さい傾向がありますが、ほとんどの場合、10ビットの正規化された値で十分です。OpenGL(3.3以降)では、10/10/10/2ビットのパック形式を介して、単一の32ビット符号なし整数に格納された10ビット法線を使用することもできます。

さらに多くのメモリが必要な場合は、頂点の位置でゲームをプレイすることもできます。

正規化を行わないと、シェーダーの貴重なサイクルを無駄にしてバイト属性を255.0で割る必要があります。ハードウェアが無料で実行できるのに、なぜこれを行うのですか?


いい答えです。しかし、除算浮動小数点演算のオーバーヘッドは、通常のサイズの50%の減少に匹敵しますか?(つまり16ビットと言うには32ビット); MODERNハードウェア。特に、(少なくとも私の場合は)メモリが多すぎることを心配する必要はありません。
減速

1
@ダニエル:まあ、それについて考えましょう。「最新のハードウェア」では、正規化された値を渡すオーバーヘッドは...ゼロです。シェーダーで除算を行うオーバーヘッドは...ゼロ以外です。それがどれほど小さくても、それはまだゼロよりも大きいです。64バイト以上のブロックではなく、32バイトの頂点データブロックを送信することによる帯域幅の節約は言うまでもありません。ああ、シェーダーは特別にプログラムする必要はありません。同じシェーダーを使用して、正規化された値または浮動小数点値を取得できます。シェーダーに分割を配置する場合、頂点データのさまざまなサイズの新しいシェーダーが必要になります。
Nicol Bolas、2011

いい答えをありがとう。私は明確にそれを心に留めておきますが、整列された頂点データを送信しているので現時点では必要ありませんが、情報を追加するにつれて、同じではない可能性があり、これは両方のキャッシュにおいて大きな利点になるかもしれませんとスループット。
減速

通常(現在(3x)32ビットfloatのシーケンスに格納されています)を32ビットint(10/10/10/2)に変換する方法に関する戦略はありますか?
deceleratedcaviar

@Daniel:ARB_vertex_type_2_10_10_10_rev拡張機能の使用方法について質問がある場合は、先ほどリンクした拡張仕様を読むことをお勧めします。個人的にビット操作を行う方法を尋ねている場合は、ビットフィールドを含むCスタイルの構造体をお勧めします
Nicol Bolas

0

高精度の法線を持つメッシュと低い法線を持つメッシュがあるとします。属性の正規化では、同じシェーダーを使用できますが、2番目のメッシュの法線をバイト単位でパックします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.