opengl-es - 在一个着色器中为不同的属性使用不同的 GL_ELEMENT_ARRAY_BUFFER?

标签 opengl-es opengl-es-2.0

在 OpenGL (OpenGL ES 2.0) 中,我可以为不同的 GL_ARRAY_BUFFER 缓冲区使用多个 GL_ELEMENT_ARRAY_BUFFER 吗?我正在阅读“OpenGL ES 2.0 编程指南”,第 6 章“顶点属性、数组和缓冲区对象”,有源示例:有几个 GL_ARRAY_BUFFER(用于位置、法线、纹理坐标)和一个 GL_ELEMENT_ARRAY_BUFFER(“用于存储元素索引”)。

当我在写问题时,我发现我不能向 glDrawElements 发送一个以上的索引数组,所以如果我使用缓冲区,可能只有最后绑定(bind)的 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 float ,对索引使用 36 字节,对法线使用 36*3 float ?所以我只能为位置属性节省内存?

最佳答案

我希望我还不算太晚,但我所做的是在顶点数组中以每个顶点为基础设置法线,然后在声明顶点属性时使用适当的步幅和缓冲区偏移量。这是我声明顶点和法线的代码:

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));

我知道这可能会占用更多内存,但也许有人可以想出更好的解决方案。这是我能想到的解决您的问题。

关于opengl-es - 在一个着色器中为不同的属性使用不同的 GL_ELEMENT_ARRAY_BUFFER?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12188011/

相关文章:

java - 在适用于 Android 的 OpenGL ES 中使用 2D 游戏渲染图像

android - 在android上的opengles 2.0中绘制 Sprite 的最快方法

iphone - OpenGL ES 2.0 GLKit GL_LINE_SMOOTH 错误

opengl-es - 在 OpenGL ES 纹理中查找最小/最大值的最佳方法是什么

ios - 在 iOS 和 OpenGLES 2.0 中使用 sampler3D 纹理的 texture3D 查找是否可用

matrix - OpenGL 矩阵缩放然后翻译仍在缩放我的位置

opengl-es - 在顶点和片段着色器中访问同名统一失败

opengl - Tizen UI - Enlightenment Foundation 库中的 E17 和 EVAS

android - OpenGL ES 1.x vs. 2.x : OpenGL ES 1. x 还值得学习吗?

opengl-es - WebGL - 在平面上显示球体