2010-08-07 7 views
4

저는 CARENDerer를 사용하여 OpenGL 컨텍스트에 Core Animation 레이어 트리를 렌더링하려고 몇 시간 동안 노력했습니다. 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 컨텍스트가 설정되는 방식에 문제가 있거나 내 뷰포트 외부에서 렌더링 중일 수 있습니다. 아마 아주 어리석은 세부 사항 일 수 있습니다. 불행하게도, 웹상의 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.0beginFrameAtTime 메서드 호출에 전달된다는 것입니다. 대신 CACurrentMediaTime의 값이어야합니다. 이렇게하면 CATransaction 블럭의 필요성이 제거되고, 다른 몇 가지 버그가 수정됩니다. 이 대답에 비틀 거릴 수있는 사람을위한 머리 위로.

+0

게시 해 주셔서 감사합니다. prepareOpenGL 메서드 다음에 CALayer가 실제로 표시되지 않고 무제한 프레젠테이션 레이어를 갖도록하는 데 도움이되는 것처럼 보입니다 (CGPath를 따라 점을 hackishly 계산하기 위해 CAKeyFrameanimation과 함께 사용하려고하는 것) –

관련 문제