2010-08-07 109 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