2010-08-07 110 views
4

我一直坚持了几个小时,试图使用CARenderer将Core Animation图层树渲染到OpenGL上下文中。 OpenGL上下文当前由Interface Builder中设置的NSOpenGLView子类提供,并且具有默认设置。CARenderer从不产生输出

以下是我在我的例子建立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已经连接到另一个上下文,它将会尽职尽责)。没有可见的输出。

我试过的其他东西:在CATransaction中包装CARenderer代码,摆弄界面生成器中的NSOpenGLView设置选项,将整个事件渲染为手动创建的OpenGL上下文,并将其保存到图像文件中...所有相同的效果:原生OpenGL命令显示正常,CARenderer不显示任何内容。

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

所以现在,我很难过,完全没有想法,所以任何指针都非常感谢!

干杯

回答

4

哦哇。所以如果有人有兴趣,我同时得到了这个“大多数工作”。下面是相关的代码:

- (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块的需求,同时纠正一些其他错误。就像任何人可能偶然发现这个答案一样。

+0

感谢您发布此信息。在prepareOpenGL方法之后,似乎有助于让CALayer拥有一个非零表示层,而不会实际显示(我试图使用CAKeyFrameanimation来冒险计算沿着CGPath的点) – 2015-08-05 04:26:09