Подтвердить что ты не робот

Предоставление OpenGL ES по требованию с использованием GLKit

Я изучаю преобразование кода рендеринга OpenGL, чтобы воспользоваться несколькими функциями GLKit (а именно, асинхронной загрузкой текстур и автоматизацией, предоставляемой GLKView/Controller). Тем не менее, похоже, что классы предназначены в основном для размещения людей с использованием цикла анимации, тогда как я работаю с рендерингом по требованию. Кроме того, некоторые из рендеринга относятся к текстуре, а не к фреймбуферу GLKView, поэтому я должен искать только подкласс GLKView и добавлять дополнительные FBOs?

Есть ли рекомендуемый подход для такого типа настройки? Я ожидал бы чего-то вроде:

  • Установите контроллер вида preferredFramesPerSecond на 0 или просто приостановить обновление фреймов?
  • Игнорировать методы glkViewControllerUpdate или glkView:drawInRect: и просто нарисуйте то, что мне нужно, когда мне это нужно.
  • Используйте представление setNeedsDisplay как с обычным UIView в порядке для отображения кадра (мне нужно позвонить bindDrawable, учитывая, что я будет также рендерить текстуру?).

Возможно, это не стоит усилий, если это не то, для чего предназначен новый API? Я желаю, чтобы документация была немного более тщательной, чем она есть. Возможно, больше образцов будет предоставлено, когда API "созрел" немного...

Спасибо

4b9b3361

Ответ 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 вызывается только один раз.

Надеюсь, что это поможет.