【问题标题】:How do I manipulate objects independently of one another in OpenGL ES 2.0?如何在 OpenGL ES 2.0 中相互独立地操作对象?
【发布时间】:2012-02-25 21:37:15
【问题描述】:

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

然而,当我对 1.1 感到满意时,我意识到,部分基于 Apple 非常以 2.0 为中心的 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);
}

我知道那是非常草率的代码——我基本上复制并粘贴了缓冲区创建部分,以便让自己在不同的缓冲区中试验两个不同的顶点数组。它似乎奏效了,因为我可以在 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 或另一个进行转换。甚至不清楚上面的代码是否对一个特定的缓冲区进行了任何引用。

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

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

    • 所以想法是有一个 GLKViewController 并使用 NSObjects 来放置对象?然后,您可以操作每个 NSObject..
    • 是的,这基本上是正确的。我最终将我所有的形状重构为很好地封装的 NSObject,这使得它们更容易使用。我上面链接的教程是一个很好的开始。
    【解决方案2】:

    GLKMatrix4 _modelViewProjectionMatrix[5]; // 开始

    En - (void)update 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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      相关资源
      最近更新 更多