将屏幕外SCNScene渲染为UIImage

Eri*_*ner 5 opengl-es ios scenekit

我怎样才能使呈现的屏幕外的 SCNSceneUIImage

我知道这SCNView提供了一种-snapshot方法,但不幸的是,它不适用于屏幕外视图.之前有人问过一个类似的问题,其中一个答案建议使用OpenGL读取位图数据glReadPixels,但这种方法对我的屏幕外场景不起作用.

我试图渲染成的情况下GLKView使用SCNRenderer没有成功.

dre*_*ter 5

使用SCNRenderer的Swift 4:

您可以使用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]
Run Code Online (Sandbox Code Playgroud)

第2步-设置SCNRenderer-渲染器在模拟器上为nil:

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

第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)
Run Code Online (Sandbox Code Playgroud)

如果正在运行动画,则需要增加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
    }   
})
Run Code Online (Sandbox Code Playgroud)

不过,使用CADisplayLink可能是一种更好的计时解决方案。

这是一个非常快速和肮脏的实现示例