【发布时间】:2014-11-10 13:40:16
【问题描述】:
我有一个 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;
}
【问题讨论】:
-
您需要在调用 [SCNRenderer render] 之前设置 glViewport(参见 SCNRenderer.h,它的工作原理与 CARenderer 类似)。 pointOfView 也应该共享(不克隆,否则克隆的节点没有父节点,因此可能是不同的世界变换)。上一篇:你考虑过[SCNView 快照]方法吗?
-
我对 SceneKit 了解不多,但我认为您需要在调用渲染之前将上下文设为当前上下文。
标签: objective-c cocoa scenekit