Рендеринг SCNView в закадровый буфер для генерации изображения

У меня есть SCNView, он отображает мою сцену. Тем не менее, я хочу получить пару скриншотов в разные моменты времени при сохранении. Мое лучшее предположение — создать SCNRenderer и визуализировать сцену, указав разное время. Я пытался, но мое изображение просто возвращается пустым, вот мой код, есть идеи?:

-(void)test 
{
//First create a new OpenGL context to render to. 
NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = {
    NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
    NSOpenGLPFADoubleBuffer,
    NSOpenGLPFANoRecovery,
    NSOpenGLPFAAccelerated,
    NSOpenGLPFADepthSize, 24,
    0
};

NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes];
if (pixelFormat == nil)
{
    NSLog(@"Error: No appropriate pixel format found");
}

NSOpenGLContext *context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];

//set the renderer to render to that context
SCNRenderer *lRenderer = [SCNRenderer rendererWithContext:context.CGLContextObj options: nil];
lRenderer.scene = myscnview.scene;
lRenderer.pointOfView = [myscnview.pointOfView clone];

//render the scene
[lRenderer render];

//I think I should now have the scene rendered into the context now?
//so i could just do:
NSImage *image = [self imageFromSceneKitView:controller.docView fromWindow:window ctx:context];

}

- (NSImage*)imageFromSceneKitView:(SCNView*)sceneKitView fromWindow:(NSWindow *)window ctx:    (NSOpenGLContext *)ctx
{
NSInteger width = sceneKitView.bounds.size.width * window.backingScaleFactor;
NSInteger height = sceneKitView.bounds.size.height * window.backingScaleFactor;
width = width - (width % 32);
height = height - (height % 32);
NSBitmapImageRep* imageRep=[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                                                                   pixelsWide:width
                                                                   pixelsHigh:height
                                                                bitsPerSample:8
                                                              samplesPerPixel:4
                                                                     hasAlpha:YES
                                                                     isPlanar:NO
                                                               colorSpaceName:NSCalibratedRGBColorSpace
                                                                  bytesPerRow:width*4
                                                                 bitsPerPixel:4*8];

CGLLockContext((CGLContextObj)[ctx CGLContextObj]);
[ctx makeCurrentContext];
glReadPixels(0, 0, (int)width, (int)height, GL_RGBA, GL_UNSIGNED_BYTE, [imageRep bitmapData]);
[NSOpenGLContext clearCurrentContext];
CGLUnlockContext((CGLContextObj)[ctx CGLContextObj]);
NSImage* outputImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
[outputImage addRepresentation:imageRep];

NSImage* flippedImage = [NSImage imageWithSize:NSMakeSize(width, height) flipped:YES drawingHandler:^BOOL(NSRect dstRect) {
    [imageRep drawInRect:dstRect];
    return YES;
}];
return flippedImage;

}


person Chris    schedule 16.09.2014    source источник
comment
вам нужно настроить glViewport перед вызовом [рендеринга SCNRenderer] (см. SCNRenderer.h, он работает так же, как CARenderer). Кроме того, pointOfView должен быть общим (не клонированным, иначе у клонированного узла нет родителя и, следовательно, возможно другое преобразование мира). Последнее: рассматривали ли вы метод [моментальный снимок SCNView]?   -  person Toyos    schedule 16.09.2014
comment
Я мало что знаю о SceneKit, но я думаю, что вам нужно сделать контекст текущим контекстом ПЕРЕД вызовом рендеринга.   -  person guitarflow    schedule 17.05.2015


Ответы (1)


Это довольно старый вопрос, но позвольте мне упомянуть относительно новый SCNView.snapshot(). и SCNRenderer.snapshot(atTime:with:antialiasingMode:) API.

person mnuages    schedule 09.12.2016