Для тех, кто просматривает эту ветку 7 лет спустя, я пытался использовать описанные выше методы, но они дали относительно медленные результаты. Я хотел визуализировать всю SKScene за кадром, так как я визуализировал изображения как кадры для видео. Это означало, что я не мог использовать 1-й метод, предложенный LearnCocos2D, поскольку он требовал, чтобы вид отображался на экране, а второй метод требовал очень много времени для преобразования из SKTexture
в UIImage
. Вы можете использовать новый класс SKRenderer
, представленный в iOS 11.0, для рендеринга всей сцены в UIImage, и он использует преимущества Metal, поэтому рендеринг происходит относительно быстро. Я смог отрендерить 1920x1080 SKScene
примерно за 0,013 секунды!
Вы можете использовать это расширение:
- Убедитесь, что вы
import MetalKit
- Параметр
ignoreScreenScale
указывает, должно ли выходное изображение быть точным до пикселя. Обычно, если вы будете отображать изображение обратно на экран, вы захотите, чтобы это значение было ложным. Если это значение равно false, размер выходного изображения масштабируется в соответствии с масштабом устройства таким образом, что каждая точка сцены занимает такое же количество пикселей изображения, как и на экране. Когда это верно, размер выходного изображения в пикселях равен размеру SKScene
в точках.
Ваше здоровье!
extension SKScene {
func toImage(ignoreScreenScale: Bool = false) -> UIImage? {
guard let device = MTLCreateSystemDefaultDevice(),
let commandQueue = device.makeCommandQueue(),
let commandBuffer = commandQueue.makeCommandBuffer() else { return nil }
let scale = ignoreScreenScale ? 1 : UIScreen.main.scale
let size = self.size.applying(CGAffineTransform(scaleX: scale, y: scale))
let renderer = SKRenderer(device: device)
let renderPassDescriptor = MTLRenderPassDescriptor()
var r = CGFloat.zero, g = CGFloat.zero, b = CGFloat.zero, a = CGFloat.zero
backgroundColor.getRed(&r, green: &g, blue: &b, alpha: &a)
let textureDescriptor = MTLTextureDescriptor()
textureDescriptor.usage = [.renderTarget, .shaderRead]
textureDescriptor.width = Int(size.width)
textureDescriptor.height = Int(size.height)
let texture = device.makeTexture(descriptor: textureDescriptor)
renderPassDescriptor.colorAttachments[0].loadAction = .clear
renderPassDescriptor.colorAttachments[0].texture = texture
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(
red: Double(r),
green: Double(g),
blue: Double(b),
alpha:Double(a)
)
renderer.scene = self
renderer.render(withViewport: CGRect(origin: .zero, size: size), commandBuffer: commandBuffer, renderPassDescriptor: renderPassDescriptor)
commandBuffer.commit()
let image = CIImage(mtlTexture: texture!, options: nil)!
let transformed = image.transformed(by: CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -image.extent.size.height))
return UIImage(ciImage: transformed)
}
}
person
CentrumGuy
schedule
29.12.2020