Как мне управлять объектами независимо друг от друга в OpenGL ES 2.0?

Я создаю игру для iOS с OpenGL ES 2.0, которая содержит сцену с примерно 100 различными «объектами», которые мне нужно преобразовывать независимо друг от друга. Я новичок в OpenGL ES. Поэтому сначала я подумал, что мне следует начать с OpenGL ES 1.1, а затем перенести приложение на 2.0, чтобы воспользоваться преимуществами улучшенных визуальных эффектов.

Однако, когда я освоился с 1.1, я понял, частично на основе очень 2.0-ориентированного шаблона Xcode от Apple для OpenGL, что будет больше проблем, чем стоит бороться с переходом сразу на 2.0, так что я укусил пулю.

Теперь мне трудно понять концепции, достаточные для выполнения простых преобразований моих объектов массива вершин независимо друг от друга. Я читал в документации OpenGLES 2.0, что лучший способ сделать это - использовать несколько VBO, по одному для каждого массива вершин. Однако я не могу трансформировать один из них, не затрагивая всю сцену.

Я начал проект с шаблона Apple OpenGL ES и оптимизировал его так, чтобы метод setupGL выглядел так:

-(void)setupGL
{
    // Setup
    [EAGLContext setCurrentContext:self.context];        
    [self loadShaders];
    self.effect = [[GLKBaseEffect alloc] init];
    self.effect.light0.enabled = GL_TRUE;
    self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f);
    glEnable(GL_DEPTH_TEST); // do depth comparisons and update the depth buffer

    // Initialize first buffer
    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);    
    glGenBuffers(1, &_vertexBuffer);    
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);    
    glBufferData(GL_ARRAY_BUFFER, sizeof(gPyramidVertexData), gPyramidVertexData, GL_DYNAMIC_DRAW);
    glEnableVertexAttribArray(GLKVertexAttribPosition);    
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));    
    glBindVertexArrayOES(0);

    // Initialize second buffer
    glGenVertexArraysOES(2, &_vertexArray2);
    glBindVertexArrayOES(_vertexArray2);
    glGenBuffers(2, &_vertexBuffer2);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
    glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
    glBindVertexArrayOES(0);
}

Я знаю, что это невероятно небрежный код - я в основном скопировал и вставил часть создания буфера, чтобы настроить себя вверх для экспериментов с двумя разными vertextArrays в разных буферах. Похоже, это сработало, поскольку я могу визуализировать оба буфера в методе drawInRect:

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glBindVertexArrayOES(_vertexArray);
    glUseProgram(_program);
    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
    glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);    
    glDrawArrays(GL_TRIANGLES, 0, numberOfVerteces);

    glBindVertexArrayOES(_vertexArray2);
    glUseProgram(_program);
    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
    glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
    glDrawArrays(GL_TRIANGLES, 0, numberOfVerteces2);
}

Моя проблема возникает, когда я пытаюсь выполнить преобразования в одном массиве вершин, не затрагивая другой. Я попытался добавить преобразования в вышеуказанный метод непосредственно перед вызовом glDrawArrays, но безуспешно - я думаю, что это может работать только с 1.1. Похоже, что мои преобразования должны выполняться в методе обновления:

-(void)update
{
    float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);        
    self.effect.transform.projectionMatrix = projectionMatrix;

    GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation( 0.0f, 0.0f, -4.0f);
    baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _sceneRotation, 1.0f, 1.0f, 1.0f);

    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, zoomFactor);
    modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _objectRotation, 0.0f, 1.0f, 0.0f);
    modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);

    _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);
    _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);    
}

Однако именно здесь я действительно запутался - совсем не ясно, как я мог изменить этот метод, чтобы выполнять преобразования в один или другой VBO. Непонятно даже, ссылается ли приведенный выше код на какой-либо конкретный буфер.

В конце концов, я хотел бы расширить свою игру, переместив код для каждого игрового объекта в экземпляр настраиваемого класса, который будет обрабатывать преобразования и т. Д. Но я хотел бы знать, полностью ли я ошибаюсь в своем подходе перед этим.

5
задан todd412 3 February 2012 в 08:34
поделиться