ios – 将屏幕外SCNScene呈现为UIImage

如何渲染屏幕外SCNScene到UI Image

我知道SCNView提供了一个-snapshot方法,但不幸的是,这对于屏幕外视图不起作用.之前已经问过一个similar question,其中一个答案建议使用glreadPixels从OpenGL读取位图数据,但这种方法对我的离屏场景不起作用.

我尝试使用SCNRenderer渲染到GLKView的上下文中但没有成功.

解决方法

Swift 4与SCNRenderer:

您可以使用SCNRenderer的快照方法将屏幕外的SCNScene很容易地渲染为UIImage.

这里有一些警告,这使用金属.我不知道设备/ iOS版本的截止位置,但你需要一个更新的设备.您也将无法在模拟器上运行它.

第1步 – 像往常一样设置场景:

// Set up your scene which won't be displayed
let hiddenScene = SCNScene()
[insert code to set up your nodes,cameras,and lights here]

第2步 – 设置SCNRenderer – 渲染器将在模拟器上为零:

// Set up the renderer -- this returns nil on simulator
let renderer = SCNRenderer(device: MTLCreateSystemDefaultDevice(),options: nil)
renderer!.scene = hiddenScene

第3步 – 渲染场景到UIImage:

// You can use zero for renderTime unless you are using animations,// in which case,renderTime should be the current scene time.
let renderTime = TimeInterval(0)

// Output size
let size = CGSize(width:300,height: 150)

// Render the image
let image = renderer!.snapshot(atTime: renderTime,with: size,antialiasingMode: SCNAntialiasingMode.multisampling4X)

如果您正在运行动画,则需要增加renderTime或将其设置为要渲染的时间索引.例如,如果要将帧渲染到场景中4秒,则将其设置为4.这仅影响动画 – 它不会回溯到时间并显示场景的历史视图.

例如,如果您运行的是使用SCNNode.runAction运行动画,您可能希望每隔60秒(0.16667秒)继续递增renderTime,这样无论何时您决定渲染,您都有一个更新的renderTime:

var timer : Timer
var renderTime = TimeInterval(0)

timer = Timer.scheduledTimer(withTimeInterval: 0.016667,repeats: true,block: { (t) in 
        self?.renderTime += 0.016667
    }   
})

然而,使用CAdisplayLink可能是更好的解决方案.

这是一个非常快速和肮脏的implementation example.

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...