ios - 如何在 OpenGL ES 2.0 中独立操作对象?

标签 ios opengl-es opengl-es-2.0

我正在使用 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);
}

我知道那是非常草率的代码——我基本上是复制并粘贴缓冲区创建部分来设置自己,以便在不同的缓冲区中试验两个不同的 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 或另一个进行转换。甚至不清楚上面的代码是否引用了一个特定的缓冲区。

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

最佳答案

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

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

关于ios - 如何在 OpenGL ES 2.0 中独立操作对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9125770/

相关文章:

ios - 等待网络调用完成

ios - 如何增加 apple Pay 操作的失败超时时间?

ios - 自动布局中的相对中心

iphone - 如何在 cocos2d Xcode 中平滑移动按钮

c++ - 顶点位置/法线/坐标无法正确渲染

android - React Native 自定义字体额外填充

java - 尝试以编程方式将 GLSurfaceView 添加到布局

iphone - OpenGL ES - 如何使某些对象保持固定大小?

ios - OpenGL photoshop 叠加混合模式