如何在OpenGL ES 2.0中相互独立地操作对象?

时间:2012-02-03 08:34:51

标签: ios opengl-es opengl-es-2.0

我正在使用OpenGL ES 2.0构建一个iOS游戏,其中包含一个包含大约100个不同“对象”的场景,我需要能够彼此独立地进行转换。我是OpenGL ES的新手。因此,我最初认为我应该从OpenGL ES 1.1开始,然后将应用程序迁移到2.0以利用增强的视觉效果。

然而,正如我对1.1感到满意一样,我意识到,部分基于Apple的以OpenGL为中心的Xcode模板,它会比直接进入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);
}

我知道这是令人难以置信的邋code代码 - 我基本上复制并粘贴了缓冲区创建部分,以便在不同的缓冲区中尝试使用两个不同的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或另一个。上面的代码根本没有对任何特定缓冲区进行任何引用,这一点甚至都不清楚。

最终我想通过将每个游戏对象的代码移动到自定义类的实例来扩展我的游戏,该实例将处理转换等。但我想知道我的方法是否完全被误导在这之前。

2 个答案:

答案 0 :(得分:4)

如果这对有类似问题的人有帮助,我在Ian Terrell的优秀博客Games by Ian Terrell找到了我想要的答案。

特别是this tutorial及其随附的示例代码正是我需要掌握这个非常复杂的主题。希望这有帮助!

答案 1 :(得分:0)

GLKMatrix4 _modelViewProjectionMatrix [5]; // Al inicio

En - (void)更新utiliza GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(-1.0f,1.0f,-1.0f / aspect,1.0f / aspect,-10.0f,10.0f);

for (int i=0; i<5;i++) {
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(i*0.2+ 0.3f, 0.0f, 0.0f);
    modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, GLKMatrix4MakeZRotation(0.0 - _rotation));
    modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, GLKMatrix4MakeXRotation(0.0 - _rotation));
    modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, GLKMatrix4MakeYRotation(0.20 - _rotation));

   _modelViewProjectionMatrix[i] = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
}