У меня есть иерархия CALayers, которую я устанавливаю в качестве свойства diffuse материала моего SCNNode.Я делаю снимки текущего состояния сцены (в котором есть только один узел), чтобы сохранить его в формате PNG в файл, используя следующий код:
scene.rootNode.addChildNode(node)
node.geometry?.firstMaterial?.diffuse.contents = self.createLayer() // CALayer
// Set transform of node.
let renderTime = CACurrentMediaTime() + 1
let size = CGSize(width: 600, height: 600)
let renderer = SCNRenderer(
device: MTLCreateSystemDefaultDevice(),
options: nil)
let image = self.renderer.snapshot(
atTime: renderTime,
with: size,
antialiasingMode: .multisampling4X)
return image
Часто это работает, что делает узел ожидаемым, ноПримерно в 25-50% случаев любой CATextLayer, который у меня есть в качестве подслоя слоя, возвращенного в self.createLayer()
, не отображает текст.Все остальные слои, кажется, каждый раз воспроизводятся очень хорошо.
Например, изображение, которое должно выглядеть так:
В конце пропускается текст "N":
Сам слой визуализируется, что я могу подтвердить, изменив цвет фона текстового слоя:
Эта проблема возникает только после создания слоев.Если я отправляю код рендеринга асинхронно, даже без добавления какой-либо задержки, все рендеринг выполняется так, как ожидалось:
scene.rootNode.addChildNode(node)
node.geometry?.firstMaterial?.diffuse.contents = self.createLayer() // CALayer
// Set transform of node.
let renderTime = CACurrentMediaTime() + 1
let size = CGSize(width: 600, height: 600)
DispatchQueue.main.async {
let image = self.renderer.snapshot(
atTime: renderTime,
with: size,
antialiasingMode: .multisampling4X)
completion(image)
}
Обходное решение кажется хакерским, и я не верю в его надежность.Кроме того, я бы предпочел не заставлять свои вызывающие сайты вызывать метод асинхронно.
Есть ли свойство или метод в SceneKit или CoreAnimation, которые мне не хватает, которые я могу использовать, чтобы убедиться, что слойполностью отрисован перед попыткой рендерить его на изображение?