CATextLayer not rendering properly on SCNNode
I have a hierarchy of CALayers that I am setting as the diffuse property of my SCNNode's material. I taking snapshots of the current state of the scene (that only has the one node) to save as a PNG to a file using this code:
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
Often this works, rendering the node as expected, but about 25-50% of the time, any CATextLayer I have as a sublayer of the layer returned in self.createLayer()
does not render the text. All other layers seem to be rendered just fine every time.
For example, an image that is supposed to look as such:
Ends up missing the text "N":
The layer itself is being rendered, as I can confirm by changing the background color of the text layer:
This seems to only be an issue that occurs immediately after creating the layers. If I dispatch the rendering code asynchronously, even without adding any delay, everything renders as expected:
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)
}
The above workaround seems hacky and I don't trust it to be reliable. Also, I'd rather not force my callsites to call the method in an asynchronous manner.
Is there a property or method in SceneKit or CoreAnimation that I'm missing that I can use to make sure the layer is completely rendered before trying to render it to an image?
ios core-animation scenekit catextlayer scnscene
add a comment |
I have a hierarchy of CALayers that I am setting as the diffuse property of my SCNNode's material. I taking snapshots of the current state of the scene (that only has the one node) to save as a PNG to a file using this code:
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
Often this works, rendering the node as expected, but about 25-50% of the time, any CATextLayer I have as a sublayer of the layer returned in self.createLayer()
does not render the text. All other layers seem to be rendered just fine every time.
For example, an image that is supposed to look as such:
Ends up missing the text "N":
The layer itself is being rendered, as I can confirm by changing the background color of the text layer:
This seems to only be an issue that occurs immediately after creating the layers. If I dispatch the rendering code asynchronously, even without adding any delay, everything renders as expected:
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)
}
The above workaround seems hacky and I don't trust it to be reliable. Also, I'd rather not force my callsites to call the method in an asynchronous manner.
Is there a property or method in SceneKit or CoreAnimation that I'm missing that I can use to make sure the layer is completely rendered before trying to render it to an image?
ios core-animation scenekit catextlayer scnscene
add a comment |
I have a hierarchy of CALayers that I am setting as the diffuse property of my SCNNode's material. I taking snapshots of the current state of the scene (that only has the one node) to save as a PNG to a file using this code:
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
Often this works, rendering the node as expected, but about 25-50% of the time, any CATextLayer I have as a sublayer of the layer returned in self.createLayer()
does not render the text. All other layers seem to be rendered just fine every time.
For example, an image that is supposed to look as such:
Ends up missing the text "N":
The layer itself is being rendered, as I can confirm by changing the background color of the text layer:
This seems to only be an issue that occurs immediately after creating the layers. If I dispatch the rendering code asynchronously, even without adding any delay, everything renders as expected:
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)
}
The above workaround seems hacky and I don't trust it to be reliable. Also, I'd rather not force my callsites to call the method in an asynchronous manner.
Is there a property or method in SceneKit or CoreAnimation that I'm missing that I can use to make sure the layer is completely rendered before trying to render it to an image?
ios core-animation scenekit catextlayer scnscene
I have a hierarchy of CALayers that I am setting as the diffuse property of my SCNNode's material. I taking snapshots of the current state of the scene (that only has the one node) to save as a PNG to a file using this code:
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
Often this works, rendering the node as expected, but about 25-50% of the time, any CATextLayer I have as a sublayer of the layer returned in self.createLayer()
does not render the text. All other layers seem to be rendered just fine every time.
For example, an image that is supposed to look as such:
Ends up missing the text "N":
The layer itself is being rendered, as I can confirm by changing the background color of the text layer:
This seems to only be an issue that occurs immediately after creating the layers. If I dispatch the rendering code asynchronously, even without adding any delay, everything renders as expected:
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)
}
The above workaround seems hacky and I don't trust it to be reliable. Also, I'd rather not force my callsites to call the method in an asynchronous manner.
Is there a property or method in SceneKit or CoreAnimation that I'm missing that I can use to make sure the layer is completely rendered before trying to render it to an image?
ios core-animation scenekit catextlayer scnscene
ios core-animation scenekit catextlayer scnscene
asked Nov 21 '18 at 1:08
JsdodgersJsdodgers
4,96621635
4,96621635
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
I can understand it is not reliable using DispatchMain as you are not sure the node has been rendered well. So there is a function tell you if the rendering has complete or not. Call snapshot inside that completion handle.
scene.rootNode.addChildNode(node)
node.geometry?.firstMaterial?.diffuse.contents = self.createLayer() // CALayer
let renderer = SCNRenderer(
device: MTLCreateSystemDefaultDevice(),
options: nil)
----renderer.prepare([node]) { (success) in // this line is useful
if (success){
let renderTime = CACurrentMediaTime() + 1
let size = CGSize(width: 600, height: 600)
let image = renderer.snapshot(
atTime: renderTime,
with: size,
antialiasingMode: .multisampling4X)
complete(image)
}
}
You may add other nodes to the array if you think it takes too long to load.
Excellent! This call isn't synchronous as I was hoping, but this is almost exactly what I was looking for! If there is a synchronous version, that would be even better, but this feels much safer than just dispatching and hoping everything works.
– Jsdodgers
Nov 24 '18 at 4:57
add a comment |
I've had success making PNG snapshots by just invoking SCNTransaction.flush() before the invoking sceneView.snapshot().
This just isn't working for me, unfortunately.
– Jsdodgers
Dec 6 '18 at 3:44
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403913%2fcatextlayer-not-rendering-properly-on-scnnode%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I can understand it is not reliable using DispatchMain as you are not sure the node has been rendered well. So there is a function tell you if the rendering has complete or not. Call snapshot inside that completion handle.
scene.rootNode.addChildNode(node)
node.geometry?.firstMaterial?.diffuse.contents = self.createLayer() // CALayer
let renderer = SCNRenderer(
device: MTLCreateSystemDefaultDevice(),
options: nil)
----renderer.prepare([node]) { (success) in // this line is useful
if (success){
let renderTime = CACurrentMediaTime() + 1
let size = CGSize(width: 600, height: 600)
let image = renderer.snapshot(
atTime: renderTime,
with: size,
antialiasingMode: .multisampling4X)
complete(image)
}
}
You may add other nodes to the array if you think it takes too long to load.
Excellent! This call isn't synchronous as I was hoping, but this is almost exactly what I was looking for! If there is a synchronous version, that would be even better, but this feels much safer than just dispatching and hoping everything works.
– Jsdodgers
Nov 24 '18 at 4:57
add a comment |
I can understand it is not reliable using DispatchMain as you are not sure the node has been rendered well. So there is a function tell you if the rendering has complete or not. Call snapshot inside that completion handle.
scene.rootNode.addChildNode(node)
node.geometry?.firstMaterial?.diffuse.contents = self.createLayer() // CALayer
let renderer = SCNRenderer(
device: MTLCreateSystemDefaultDevice(),
options: nil)
----renderer.prepare([node]) { (success) in // this line is useful
if (success){
let renderTime = CACurrentMediaTime() + 1
let size = CGSize(width: 600, height: 600)
let image = renderer.snapshot(
atTime: renderTime,
with: size,
antialiasingMode: .multisampling4X)
complete(image)
}
}
You may add other nodes to the array if you think it takes too long to load.
Excellent! This call isn't synchronous as I was hoping, but this is almost exactly what I was looking for! If there is a synchronous version, that would be even better, but this feels much safer than just dispatching and hoping everything works.
– Jsdodgers
Nov 24 '18 at 4:57
add a comment |
I can understand it is not reliable using DispatchMain as you are not sure the node has been rendered well. So there is a function tell you if the rendering has complete or not. Call snapshot inside that completion handle.
scene.rootNode.addChildNode(node)
node.geometry?.firstMaterial?.diffuse.contents = self.createLayer() // CALayer
let renderer = SCNRenderer(
device: MTLCreateSystemDefaultDevice(),
options: nil)
----renderer.prepare([node]) { (success) in // this line is useful
if (success){
let renderTime = CACurrentMediaTime() + 1
let size = CGSize(width: 600, height: 600)
let image = renderer.snapshot(
atTime: renderTime,
with: size,
antialiasingMode: .multisampling4X)
complete(image)
}
}
You may add other nodes to the array if you think it takes too long to load.
I can understand it is not reliable using DispatchMain as you are not sure the node has been rendered well. So there is a function tell you if the rendering has complete or not. Call snapshot inside that completion handle.
scene.rootNode.addChildNode(node)
node.geometry?.firstMaterial?.diffuse.contents = self.createLayer() // CALayer
let renderer = SCNRenderer(
device: MTLCreateSystemDefaultDevice(),
options: nil)
----renderer.prepare([node]) { (success) in // this line is useful
if (success){
let renderTime = CACurrentMediaTime() + 1
let size = CGSize(width: 600, height: 600)
let image = renderer.snapshot(
atTime: renderTime,
with: size,
antialiasingMode: .multisampling4X)
complete(image)
}
}
You may add other nodes to the array if you think it takes too long to load.
answered Nov 21 '18 at 2:15
E.ComsE.Coms
2,5152414
2,5152414
Excellent! This call isn't synchronous as I was hoping, but this is almost exactly what I was looking for! If there is a synchronous version, that would be even better, but this feels much safer than just dispatching and hoping everything works.
– Jsdodgers
Nov 24 '18 at 4:57
add a comment |
Excellent! This call isn't synchronous as I was hoping, but this is almost exactly what I was looking for! If there is a synchronous version, that would be even better, but this feels much safer than just dispatching and hoping everything works.
– Jsdodgers
Nov 24 '18 at 4:57
Excellent! This call isn't synchronous as I was hoping, but this is almost exactly what I was looking for! If there is a synchronous version, that would be even better, but this feels much safer than just dispatching and hoping everything works.
– Jsdodgers
Nov 24 '18 at 4:57
Excellent! This call isn't synchronous as I was hoping, but this is almost exactly what I was looking for! If there is a synchronous version, that would be even better, but this feels much safer than just dispatching and hoping everything works.
– Jsdodgers
Nov 24 '18 at 4:57
add a comment |
I've had success making PNG snapshots by just invoking SCNTransaction.flush() before the invoking sceneView.snapshot().
This just isn't working for me, unfortunately.
– Jsdodgers
Dec 6 '18 at 3:44
add a comment |
I've had success making PNG snapshots by just invoking SCNTransaction.flush() before the invoking sceneView.snapshot().
This just isn't working for me, unfortunately.
– Jsdodgers
Dec 6 '18 at 3:44
add a comment |
I've had success making PNG snapshots by just invoking SCNTransaction.flush() before the invoking sceneView.snapshot().
I've had success making PNG snapshots by just invoking SCNTransaction.flush() before the invoking sceneView.snapshot().
answered Dec 5 '18 at 22:36
LenKLenK
1,34811217
1,34811217
This just isn't working for me, unfortunately.
– Jsdodgers
Dec 6 '18 at 3:44
add a comment |
This just isn't working for me, unfortunately.
– Jsdodgers
Dec 6 '18 at 3:44
This just isn't working for me, unfortunately.
– Jsdodgers
Dec 6 '18 at 3:44
This just isn't working for me, unfortunately.
– Jsdodgers
Dec 6 '18 at 3:44
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403913%2fcatextlayer-not-rendering-properly-on-scnnode%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown