Предоставление OpenGL ES по требованию с использованием GLKit
Я изучаю преобразование кода рендеринга OpenGL, чтобы воспользоваться несколькими функциями GLKit
(а именно, асинхронной загрузкой текстур и автоматизацией, предоставляемой GLKView/Controller
). Тем не менее, похоже, что классы предназначены в основном для размещения людей с использованием цикла анимации, тогда как я работаю с рендерингом по требованию. Кроме того, некоторые из рендеринга относятся к текстуре, а не к фреймбуферу GLKView, поэтому я должен искать только подкласс GLKView и добавлять дополнительные FBOs?
Есть ли рекомендуемый подход для такого типа настройки? Я ожидал бы чего-то вроде:
- Установите контроллер вида
preferredFramesPerSecond
на 0
или просто
приостановить обновление фреймов?
- Игнорировать методы
glkViewControllerUpdate
или glkView:drawInRect:
и просто нарисуйте то, что мне нужно, когда мне это нужно.
- Используйте представление
setNeedsDisplay
как с обычным UIView
в порядке
для отображения кадра (мне нужно позвонить bindDrawable
, учитывая, что я
будет также рендерить текстуру?).
Возможно, это не стоит усилий, если это не то, для чего предназначен новый API? Я желаю, чтобы документация была немного более тщательной, чем она есть. Возможно, больше образцов будет предоставлено, когда API "созрел" немного...
Спасибо
Ответы
Ответ 1
Подход, который я использовал, заключался в том, чтобы не беспокоиться с GLKViewController
, но просто используйте GLKView
непосредственно под подклассом UIViewController
.
Очевидно, что GLKViewController
предназначен для людей, которым необходим последовательный цикл рендеринга для таких приложений, как игры. Без него рисование на GLKView
так же просто, как вызов [glkView setNeedsDisplay]
. Обязательно установите enableSetNeedsDisplay
на YES
, чтобы включить это поведение.
Если вы все еще хотите использовать GLKViewController
, вы можете отключить цикл рендеринга анимации в viewWillAppear
следующим образом:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated]; // setPaused automatically set to NO in super implementation
[self setPaused:YES];
}
Кроме того, установите resumeOnDidBecomeActive
на NO
, чтобы контроллер просмотра снова не возобновлялся автоматически.
Использование простого UIViewController
с GLKView
вполне приемлемо, но я видел, как он рекомендовал инженер Apple как подходящий способ выполнить рисование по требованию.
Ответ 2
Я только что конвертировал свой код с помощью менеджера EAGLContext, который я применил для использования классов GLKit.
Вы предлагаете вам "..игнорировать методы... glkView:drawInRect:
и просто нарисовать то, что вам нужно, когда мне это нужно". Это похоже на разумный выбор производительности; Я предполагаю (хотя и не пробовал), если вы просто не укажете GLKViewDelegate
или не предоставили подклассу GLKView
с ее drawInRect:
, тогда никакая анимация цикла анимации не произойдет. Вы пытались это сделать?
Альтернативой было бы просто создать несколько @property (assign, nonatomic) BOOL shouldUpdate;
в вашем классе MyController : GLKViewController <GLKViewDelegate>
, который будет обновляться только в том случае, если что-то делать:
[self setDelegate:self]; // in init or awakeFromNib or other..
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
if ([self shouldUpdate]) { ...
Я уверен, что вы поняли, что это сложно.
Следует упомянуть одно: официальные документы API указывают, что viewDidLoad
следует использовать в GLKViewController
для начальной настройки GL. У меня были проблемы с этим; по какой-то причине мои вызовы glCreateShader
всегда возвращаются в нуль. Возможно, это связано с тем, что я установил пост-инициализацию EAGLContext
; Я не мог передать его как параметр init
, так как я создал контроллер в Storyboard. Однако в коде не было ничего логичного, поэтому я предлагаю это дружественное предупреждение, если вы столкнулись с подобными проблемами. Мое решение состоит в том, чтобы в моем drawInRect было следующее:
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
if ([self initialGLSetupDone] == NO) {
[self beforeFirstRender];
[self setInitialGLSetupDone:YES];
}
// .. rest of render code goes here.
}
Очевидно, что это не идеальный вариант, чтобы иметь IF там без необходимости, но это было простое решение.
Сообщите мне, как это сделать, если вы попробуете обновить, чтобы использовать GLKit.
Ответ 3
После того, как вы создали GLKView, добавьте эту строку:
glkView.enableSetNeedsDisplay = TRUE;
(из-за этого никто не будет автоматически перерисовывать вид)
Если вы хотите перерисовать, вставьте эту строку:
[glkView setNeedsDisplay];
... тогда подпрограмма drawInRect
вызывается только один раз.
Надеюсь, что это поможет.