Вот пример приложения «GLKView Subview», которое я написал на основе примера проекта OpenGL Game в Xcode 4.5. Он создает подпредставление GLKView с его делегатом, установленным в GLKViewController владельца файла, так что оба представления OpenGL ES 2 управляются одним контроллером:
Вот скриншот, я подкрасил фон подвида красным для контраста:
Я был взволнован тем, что у меня был простой способ добавить несколько GLKView под один GLKViewController и EAGLContext (для обмена текстурами и т. д.), пока я не понял, что размер кадра разбит:
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
NSLog(@"My view frame: %@", NSStringFromCGRect(view.bounds));
float aspect = fabsf(view.bounds.size.width / 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, _rotation, 0.0f, 1.0f, 0.0f);
// Compute the model view matrix for the object rendered with GLKit
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f);
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
self.effect.transform.modelviewMatrix = modelViewMatrix;
// Compute the model view matrix for the object rendered with ES2
modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f);
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
_normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);
_modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
if(view == self.view)
{
glClearColor(0.65f, 0.65f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArrayOES(_vertexArray);
// Render the object with GLKit
[self.effect prepareToDraw];
glDrawArrays(GL_TRIANGLES, 0, 36);
// Render the object again with ES2
glUseProgram(_program);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
glDrawArrays(GL_TRIANGLES, 0, 36);
[self.subview display];
}
else
{
glClearColor(1.0f, 0.65f, 0.65f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArrayOES(_vertexArray);
// Render the object with GLKit
[self.effect prepareToDraw];
glDrawArrays(GL_TRIANGLES, 0, 36);
// Render the object again with ES2
glUseProgram(_program);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);
glDrawArrays(GL_TRIANGLES, 0, 36);
}
}
Вывод в iOS Simulator с iPhone 4" Retina:
2013-04-27 15:50:56.149 GLKView Subview[48136:11903] My view frame: {{0, 0}, {568, 320}}
2013-04-27 15:50:56.152 GLKView Subview[48136:11903] My view frame: {{0, 0}, {248, 100}}
Кадр подпредставления должен быть {100, 100}, но по какой-то причине он выходит на {248, 100}. Я перепробовал все, что мог придумать, даже встроил его в UIView, думая, что, возможно, его ограничения автоматического изменения размера были установлены неправильно, если основной GLKView был его родителем. Как вы можете видеть, размер UIView правильный, но размер дочернего GLKView не соответствует размеру.
Как разработчик, это казалось первым, что нужно попробовать, но у Apple обычно другие идеи. Без автоматического изменения размера GLKView бесполезен для макетов произвольной формы, которые работают с любым размером устройства.
Мне удалось заставить несколько GLKViewController, совместно использующих один EAGLContext, работать как дочерние контроллеры в другом проекте. Но я не понимаю, почему мы должны нести груз создания GLKViewController каждый раз, когда мы хотим добавить GLKView на экран. Я предполагаю, что GLKViewController путается, когда он является делегатом для GLKView, который не является его собственным представлением.
Мне также удалось заставить мои представления работать вручную, просто используя glViewport(), и после потери двух дней из-за проблем с GLKView я, вероятно, порекомендовал бы пойти по этому пути всем, кто читает это (также получая преимущества кроссплатформенности).
Я надеюсь, что есть простое объяснение/исправление, даже если это просто «вам нужно создать GLKViewController для каждого GLKView». Заранее спасибо всем, кому удастся заставить его работать. Если нет, возможно, кому-то поможет пример этой функции bug.