2017-12-03 8 views
2

私は私を混乱させる何かに遭遇しました。私はそれに対する答えを見つけることができません。私はこのようなシェーダ書く時:ユニフォームと変化のためのOpenGLとGLSLのメモリアライメント

layout (location = 0) in vec3 inPosition; 
layout (location = 1) in vec3 inNormal; 
layout (location = 2) in vec2 inTexCoords; 

を私はvec3年代は、多くのであるvec4、またはSIMD互換性のあるデータ型として整列16バイトではないことを知っています。

struct Vertex 
{ 
    vec3 position; 
    vec3 normal; 
    vec2 texCoords; 
}; 

各ベクトルは、サイズが8 *のはsizeof(フロート)、32バイトであること、無パディングで、お互いにぴったりと座っている:私のC++コードでの私のデータがあるので、私は、(私が思う)これを知っています。私はそれを制服に渡し、シェーダはそれをうまく読みます。したがって、両方が整列していることがわかります。

しかし、とき、それは例えばstd140規格にvec3は別のvec3またはvec4を追加する前に、余分な4つのバイトでパディングされなければならない、GLSLで均一なブロックに来る:メンバーである場合

  1. N基本的なマシン単位消費コンポーネントと三成分ベクトル、ベースアライメント4N

あるあなたもコンパクトにvec3と次vec3間に4バイトの整数または4バイトブール値を記憶することができるがサイズ。これは、頂点レイアウトのattribポインタ値がstd140レイアウトに従わないことを意味しますか?また、たとえば私のC++コードでSIMDの16バイト整列ベクタを使用している場合、私はもはやattribポインタの値をvec3、vec3、vec2として設定することはできませんが、むしろすべてのvec4を持っていますか?

警告:実装は時々 vec3コンポーネントのstd140レイアウト誤解し

はまた、私はマニュアルの次の警告を見ました。 構造体/配列を手動で埋めて、vec3をまったく使用しないようにすることをお勧めします。

ここではvec3の使用を避けると言っていますが、vec3の後に4バイトのintまたはboolをパックするスマートな省スペース技術だと思いました。

答えて

4

std140レイアウトは、interface blocksにのみ適用され、バッファの内容やインターフェイスブロック外の属性には適用されません。インターフェイスブロックは頂点シェーダへの入力またはフラグメントシェーダからの出力として使用できないため、std140はどのように設定されているか、または頂点データの格納方法には影響しません。

警告:はい、格納するためにvec3の後にスペースを使用し、int/float/boolを使用するのはスマートなテクニックです。しかし、警告が述べるように、ドライバの実装は時々それを間違ってしまいます。だから、コードが確実にどこでも確実に実行されるようにしたいのであれば、たくさんテストするか、vec3を使わないでください。繰り返しになりますが、これはインターフェイスブロックの場合にのみ関連することに注意してください。普通のvec3制服はこれで触れられません。

あなたができることは、3つのフロートとintをC++側に格納するようにパックすることですが、インターフェイスブロックのvec4を使ってアクセスします。 floatBitsToInt(myBlock.myVec4.w)を使用して整数を取得することはできません。

+0

これは参考になりました。 floatBitsToIntは私の心を吹き飛ばしました。最初は0〜255のRGBAを格納するu8vec4を見つけようとしていましたが、glslはシングルバイトデータ型を扱っていないことが分かったので、次のアイデアはintを送り、適切なカラーチャネルを確保するためにビット演算子を使用します。 – Zebrafish

+0

ちょっと待ってちょっと浮かれば私はまだ気づいたfloatBitsToIntでもやらなければならない。私の0 - 255の色が私のvec4.wなら、私はまだシフトし、正しいバイトを抽出する必要があります。 – Zebrafish

関連する問題