3

OpenGL (OpenGL ES 2.0) では、異なる GL_ARRAY_BUFFER バッファに対して複数の GL_ELEMENT_ARRAY_BUFFER を使用できますか? 「OpenGL ES 2.0 プログラミング ガイド」の第 6 章「頂点属性、配列、およびバッファ オブジェクト」を読んでいます。ソースの例があります。要素インデックス」)。

質問を書いているときに、複数のインデックス配列を glDrawElements に送信できないことがわかったので、バッファを使用する場合、最後にバインドされた GL_ELEMENT_ARRAY_BUFFER のみが描画に使用されている可能性があります。しかし、メモリの節約についてはどうですか (glDrawElements の目的は何ですか)? 私が直面した問題を説明します。

2 つの配列があります (GL_ARRAY_BUFFER として) - 8 つの頂点と 6 つの法線

GLfloat gVertexPositions[] =
{
    0.5f, 0.5f, 0.5f,
    0.5f, -0.5f, 0.5f,
    -0.5f, -0.5f, 0.5f,
    -0.5f, 0.5f, 0.5f,
    0.5f, 0.5f, -0.5f,
    0.5f, -0.5f, -0.5f,
    -0.5f, -0.5f, -0.5f,
    -0.5f, 0.5f, -0.5f
};

GLfloat gVertexNormals[] =
{
    1.0f, 0.0f, 0.0f,  // top
    -1.0f, 0.0f, 0.0f, // bottom
    0.0f, 1.0f, 0.0f,  // right
    0.0f, -1.0f, 0.0f, // left
    0.0f, 0.0f, 1.0f,  // back
    0.0f, 0.0f, -1.0f  // front
};

インデックスの 2 つの配列 (GL_ELEMENT_ARRAY_BUFFER として)

GLubyte gVertexPositionIndices[] =
{
    0, 1, 2, // top
    2, 3, 0,
    0, 4, 1, // right
    1, 4, 5,
    5, 4, 7, // bottom
    6, 5, 7,
    2, 6, 7, // left
    2, 7, 3,
    1, 4, 2, // front
    2, 4, 5,
    0, 3, 4, // back
    7, 4, 3
};

GLubyte gVertexNormalIndices[] =
{
    0, 0, 0,
    0, 0, 0,
    2, 2, 2,
    2, 2, 2,
    1, 1, 1,
    1, 1, 1,
    3, 3, 3,
    3, 3, 3,
    5, 5, 5,
    5, 5, 5,
    4, 4, 4,
    4, 4, 4
};

頂点属性の状態を設定します

    glBindAttribLocation(program, ATTRIB_POSITION, "a_position");
    glBindAttribLocation(program, ATTRIB_NORMAL, "a_normal");

//.....

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[VBO_POSITION_INDICES]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * 36, gVertexPositionIndices, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, vboIds[VBO_POSITION_DATA]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * 8, gVertexPositions, GL_STATIC_DRAW); 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[VBO_NORMAL_INDICES]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * 36, gVertexNormalIndices, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, vboIds[VBO_NORMAL_DATA]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * 6, gVertexNormals, GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[VBO_POSITION_INDICES]);
    glBindBuffer(GL_ARRAY_BUFFER, vboIds[VBO_POSITION_DATA]);
    glEnableVertexAttribArray(ATTRIB_POSITION);

    glBindBuffer(GL_ARRAY_BUFFER, vboIds[VBO_NORMAL_DATA]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[VBO_NORMAL_INDICES]);
    glEnableVertexAttribArray(ATTRIB_NORMAL);

    glVertexAttribPointer(ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glVertexAttribPointer(ATTRIB_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, 0);

次に描く

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, 0);

そして画面は空です(最後のGL_ELEMENT_ARRAY_BUFFERが「a_position」属性に使用されているため、すべてのトリプレットは同じ番号を持っています)

私が望むすべて - プログラムは 36 個の頂点を作成し、gVertexPositionIndices を使用して gVertexPositions から位置を設定し、gVertexNormalIndices を使用して gVertexNormals から法線を設定します。それが可能かどうかは疑問ですが、正確に知りたいです。また、それが不可能な場合、どのような方法が正しいでしょうか? 位置に 8*3 浮動小数点数、インデックスに 36 バイト、法線に 36*3 浮動小数点数を使用する必要がありますか? では、位置属性だけにメモリを節約できますか?

4

1 に答える 1

1

手遅れではないことを願っていますが、頂点配列内で頂点ごとに法線を設定し、頂点属性を宣言するときに適切なストライドとバッファー オフセットを使用します。頂点と法線を宣言するコードは次のとおりです。

GLfloat BlockVertexData[144] = {

//Right side...  
//Vertices...            //Normals...        
 1.0f,  2.0f,  0.5f,     1.0f,  0.0f,  0.0f, //B
 1.0f,  2.0f, -0.5f,     1.0f,  0.0f,  0.0f, //F
 1.0f, -2.0f,  0.5f,     1.0f,  0.0f,  0.0f, //D
 1.0f, -2.0f, -0.5f,     1.0f,  0.0f,  0.0f, //H

//Front side...
-1.0f,  2.0f,  0.5f,     0.0f,  0.0f,  1.0f, //A
 1.0f,  2.0f,  0.5f,     0.0f,  0.0f,  1.0f, //B
-1.0f, -2.0f,  0.5f,     0.0f,  0.0f,  1.0f, //C
 1.0f, -2.0f,  0.5f,     0.0f,  0.0f,  1.0f, //D

//Left side...
-1.0f,  2.0f,  0.5f,    -1.0f,  0.0f,  0.0f, //A
-1.0f,  2.0f, -0.5f,    -1.0f,  0.0f,  0.0f, //E
-1.0f, -2.0f,  0.5f,    -1.0f,  0.0f,  0.0f, //C
-1.0f, -2.0f, -0.5f,    -1.0f,  0.0f,  0.0f, //G

//Back side...
-1.0f,  2.0f, -0.5f,     0.0f,  0.0f, -1.0f, //E
 1.0f,  2.0f, -0.5f,     0.0f,  0.0f, -1.0f, //F
-1.0f, -2.0f, -0.5f,     0.0f,  0.0f, -1.0f, //G
 1.0f, -2.0f, -0.5f,     0.0f,  0.0f, -1.0f, //H

//Top side...
-1.0f,  2.0f, -0.5f,     0.0f,  1.0f,  0.0f, //E
 1.0f,  2.0f, -0.5f,     0.0f,  1.0f,  0.0f, //F
-1.0f,  2.0f,  0.5f,     0.0f,  1.0f,  0.0f, //A
 1.0f,  2.0f,  0.5f,     0.0f,  1.0f,  0.0f, //B

//Bottom side...
-1.0f, -2.0f, -0.5f,     0.0f, -1.0f,  0.0f, //G
 1.0f, -2.0f, -0.5f,     0.0f, -1.0f,  0.0f, //H
-1.0f, -2.0f,  0.5f,     0.0f, -1.0f,  0.0f, //C
 1.0f, -2.0f,  0.5f,     0.0f, -1.0f,  0.0f  //D };

GLuint BlockIndicesData[36] = {

//Right side...
2, 0, 3,     0, 1, 3,

//Front side...
6, 4, 7,     4, 5, 7,

//Left side...
11, 10, 8,    8, 9, 11,

//Back side...
15, 14, 12,  12, 13, 15,

//Top side...
19, 18, 16,  16, 17, 19,

//Bottom side...
23, 22, 20,  20, 21, 23 };

属性を宣言するコードは次のとおりです。

// The stride shows that there are 6 floats in each row.
GLsizei stride = 6 * sizeof(GLfloat);
GLuint attribute;

attribute = glGetAttribLocation(program, "VertexPosition");
glEnableVertexAttribArray(attribute);
glVertexAttribPointer(attribute, 3, GL_FLOAT, GL_FALSE, stride, 0);

attribute = glGetAttribLocation(self.program, "VertexNormal");
glEnableVertexAttribArray(attribute);
// The sixth parameter indicates the buffer offset, so here there were 3 floats preceding it, so this indicates it.
glVertexAttribPointer(attribute, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid *)(sizeof(GLfloat) * 3));

これがより多くのメモリを占有する可能性があることはわかっていますが、誰かがより良い解決策を思い付くことができるかもしれません. これは、あなたの問題を解決するために私が考えることができるものです.

于 2014-02-14T21:21:09.193 に答える