OpenGL рисует черный экран после возвращения из другого просмотра - PullRequest
1 голос
/ 24 ноября 2011

Я целый день пытаюсь найти ответ на этот вопрос.

Проблема:

У меня есть представление OpenGL, я создаю его в IB, инициализирую все буферы и устанавливаю цикл рендеринга в displayLink.,Отлично работает, все хорошо.Но затем я пытаюсь создать еще один контроллер с этим представлением openGL в корневом контроллере и представить его с помощью:

[self presentModalViewController:newPage animated:YES];

Он выглядит хорошо, как я и хотел.Он также прекрасно работает без проблем.Он также инициирован из IB.Но как только я использую

[self dismissModalViewControllerAnimated:YES];

, анимация действительно происходит, вид падает, но когда он падает, он оставляет за собой «мусор» (части изображения на черном фоне) и предыдущий openGL.вид остается черным.Я попытался удалить и восстановить displayLink, но безуспешно.Я снова попытался уничтожить / создать фреймбуферы, и мне удалось однажды заставить его работать, но это заняло много времени, и, поскольку я создаю его из представления, я не знаю, является ли это правильным подходом.Просто, чтобы сделать это проще, вот некоторые части моего кода:

- (BOOL)createFrameBuffer
{
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);



    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if (YES) 
    {
        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
    }

    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) 
    {
        NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
        return NO;
    }

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

    return YES;
    }

    }

    - (void)destroyFrameBuffer
    glDeleteFramebuffersOES(1, &viewFramebuffer);
    viewFramebuffer = 0;
    glDeleteRenderbuffersOES(1, &viewRenderbuffer);
    viewRenderbuffer = 0;

    if(depthRenderbuffer) 
    {
        glDeleteRenderbuffersOES(1, &depthRenderbuffer);
        depthRenderbuffer = 0;
    }

    - (void)layoutSubviews


    [EAGLContext setCurrentContext:context];

    [self draw:nil];

Внутренний init - это мой основной метод init.

 - (id)internalInit
{    

        CAEAGLLayer* eaglLayer = (CAEAGLLayer*) super.layer;
        eaglLayer.opaque = YES;


        context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];

        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            return nil;
        }

    [self createFrameBuffer];

    [self setupView:self];

        [self drawView: nil];

        CADisplayLink* displayLink;
        displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(draw:)];
        [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        [displayLink setFrameInterval:1];

    return self;
}

Метод setupView: в основном создает область просмотра, устанавливает усеченную область, все необходимые переменные и состояния.Ничего особенного.

Заранее благодарим за все и каждую минуту, потраченную на это.

Ответы [ 3 ]

2 голосов
/ 24 ноября 2011

У меня был тот же самый эффект, случившийся со мной после некоторых оптимизаций, которые я выполнил, которые не работали в каждом случае, для меня проблема возникает сама по себе после закрытия просмотров Game Center или после завершения воспроизведения фильма MPPlayer.

Из шаблона Apple OpenGL, когда вы получаете LayoutSubviews (который вы получите после исчезновения верхнего окна), вы должны уничтожить и воссоздать ваши буферы кадров

- (void)layoutSubviews
{
    // The framebuffer will be re-created at the beginning of the next setFramebuffer method call.
    [self deleteFramebuffer];
}

После этого функция self ((EAGLView *) self.view setFramebuffer];должен вызываться для повторного создания буфера кадров, в оригинальном шаблоне этот вызов вызывается в каждом кадре, но его нужно вызывать только один раз после его уничтожения.(Я поместил туда первую вызываемую переменную, чтобы сделать это)

Я просто помещу здесь подпрограммы:

- (void)setFramebuffer
{
    if (context)
    {
        [EAGLContext setCurrentContext:context];

        if (!defaultFramebuffer)
            [self createFramebuffer];

        glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
        first = FALSE;

    }
}

- (void)createFramebuffer
{
if (context && !defaultFramebuffer)
{
    NSLog(@"Create Frame Buffer");

    [EAGLContext setCurrentContext:context];

    // Create default framebuffer object.
    glGenFramebuffersOES(1, &defaultFramebuffer);
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);

    // Create color render buffer and allocate backing store.
    glGenRenderbuffersOES(1, &colorRenderbuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);

    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer *)self.layer];
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &framebufferWidth);
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &framebufferHeight);

    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);

    // Need a depth buffer
    glGenRenderbuffersOES(1, &depthRenderbuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES,  framebufferWidth, framebufferHeight);
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);

    if (glCheckFramebufferStatus(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
        NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER_OES));
}

}

Так что этот setFramebuffer вызывается для функции, вызываемой из displaylink.И я сначала сбрасываю переменную на FALSE в моих уведомлениях о дидфинише из Game Center MPPlayer.

Если вы не можете найти свою проблему, попробуйте отладить то, что вызывается на уровне объекта EAGL, NSLog каждую функцию там и посмотретьесли что-то странное происходит с вашими буферами или привязками.

0 голосов
/ 04 ноября 2014

У меня была такая же проблема из-за glDepthMask (FALSE) для фонового рисования рамки, чтобы сохранить его в изображение, которое затем не было возвращено для обычного рендеринга. Надеюсь, это поможет.

Спасибо.

0 голосов
/ 12 июля 2013

Другое возможное объяснение проблемы «EAGLView - черный при появлении или повторном появлении» - это то, что ваш метод [EAGLView renderbufferStorage:fromDrawable:] не был вызван в главном потоке. Вызов этого метода из фона приведет к ситуации, которая обычно работает, но иногда становится черной. Вероятно, не причина именно указанной проблемы, но достаточно загадочная, чтобы в будущем это могло быть полезно для отчаявшихся гуглеров, наткнувшихся на эту страницу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...