2

glVertexAttribPointer() の型パラメーターとして GL_INT_2_10_10_10_REV をどのように正確に使用するのか、誰か教えてもらえますか? この型を使用して色の値を渡そうとしています。また、このタイプの「REV」サフィックスの意味は何ですか? シェーダーで特別な処理が必要ですか?

私のコードは次のとおりです。

GLuint red=1023,green=1023,blue=1023,alpha=3;

GLuint val = 0;
val = val | (alpha << 30);
val = val | (blue << 20);
val = val | (green << 10);
val = val | (red << 0);

GLuint test_data[]={val,val,val,val};

loadshaders();

glBindAttribLocation(ps,0,"tk_position");

glBindAttribLocation(ps,1,"color");

LinkShader();

glUseProgram(ps);

glEnableVertexAttribArray (0);

glVertexAttribPointer(0, 4, GL_FLOAT, 0, 0, vertices);

glEnableVertexAttribArray (1);

glVertexAttribPointer(1,GL_BGRA,GL_UNSIGNED_INT_2_10_10_10_REV,GL_TRUE,0,test_data);

glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

シェーダーは次のとおりです。 頂点シェーダー -

#version 150

in vec4 tk_position;
in vec4 color;

out vec4 v_color;

void main()
{
    v_color = color;
    gl_Position = tk_position; 
}

フラグメントシェーダー -

#version 150

in vec4 v_color;
out vec4 fragColor;

void main()
{
    fragColor =  v_color;
}

プログラム オブジェクトも検証されます。そこに問題はありません。このコードは、AMD カードでは問題なく動作しますが、NVidia では失敗します。失敗すると、glDrawArrays() 呼び出しで NULL ポインター アクセスを取得します。

Access violation
    Exception Flag: 0x00000000
    Exception Addr: 0x055f32ce
4

2 に答える 2

16

色を渡す場合は、UNSIGNED_INT_2_10_10_10_REVが必要になる可能性が高くなります。だから私はそれがあなたが求めたものであると仮定します。

フィールド全体が 1 つの符号なし整数にパックされます。OpenGL は符号なし整数を正確に 32 ビットのサイズと定義しているため、GLuintOpenGL が提供する typedef を使用して取得する必要があります。

ただし、この形式はpackedであるため、配列を押し込むことはできません。これは一種の圧縮であるため、頂点属性データを小さくすることを真剣に考えている場合に一般的に使用されます。

まず、色に 10/10/10/2 を使用する唯一の理由は、元のソース カラーの色深度が通常のチャネルあたり 8 ビットの色などよりも高い場合です。結局、RGB コンポーネントはそれぞれ 10 ビットになります。元の色が 8 ビットしかない場合、実際には新しい情報は得られません。

では、浮動小数点精度の浮動小数点カラー値があるとします。各コンポーネントを [0, 1] の範囲に正規化する必要があります。次に、各値に 2 10 - 1 を掛けて、[0, 1023] の範囲に拡張します。次に、各コンポーネントを整数に変換します。

問題は、それを実際のフィールドに詰め込むことです。名前の「REV」は、コンポーネントの順序が優先されることを意味します。通常、OpenGL で のような形式が表示される場合GL_UNSIGNED_SHORT_5_6_5、これは各 unsigned short が 5 ビット、6 ビット、さらに 5 ビットのパターンに分割されていることを意味します。左端の 5 ビット フィールドは赤、6 ビット フィールドは緑、右端の 5 ビット フィールドは青です。

REV」はこれを逆にすることを意味します。したがって2_10_10_10_REV、最上位 2 ビットがalphaに移動することを意味します。次の 10 ビットは青になります。次にグリーン。次にレッド。

したがって、整数を [0, 1023] の範囲にまとめて、GLuint 値の適切な場所に押し込む必要があります。そして、配列内のそのようなすべてのコンポーネントに対してそれを行います。

GLuint val = 0;
val = val | (alpha << 30);
val = val | (blue << 20);
val = val | (green << 10);
val = val | (red << 0);

alphaこのコードは、ゼロ以外のビットが 2 つしかなくblue、 、green、およびredそれぞれにゼロ以外のビットが 10 個しかないことを前提としています。

于 2012-12-29T15:01:45.717 に答える
4

それでは、これをわかりやすい部分に分解してみましょう。

INT形式が整数として読み取られることを意味します。

2_10_10_10は、最初の int が 2 ビット、次の 3 が 10 ビットであることを意味します。これらの値を合計すると、4 バイト整数のビット数である 32 になることに注意してください。

REVコンポーネントの順序が逆であることを意味します。

IIRC この形式は、頂点データのサイズを縮小するために、頂点法線をパッキングするために最も一般的に使用されます。それ以外に使われているのを見たことがありません。

編集

また、どのビットがどの値を表しているかを正確に視覚化した表を含むこのクールなページも見つけました。サイトはほとんど日本語ですが、表は英語です。

編集2

上記のページへのリンクは無効になっています。値がどのように配置されているかを表にした別のページがあります。

于 2012-12-26T10:46:46.513 に答える