Правильное место для настройки шейдеров для GLKView?

У меня возникли проблемы с поиском правильного места для настройки шейдера для приложения OpenGLES с использованием GLKView и GLKViewController.

Кажется, что viewDidLoad — это естественное место для этого, но создание шейдера терпит неудачу, когда я пытаюсь сделать это здесь. Моя установка примерно такая:

//shader helper method
int setupShaders(const char* vShader, const char* fShader); //returns a program handle

//inside GLKViewController subclass

static int program;

-(void)viewDidLoad{
    [super viewDidLoad];
    program = setupShaders(vsh, fsh); //program will be zero indicating setup failure
}

Я знаю, что код установки работает, потому что он преуспевает, если я вызываю его внутри -(void)glkView:(GLKView *)view drawInRect:(CGRect)rect.

Итак, я предполагаю, что OpenGL не полностью инициализирован, когда вызывается -(void)viewDidLoad, или что-то нужно сделать, чтобы установить правильный контекст OpenGL для настройки, которую я пытаюсь сделать, я просто не могу найти никакой документации где и как сделать настройку правильно.


person sak    schedule 03.09.2013    source источник


Ответы (3)


Вы правы в том, что самое раннее место, где вы можете легко настроить свои шейдеры, находится в методе drawRect. Это потому, что должен быть действительный текущий контекст GL. Согласно документации GLKView:

Перед вызовом метода drawRect: представление делает свой объект EAGLContext текущим контекстом OpenGL ES и привязывает свой объект кадрового буфера к контексту OpenGL ES в качестве цели для команд рендеринга.

Итак, проще всего ухватиться за какую-то информацию, например дескриптор program, и инициализировать только в том случае, если он не равен нулю.

if (program == 0)
    program = setupShaders(vsh, fsh);

Если вам не нравится такой подход, вы можете инициализировать свой GLKView контекстом, который вы предоставляете, или переопределить bindDrawable. Или вы не могли бы использовать GLKView и делать что-то вручную...

person Jacob Foshee    schedule 04.09.2013

Должен быть текущий EAGLContext, прежде чем вы сможете вызывать любой API OpenGL ES, и это включает работу по настройке, такую ​​​​как компиляция шейдеров. GLKView делает свой контекст текущим перед вызовом вашего метода drawRect: (или glkView:drawInRect:), но вы можете сделать его текущим контекстом в любое время.

Контекст представления актуален с viewDidAppear:, потому что этот метод вызывается после первого отрисовки представления. Я не уверен, что он гарантированно будет актуальным на тот момент — нет задокументированного контракта API, согласно которому контекст GLKView останется текущим после окончания отрисовки. Так что лучше вызывать [EAGLContext setCurrentContext:myContext] самостоятельно всякий раз, когда вы хотите выполнить настройку вашей сцены OpenGL ES (даже если вы решите сделать это в viewDidAppear:).

См. шаблон Игра OpenGL ES при создании нового проекта Xcode для примера настройки GLKView/GLKViewController.

person rickster    schedule 06.09.2013

Так что получается, что он отлично работает, если вы инициализируете изнутри -(void)viewDidAppear. Решение Джейкоба также работает нормально, но мне кажется более правильным использовать обратный вызов, а не добавлять условное выражение к методу рисования.

person sak    schedule 06.09.2013