OpenGL ES 1.1 顶点缓冲区对象不工作

发布于 2024-12-21 19:54:14 字数 4463 浏览 3 评论 0原文

我正在使用 OpenGL ES 1.1 开发一款 iPhone 游戏,需要使用顶点缓冲区对象来渲染 500 多个粒子而不降低性能。

我的游戏能够使用非 VBO 方法成功绘制,但现在我尝试合并 VBO,却不再绘制任何内容。

请帮助我找出我做错了什么并提供一个正确的例子。

我有一个名为 TexturedQuad 的类,它由以下内容组成:

// TexturedQuad.h

enum {
    ATTRIB_POSITION,
    ATTRIB_TEXTURE_COORD
 };

@interface TexturedQuad : NSObject {

    GLfloat *textureCoords; // 8 elements for 4 points (u and v)
    GLfloat *vertices;      // 8 elements for 4 points (x and y)
    GLubyte *indices;       // how many elements does this need?

    // vertex buffer array IDs generated using glGenBuffers(..)
    GLuint vertexBufferID;
    GLuint textureCoordBufferID;
    GLuint indexBufferID;

    // ...other ivars
}

// @synthesize in .m file for each property
@property (nonatomic, readwrite) GLfloat *textureCoords;
@property (nonatomic, readwrite) GLfloat *vertices;
@property (nonatomic, readwrite) GLubyte *indices;
@property (nonatomic, readwrite) GLuint vertexBufferID;
@property (nonatomic, readwrite) GLuint textureCoordBufferID;
@property (nonatomic, readwrite) GLuint indexBufferID;

// vertex buffer object methods
- (void) createVertexBuffers;
- (void) createTextureCoordBuffers;
- (void) createIndexBuffer;

TexturedQuad.m 中,创建顶点缓冲区:

- (void) createVertexBuffers {
    glGenBuffers(1, &vertexBufferID);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}

- (void) createTextureCoordBuffers {
    glGenBuffers(1, &textureCoordBufferID);
    glBindBuffer(GL_ARRAY_BUFFER, textureCoordBufferID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(textureCoords), textureCoords, GL_STATIC_DRAW);
}

- (void) createIndexBuffer {
    glGenBuffers(1, &indexBufferID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * 16, indices, GL_STATIC_DRAW);
}

上述 VBO 创建方法由自定义 调用AtlasLibrary 类初始化每个TexturedQuad 实例。

首先,顶点按以下格式排列:

// bottom left
quad.vertices[0] = xMin;
quad.vertices[1] = yMin;

// bottom right
quad.vertices[2] = xMax;
quad.vertices[3] = yMin;

// top left
quad.vertices[4] = xMin;
quad.vertices[5] = yMax;

// top right
quad.vertices[6] = xMax;
quad.vertices[7] = yMax;

其次,纹理坐标按以下格式排列(翻转以考虑 OpenGL ES 镜像图像的趋势):

// top left (of texture)
quad.textureCoords[0] = uMin;
quad.textureCoords[1] = vMax;

// top right
quad.textureCoords[2] = uMax;
quad.textureCoords[3] = vMax;

// bottom left
quad.textureCoords[4] = uMin;
quad.textureCoords[5] = vMin;

// bottom right
quad.textureCoords[6] = uMax;
quad.textureCoords[7] = vMin;

..接下来,VBO 创建方法被调用(在 AtlasLibrary 中)

[quad createVertexBuffers];
[quad createTextureCoordBuffers];
[quad createIndexBuffer];

现在是主要内容。 SceneObject 类。场景对象是游戏中可渲染的对象。它们引用TexturedQuad实例并包含有关旋转、平移和缩放的信息。

这是 SceneObject 中的渲染方法:

- (void) render {

    // binds texture in OpenGL ES if not already bound
    [[AtlasLibrary sharedAtlasLibrary] ensureContainingTextureAtlasIsBoundInOpenGLES:self.containingAtlasKey];

    glPushMatrix();

    glTranslatef(translation.x, translation.y, translation.z);

    glRotatef(rotation.x, 1, 0, 0);
    glRotatef(rotation.y, 0, 1, 0);
    glRotatef(rotation.z, 0, 0, 1);

    glScalef(scale.x, scale.y, scale.z);

    // change alpha
    glColor4f(1.0, 1.0, 1.0, alpha);

    // vertices
    glBindBuffer(GL_ARRAY_BUFFER, texturedQuad.vertexBufferID);
    glVertexAttribPointer(ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT), &texturedQuad.vertices[0]);


    // texture coords
    glBindBuffer(GL_ARRAY_BUFFER, texturedQuad.textureCoordBufferID);
    glVertexAttribPointer(ATTRIB_TEXTURE_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT), &texturedQuad.textureCoords[0]);

    // bind index buffer array
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, texturedQuad.indexBufferID);

    // draw
    glDrawElements(GL_TRIANGLE_STRIP, sizeof(texturedQuad.indices) / sizeof(texturedQuad.indices[0]), GL_UNSIGNED_BYTE, texturedQuad.indices);

    glPopMatrix();
}

我强烈感觉我的索引数组结构不正确,或者 glDrawElements(..) 函数调用不正确。

要回答这个问题,请:

  • 确定我做错了什么,导致 OpenGL ES 无法绘制我的场景对象。
  • 提供正确的方法来完成我想做的事情(请根据我的框架)
  • 提供任何可能有帮助的建议或链接(可选)

非常感谢!

I am developing an iPhone game using OpenGL ES 1.1 and need to use vertex buffer objects in order to render 500+ particles without the performance decreasing.

My game was able to draw successfully using the non-VBO method, but now that I've attempted to incorporate VBOs, nothing is drawing anymore.

Please help me to identify what I am doing wrong and provide a correct example.

I have a class called TexturedQuad which consists of the following:

// TexturedQuad.h

enum {
    ATTRIB_POSITION,
    ATTRIB_TEXTURE_COORD
 };

@interface TexturedQuad : NSObject {

    GLfloat *textureCoords; // 8 elements for 4 points (u and v)
    GLfloat *vertices;      // 8 elements for 4 points (x and y)
    GLubyte *indices;       // how many elements does this need?

    // vertex buffer array IDs generated using glGenBuffers(..)
    GLuint vertexBufferID;
    GLuint textureCoordBufferID;
    GLuint indexBufferID;

    // ...other ivars
}

// @synthesize in .m file for each property
@property (nonatomic, readwrite) GLfloat *textureCoords;
@property (nonatomic, readwrite) GLfloat *vertices;
@property (nonatomic, readwrite) GLubyte *indices;
@property (nonatomic, readwrite) GLuint vertexBufferID;
@property (nonatomic, readwrite) GLuint textureCoordBufferID;
@property (nonatomic, readwrite) GLuint indexBufferID;

// vertex buffer object methods
- (void) createVertexBuffers;
- (void) createTextureCoordBuffers;
- (void) createIndexBuffer;

In TexturedQuad.m, the vertex buffers are created:

- (void) createVertexBuffers {
    glGenBuffers(1, &vertexBufferID);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
}

- (void) createTextureCoordBuffers {
    glGenBuffers(1, &textureCoordBufferID);
    glBindBuffer(GL_ARRAY_BUFFER, textureCoordBufferID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(textureCoords), textureCoords, GL_STATIC_DRAW);
}

- (void) createIndexBuffer {
    glGenBuffers(1, &indexBufferID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * 16, indices, GL_STATIC_DRAW);
}

The above VBO creation methods are invoked by a custom AtlasLibrary class which initializes each TexturedQuad instance.

Firstly, the vertices are arranged in the following format:

// bottom left
quad.vertices[0] = xMin;
quad.vertices[1] = yMin;

// bottom right
quad.vertices[2] = xMax;
quad.vertices[3] = yMin;

// top left
quad.vertices[4] = xMin;
quad.vertices[5] = yMax;

// top right
quad.vertices[6] = xMax;
quad.vertices[7] = yMax;

Secondly, texture coordinates are arranged in the following format (flipped to account for OpenGL ES's tendency to mirror images):

// top left (of texture)
quad.textureCoords[0] = uMin;
quad.textureCoords[1] = vMax;

// top right
quad.textureCoords[2] = uMax;
quad.textureCoords[3] = vMax;

// bottom left
quad.textureCoords[4] = uMin;
quad.textureCoords[5] = vMin;

// bottom right
quad.textureCoords[6] = uMax;
quad.textureCoords[7] = vMin;

...next, the VBO-creation methods are called (in AtlasLibrary)

[quad createVertexBuffers];
[quad createTextureCoordBuffers];
[quad createIndexBuffer];

Now the meat and potatoes. The SceneObject class. SceneObjects are objects in the game that are renderable. They reference a TexturedQuad instance and contain information about rotation, translation, and scale.

Here is the render method in SceneObject:

- (void) render {

    // binds texture in OpenGL ES if not already bound
    [[AtlasLibrary sharedAtlasLibrary] ensureContainingTextureAtlasIsBoundInOpenGLES:self.containingAtlasKey];

    glPushMatrix();

    glTranslatef(translation.x, translation.y, translation.z);

    glRotatef(rotation.x, 1, 0, 0);
    glRotatef(rotation.y, 0, 1, 0);
    glRotatef(rotation.z, 0, 0, 1);

    glScalef(scale.x, scale.y, scale.z);

    // change alpha
    glColor4f(1.0, 1.0, 1.0, alpha);

    // vertices
    glBindBuffer(GL_ARRAY_BUFFER, texturedQuad.vertexBufferID);
    glVertexAttribPointer(ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT), &texturedQuad.vertices[0]);


    // texture coords
    glBindBuffer(GL_ARRAY_BUFFER, texturedQuad.textureCoordBufferID);
    glVertexAttribPointer(ATTRIB_TEXTURE_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT), &texturedQuad.textureCoords[0]);

    // bind index buffer array
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, texturedQuad.indexBufferID);

    // draw
    glDrawElements(GL_TRIANGLE_STRIP, sizeof(texturedQuad.indices) / sizeof(texturedQuad.indices[0]), GL_UNSIGNED_BYTE, texturedQuad.indices);

    glPopMatrix();
}

I have a strong feeling that either my indices array is structured incorrectly or that the glDrawElements(..) function is called incorrectly.

To answer this question, please:

  • identify what I am doing incorrectly that would cause OpenGL ES to not draw my SceneObjects.
  • provide the correct way to do what I am trying to do (according to my framework, please)
  • provide any suggestions or links which may help (optional)

Thanks so much!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

指尖微凉心微凉 2024-12-28 19:54:15

我对 OpenGL 和 OpenGL ES 之间的差异没有经验,但我没有看到任何对 glEnableVertexAttribArray() 在您的代码中。

OpenGL ES 1.1 文档中可疑地缺少该函数,但是位于 2.0,并用于 Apple 的 OpenGL ES VBO 文章(感谢 JSPerfUnkn0wn)。

这里还有一些关于 Vertex 的其他不错的(非 ES)教程缓冲区对象索引缓冲区对象

I'm not experienced in the differences between OpenGL and OpenGL ES, but I'm not seeing any calls to glEnableVertexAttribArray() in your code.

The function is suspiciously absent in the OpenGL ES 1.1 docs, but is in 2.0, and is being used in Apple's OpenGL ES VBO article (thanks JSPerfUnkn0wn).

Here are some other good (though, non-ES) tutorials on Vertex Buffer Objects, and Index Buffer Objects.

自在安然 2024-12-28 19:54:15

除非我遗漏了什么,否则你在哪里加载纹理?您正在设置纹理坐标,但我没有看到 glBindTexture。我还假设 alpha 是一个有效值。

请参阅 Apple OpenGL ES VBO 文章, 即来自清单 9-1,而这个 OpenGL ES VBO 教程

Unless I'm missing something, where are you loading the textures? You're setting texture coordinates but I see no glBindTexture. And I'm also assuming alpha is a valid value.

See Apple OpenGL ES VBO article, namely from Listing 9-1, and this OpenGL ES VBO tutorial.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文