OpenGL ES 1.1 объект буфера вершин не работает - PullRequest
4 голосов
/ 18 декабря 2011

Я занимаюсь разработкой игры для iPhone с использованием OpenGL ES 1.1, и мне нужно использовать объекты буфера вершин для рендеринга более 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 . SceneObjects - это объекты в игре, которые можно рендерить. Они ссылаются на экземпляр 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 не будет рисовать мои SceneObjects.
  • предоставьте правильный способ сделать то, что я пытаюсь сделать (в соответствии с моей структурой, пожалуйста)
  • предоставить любые предложения или ссылки, которые могут помочь (необязательно)

Большое спасибо!

Ответы [ 2 ]

1 голос
/ 08 марта 2012

Я не испытываю различий между OpenGL и OpenGL ES, но я не вижу никаких вызовов glEnableVertexAttribArray () в вашем коде.

Эта функция подозрительно отсутствует в OpenGL ES 1.1 документах , но содержится в 2.0 и используется в статье Apple OpenGL ES VBO (спасибо JSPerfUnkn0wn ).

Вот некоторые другие хорошие (хотя и не-ES) учебные пособия по объектам буфера вершин и объектам буфера индекса .

0 голосов
/ 28 декабря 2011

Если я что-то упустил, куда вы загружаете текстуры?Вы устанавливаете координаты текстуры, но я не вижу glBindTexture.И я также предполагаю, что alpha является допустимым значением.

См. статью Apple OpenGL ES VBO, именно из Листинга 9-1, и это OpenGL ES VBO учебное пособие .

...