Я создаю игру для iOS с OpenGL ES 2.0, которая содержит сцену с около 100 различными «объектами», которые мне нужно преобразовывать независимо друг от друга. Я новичок в OpenGL ES. Поэтому я сначала подумал, что мне следует начать с OpenGL ES 1.1, а затем перенести приложение на 2.0, чтобы воспользоваться расширенными визуальными эффектами.
Однако, как только я освоился с 1.1, я понял, отчасти основываясь на очень 2.0-центрированном Apple-шаблоне Xcode для 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 или другой. Даже не ясно, что приведенный выше код вообще ссылается на один конкретный буфер.
В конечном итоге я хотел бы расширить свою игру, перенеся код для каждого игрового объекта в экземпляр пользовательского класса, который будет обрабатывать преобразования и т. Д. Но я хотел бы знать, полностью ли я ошибочен в своем подходе перед этим.