Here is what I am using:
macOS 10.12
in:
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
...
DispatchQueue.main.async {
SCNTransaction.begin()
SCNTransaction.disableActions = true
let snapshot = gView.snapshot()
let repr = self.TIFFRepresentation(image: snapshot)
do{
_ = try repr?.write(to: fileUrl as! URL, options: NSData.WritingOptions.atomicWrite)
}
catch let error as NSError {
print(error.localizedDescription)
}
SCNTransaction.commit()
}
...
func TIFFRepresentation(image: NSImage) -> Data? {
if let TIFFRepresentation = image.tiffRepresentation, let bitmap = NSBitmapImageRep(data: TIFFRepresentation) {
return bitmap.representation(using: .TIFF, properties: [:])
}
return nil
}
The resulting TIFF file is 8 bit per channel. Color Profile: sRGB IEC61966-2.1
It should be 32-bit per channel,
Color Profile: Wide Gamut RGB (Linear RGB Profile)
Also I can get bigger resolutions like 7.2Kx7.2K using Metal:
===
func setupMetal() {
if gView.renderingAPI == SCNRenderingAPI.metal {
let device = gView.device
commandQueue = device?.makeCommandQueue()
/
SCNRenderer
An SCNRenderer object renders a SceneKit scene into an arbitrary Metal workflow or OpenGL context. Use this class when you want to add content rendered by SceneKit to an app that already renders other content by using Metal or OpenGL or OpenGL ES directly. To provide content for a SceneKit renderer, assign a SCNScene object to its scene property.
*/
renderer = SCNRenderer(device: device, options: nil)
} else {
fatalError("Sorry, Metal only")
}
}
===
and then:
===
func doRender() -> NSImage{
/
let rect = CGRect(x: 0, y: 0, width: CGFloat(textureSizeX), height: CGFloat(textureSizeY))
let viewport = rect
let renderPassDescriptor = MTLRenderPassDescriptor()
let commandBuffer = commandQueue.makeCommandBuffer()
renderer.scene = scene
renderer.pointOfView = gView.pointOfView
renderer.render(atTime: 0, viewport: viewport, commandBuffer: commandBuffer, passDescriptor: renderPassDescriptor)
commandBuffer.commit()
/
let size = CGSize(width: textureSizeX, height: textureSizeY)
let img = renderer.snapshot(atTime: 0, with: size, antialiasingMode: .none)
print(img)
return img
/
}
Basically utilizing Metal's renderer.snapshot of the scene. This is giving me benefit of 2x offscreen size.
The question is how to get HDR image possibly using Image I/O framework?