Рендеринг OpenGL ES по требованию с использованием GLKit - PullRequest
18 голосов
/ 13 октября 2011

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

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

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

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

Спасибо

Ответы [ 3 ]

23 голосов
/ 08 ноября 2011

Подход, который я в итоге использовал, заключался в том, чтобы не беспокоиться о 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's implementation

    [self setPaused:YES];
}

Кроме того, установите resumeOnDidBecomeActive на NO, чтобы предотвратить автоматическое возобновление контроллера вида.

Использование простого UIViewController с GLKView вполне приемлемо, однако, я видел его рекомендованным инженером Apple как подходящий способ выполнения рисования по требованию.

3 голосов
/ 22 октября 2011

Я только что преобразовал свой код из диспетчера 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]) { ...

I 'Я уверен, что вы поняли идею, это вряд ли сложно.

Стоит отметить одну вещь: в официальных документах API указано, что viewDidLoad должен использоваться в вашем GLKViewController для начальной настройки GL.У меня были проблемы с этим;почему-то мои glCreateShader звонки всегда возвращали ноль.Это может быть связано с тем, что я установил EAGLContext после инициализации;Я не мог передать его как параметр init, так как я создал контроллер в раскадровке.Однако в коде не было ничего логически неправильного, поэтому я предлагаю это дружеское предупреждение на случай возникновения подобных проблем.Мое решение состоит в том, чтобы просто иметь следующее в моем 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.

1 голос
/ 08 ноября 2011

После того, как вы создали GLKView, добавьте эту строку:

glkView.enableSetNeedsDisplay = TRUE;

(из-за этого никто не будет перерисовывать вид автоматически)

Если вы хотите перерисовать, вставьте эту строку:

[glkView setNeedsDisplay];

... тогда drawInRect процедура будет вызываться только один раз.

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

...