【发布时间】: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