CARenderer从不产生输出

ig2*_*g2r 5 opengl macos cocoa core-animation

试图使用CARenderer将Core Animation图层树渲染到OpenGL上下文中,我已经呆了几个小时。OpenGL上下文当前由Interface Builder中设置的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];
Run Code Online (Sandbox Code Playgroud)

如果我将它们添加到常规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();
}
Run Code Online (Sandbox Code Playgroud)

我验证了在创建图层后是否重新绘制了视图,并且视图本身似乎可以正常工作-我发出的OpenGL命令可以正确显示。CARenderer确实可以运行(实际上,如果在运行此代码时l1已经附加到另一个上下文,它将忠实地抱怨)。从来没有可见的输出。

我尝试过的其他方法:将CARenderer代码包装在CATransaction中,摆弄Interface Builder中的NSOpenGLView设置选项,将整个事务渲染到屏幕外的手动创建的OpenGL上下文中,然后将其保存到图像文件中……全部相同效果:原生OpenGL命令显示正常,CARenderer不显示任何内容。

我怀疑OpenGL上下文的设置方式存在问题,或者甚至可能以某种方式在我的视口之外进行渲染……可能是一些非常愚蠢的小细节。不幸的是,Web上CARenderer的文档和示例代码都很少,尽管我对Core Animation相当有经验,但是我的OpenGL知识绝对有限。

所以,现在,我很沮丧,完全没有想法,因此非常感谢任何指点!

干杯

ig2*_*g2r 5

哇哦 因此,如果有人感兴趣,我会在此期间同时进行“大部分工作”。以下是相关代码:

- (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];
}
Run Code Online (Sandbox Code Playgroud)

注意CATransaction图层/渲染器创建代码周围的块。没有这个,图层将根本不显示(这是我最初的问题),或者仅在稍有延迟之后才渲染,即,经过一段时间后重新绘制视图时。至于为什么必须这样做,我仍不确定,如果有人能对此有所启发,我会感到非常高兴。

显然,此解决方案可能仍然存在某种错误,但是考虑到缺少示例代码,我决定暂时将其留在此处CARenderer

编辑:正如我后来发现的那样,上述解决方案的一个相当非显而易见的错误是将0.0其传递给beginFrameAtTime方法调用;相反,这应该是中的值CACurrentMediaTime。这将消除对CATransaction块的需求,并在此过程中纠正其他一些错误。就像对任何可能偶然发现此答案的人的提醒。