0

私が今持っているもの

#define QUAD_VERT_COUNT 4

#define QUAD_POS_COMP 3

typedef struct quad_pos
{
 GLfloat x, y, z;
}quad_pos;

#define SIZE_QUAD_POS = sizeof(quad_pos) * QUAD_VERT_COUNT

static QUAD_BUFFER = 0;

void init_quad_buffer()
{
 quad_pos* pos_data = malloc(SIZE_QUAD_POS);

 pos_data[0].x = -1.0f;
 pos_data[0].y = -1.0f;
 pos_data[0].z = 0.0f;

 pos_data[1].x = 1.0f;
 pos_data[1].y = -1.0f;
 pos_data[1].z = 0.0f;

 pos_data[2].x = -1.0f;
 pos_data[2].y = 1.0f;
 pos_data[2].z = 0.0f;

 pos_data[3].x = 1.0f;
 pos_data[3].y = 1.0f;
 pos_data[3].z = 0.0f;

 QUAD_BUFFER = create_buffer(GL_ARRAY_BUFFER, GL_STATIC_DRAW, pos_data, SIZE_QUAD_POS);
 free(pos_data);
}

void get_quad_buffer
{
  return QUAD_BUFFER;
}

そして作画(一部)

glBindBuffer(GL_ARRAY_BUFFER, get_quad_buffer());
glEnableVertexAttribArray(ss->attrib[0]);//attrib[o] is vertex pos
glVertexAttribPointer(ss->attrib[0], QUAD_POS_COMP, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, QUAD_VERT_COUNT);

マトリックスとシェーダーを使用してスケーリング、変換、回転を行うため、このバッファーはスプライトごとに変更されることはありません。

しかし、なぜ -1.0, 1.0 だけに GL_float を使用する必要があるのでしょうか? GL_Byte で十分です。

 typedef struct quad_pos
 {
 GLbyte x, y, z;
 }quad_pos;

void init_quad_buffer()
{
 quad_pos* pos_data = malloc(SIZE_QUAD_POS);

 pos_data[0].x = -1;
 pos_data[0].y = -1;
 pos_data[0].z = 0;
 ....
}

描画

  ...
  glVertexAttribPointer(ss->attrib[0], QUAD_POS_COMP, GL_BYTE, GL_FALSE, 0, 0);
  glDrawArrays(GL_TRIANGLE_STRIP, 0, QUAD_VERT_COUNT);

質問 1:正規化を GL_TRUE に設定する必要がありますか?
質問 2: GLclampf と GLfloat はどちらも 4 バイトの浮動小数点数ですが、色の値は 0.0 から 1.0 であるため、それらを GLbyte にも入れると (val/256、1.0 の場合は 255、0.5 の場合は 128、0 の場合は 0)、GL_TRUE が必要ですか? glVertexAttribPointerで正規化しますか?
質問 3:頂点データ/その他のデータにパディングが本当に必要ですか? sizeof(pos_data) = 16 のためだけに架空の pos_data.g を追加 == gpu に適していますか?

4

2 に答える 2

2

一般に、メモリを節約するために、常に半浮動小数点 (16 ビット浮動小数点) 拡張を目指すことができます。

あなたの実装は、ドローコールのオーバーヘッドを引き起こしているようです。(その場で!) 正規化すると、追加のオーバーヘッドが発生します。この一定のクワッドの複数のインスタンスを描画する場合、速度を上げるために次のことをお勧めします。

  • ジオメトリ シェーダーの実装。クワッドの 4 つの頂点を生成、変換、放出します。
  • 各クワッド インスタンスの変換マトリックスを含むテクスチャ バッファー オブジェクト(TBO) を使用した変換バッファーを使用したインスタンス化された描画(各マトリックス列には、組み込みのユニフォーム 'gl_InstanceID' を使用してアクセスします)。
    または:頂点属性配列
    を介して行列を提供します(おそらくより高速です)。これら 2 つのアプローチは、同じバッファー データ レイアウト (単なる行列の配列) に実装できます。
于 2012-08-13T23:25:29.600 に答える
1

しかし、なぜ -1.0, 1.0 だけに GL_float を使用する必要があるのでしょうか? GL_Byte で十分です。

これは一般に当てはまらないことに注意してください。ほとんどの場合、精度のために浮動小数点数が必要になります。また、値が非常に少なく、ジオメトリが非常に単純な場合、そもそも最適化する理由がまったくない可能性が非常に高くなりglByteます。頂点の数が非常に少ない可能性が高いのに、なぜそれらのストレージを節約したいのでしょうか? これは時期尚早の最適化の非常に良い例のように思えます (私は知っていますが、これは使い古された用語です)。

さて、実際の質問について:

  1. いいえ、同じ機能が必要な場合は違います。normalize が false の場合、-1は に変換され-1.0f、true の場合は-0.0078125f(または-1/128.0f) のようなものになります。したがって、同じスケールを維持したい場合は、正規化する必要はありません。
  2. GLclampf と GLfloat が 8 バイトの float であるという考えはどこから得られますか? 通常は 4 バイトの float です。頂点属性を介して RGB カラーを渡したい場合は、はい、OpenGL はカラー コンポーネントが範囲内にあると想定しているため、それらを正規化する必要があります[0.0f,1.0f]。しかし、繰り返しますが、単純に float として渡してはどうでしょうか? 何を得ると思いますか?単純なゲームでは、おそらく違いに気付くほど十分な色がなく、単純でないゲームではテクスチャを使用する可能性が高くなります。
  3. これについてはよくわかりません。私はそれが古い GPU に当てはまることを知っています (そして、ほぼ 10 年前のことを意味します) が、これが実際に何かを改善するという最近の主張を知りません. いずれにせよ、最もよく知られているアライメントは、1 つの頂点のすべての頂点属性を 32 バイト (の倍数) にまとめてプロップすることであり、それは ATI カード用でした。いくつかのトリッキーなこと/拡張にはバイトアライメントが必要かもしれませんが、まだ心配する必要はないと思います.
于 2012-08-13T22:02:05.507 に答える