CARenderer никогда не производит вывод - PullRequest
5 голосов
/ 07 августа 2010

Я застрял в течение нескольких часов, пытаясь представить дерево слоев Core Animation в контексте OpenGL с помощью CARenderer. Контекст OpenGL в настоящее время предоставляется подклассом NSOpenGLView, настроенным в Интерфейсном Разработчике, с настройками по умолчанию.

Вот как я настроил CALayers в моем примере:

l1 = [[CALayer layer] retain];        // l1 is an instance variable
l1.bounds = CGRectMake(0, 0, 100, 100);
l1.backgroundColor = CGColorCreateGenericRGB(1, 1, 0, 1);
CALayer* l2 = [CALayer layer];
l2.bounds = CGRectMake(0, 0, 20, 20);
l2.backgroundColor = CGColorCreateGenericRGB(1, 0, 0, 1);
l2.position = CGPointMake(50, 50);
[l1 addSublayer:l2];

Если я добавлю их в обычный NSView, они будут отображаться просто отлично.

Вот код для рисования из моего подкласса NSOpenGLView:

- (void) drawRect:(NSRect)dirtyRect
{
    NSRect frame = [self frame];

    // set up context according to CARenderer.h instructions
    glViewport(0, 0, frame.size.width, frame.size.height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, frame.size.width, 0, frame.size.height, -1, 1);

    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);

    if (l1)
    {
        CARenderer* renderer = [CARenderer rendererWithCGLContext:[[self openGLContext] CGLContextObj] options:nil];
        renderer.layer = l1;
        renderer.bounds = NSRectToCGRect(frame);
        [renderer beginFrameAtTime:0.0 timeStamp:NULL];
        [renderer addUpdateRect:renderer.bounds];
        [renderer render];
        [renderer endFrame];
    }

    glFlush();
}

Я проверил, что представление было перерисовано после того, как слои были созданы, и само представление, кажется, работает хорошо - команды OpenGL, которые я выпускаю, показывают правильно. CARenderer действительно оживает (на самом деле, если l1 уже подключен к другому контексту во время выполнения этого кода, он будет послушно жаловаться). Там просто нет видимого вывода, когда-либо.

Другие вещи, которые я пробовал: оборачивать код CARenderer в транзакцию CAT, переключать параметры настройки NSOpenGLView в Interface Builder, переводить весь процесс в созданный вручную контекст OpenGL вне экрана и сохранять его в файл изображения ... все к тому же эффекту: родные команды OpenGL показывают нормально, CARenderer ничего не показывает.

Я подозреваю, что что-то не так с тем, как настроен мой контекст OpenGL, или что я могу даже каким-то образом рендерить за пределами моего окна просмотра ... возможно, некоторые действительно глупые мелкие детали. К сожалению, и документация, и пример кода для CARenderer в Интернете несколько скудны, и, хотя у меня достаточно опыта работы с Core Animation, мои знания OpenGL явно ограничены.

Так что сейчас я серьезно озадачен и полностью вне идей, поэтому любые указатели очень ценятся!

Приветствия

1 Ответ

5 голосов
/ 07 августа 2010

Ого.Так что на случай, если кому-то будет интересно, я тем временем получаю это «в основном работающее».Вот соответствующий код:

- (void) drawRect:(NSRect)dirtyRect
{
    NSRect viewBounds = [self bounds];

    // set up context according to CARenderer.h instructions
    glViewport(0, 0, viewBounds.size.width, viewBounds.size.height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, viewBounds.size.width, 0, viewBounds.size.height, -1, 1);

    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);

    [renderer beginFrameAtTime:0.0 timeStamp:NULL];
    [renderer addUpdateRect:renderer.bounds];
    [renderer render];
    [renderer endFrame];

    glFlush();
}

- (void) prepareOpenGL
{
    renderer = [[CARenderer rendererWithCGLContext:[[self openGLContext] CGLContextObj] options:nil] retain];

    [CATransaction begin];
    CALayer* l = [CALayer layer];
    l.bounds = CGRectMake(0, 0, 100, 100);
    l.backgroundColor = CGColorCreateGenericRGB(1, 1, 0, 1);

    renderer.layer = l;
    renderer.bounds = l.bounds;
    [CATransaction commit];
}

Обратите внимание на блок CATransaction вокруг кода создания слоя / средства визуализации.Без этого слой либо вообще не будет отображаться (как это было в моей первоначальной проблеме), либо будет отображаться только после небольшой задержки, т. Е. Когда представление перерисовывается через некоторое время.Что касается , почему это необходимо, я все еще не уверен, и я был бы более чем счастлив, если бы кто-то мог просветить меня в этом вопросе.но я решил оставить его здесь на время, учитывая отсутствие примера кода для CARenderer.

РЕДАКТИРОВАТЬ: как я позже выяснил, одна довольно неочевидная ошибка с решением выше является0.0 передается в вызов метода beginFrameAtTime;вместо этого это должно быть значение из CACurrentMediaTime.Это устранит необходимость в блоках CATransaction, а также исправит несколько других ошибок на этом пути.Так же, как хедз-ап для любого, кто может наткнуться на этот ответ.

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