2013-08-08 2 views
4

Я пытаюсь создать подкласс CAEAGLLayer с контекстом gl. То есть вместо создания подкласса UIView, который возвращает CAEAGLLayer и привязывает gl-контекст к этому слою из подкласса UIView, я непосредственно подклассифицирую этот слой и пытаюсь настроить контекст в инициализации слоя, например:как создать подкласс CAEAGLLayer с контекстом openGL: текущий фреймбуфер недействителен

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     self.opaque = YES; 

     _glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 
     NSAssert([EAGLContext setCurrentContext:_glContext], @""); 

     glGenRenderbuffers(1, &_colorRenderBuffer); 
     glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer); 
     [_glContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:self]; 

     glGenFramebuffers(1, &_framebuffer); 
     glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); 
     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer); 

     /// . . . 

до этого момента все кажется прекрасным. Тем не менее, я затем пытаюсь создать шейдерную программу с помощью пары «pass-thru» vertex/fragment shader и , тогда как при связывании программы не возвращаются никакие ошибки, проверка не выполняется, говоря: «Текущий фреймбуфер кадров недействителен».

Код, ссылки и проверяет программу шейдера (после завязывания шейдеры) выглядит так, на всякий случай:

- (BOOL)linkAndValidateProgram 
{ 
    GLint status; 
    glLinkProgram(_shaderProgram); 

#ifdef DEBUG 
    GLint infoLogLength; 
    GLchar *infoLog = NULL; 
    glGetProgramiv(_shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength); 
    if (infoLogLength > 0) { 
     infoLog = (GLchar *)malloc(infoLogLength); 
     glGetProgramInfoLog(_shaderProgram, infoLogLength, &infoLogLength, infoLog); 
     NSLog(@"Program link log:\n%s", infoLog); 
     free(infoLog); 
    } 
#endif 

    glGetProgramiv(_shaderProgram, GL_LINK_STATUS, &status); 
    if (!status) { 
     return NO; 
    } 

    glValidateProgram(_shaderProgram); 

#ifdef DEBUG 
    glGetProgramiv(_shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength); 
    if (infoLogLength > 0) { 
     infoLog = (GLchar *)malloc(infoLogLength); 
     glGetProgramInfoLog(_shaderProgram, infoLogLength, &infoLogLength, infoLog); 
     NSLog(@"Program validation log:\n%s", infoLog); 
     free(infoLog); 
    } 
#endif 

    glGetProgramiv(_shaderProgram, GL_VALIDATE_STATUS, &status); 
    if (!status) { 
     return NO; 
    } 

    glUseProgram(_shaderProgram); 
    return YES; 
} 

Я интересно, если там могут быть некоторые дополнительные настройки в какой-то момент в течение жизненный цикл CAEAGLLayer, о котором я мог бы не знать и мог бы пропустить, пытаясь установить GL в init?

ответ

1

Проблема заключалась в том, что в этой точке у слоя нет измерений. Что, в свою очередь, делает это, когда попытка установить буферное хранилище для визуализации на слой подразумевает буфер 0.

ОБНОВЛЕНИЕ: Мое настоящее лучшее мышление заключается в том, что вместо того, чтобы накладывать размер на init (который отлично работал для цели тестирования, но является добрым хаккой), я должен просто установить буферную память всякий раз, когда слой изменяет размеры. Поэтому я переоцениваю -setBounds: так:

- (void)setBounds:(CGRect)bounds 
{ 
    [super setBounds:bounds]; 
    [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:self]; 
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &someVariableToHoldWidthIfYouNeedIt); 
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &someVariableToHoldHeightIfYouNeedIt); 
} 
+0

Спасибо за сообщение, я просто боролся с той же проблемой! – daivuk

+0

На самом деле, если вы хотите сделать это правильно (или, по крайней мере, это мое текущее лучшее мышление), переопределите -setBounds: так, чтобы каждый раз, когда слой менял размер, вы повторно назначали его как буферное хранилище, и поэтому фреймбуфер будет оставаться в синхронизации со слоем. – SaldaVonSchwartz

0

Насколько я знаю, вы должны перезаписать метод layerClass в представлении, как этот

+ (Class)layerClass 
    { 
     return [MYCEAGLLayer class]; 
    } 

Также вы должны установить drawableProperties на MYCEAGLLayer.

Смежные вопросы