How can i add a 2dView having text in ARkit scene iOS.How can i add that view in top of a node that won't rotate when we rotate the node.
2 Answers
You can add a SCNPlane
and use a SCNLookAtConstraint
to so that the plane always looks at the camera.
You can create a custom material and set it's material properties to:
A color (UIColor or CGColor), specifying a constant color across the material’s surface A number (
An image (UIImage or CGImage), specifying a texture to be mapped across the material’s surface
- A Core Animation layer (CALayer)
- A texture (SKTexture, MDLTexture, MTLTexture, or GLKTextureInfo)
- A SpriteKit scene (SKScene)
You can also display animated contents using CoreAnimation or SpriteKit but
SceneKit cannot use a layer that is already being displayed elsewhere (for example, the backing layer of a UIView object)
Here is an example using SpriteKit:
- Create your SpriteKit Scene:
e.g.:
let skScene = SKScene(size: CGSize(width: 200, height: 200))
skScene.backgroundColor = UIColor.clear
let rectangle = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 200, height: 200), cornerRadius: 10)
rectangle.fillColor = #colorLiteral(red: 0.807843148708344, green: 0.0274509806185961, blue: 0.333333343267441, alpha: 1.0)
rectangle.strokeColor = #colorLiteral(red: 0.439215689897537, green: 0.0117647061124444, blue: 0.192156866192818, alpha: 1.0)
rectangle.lineWidth = 5
rectangle.alpha = 0.4
let labelNode = SKLabelNode(text: "Hello World")
labelNode.fontSize = 20
labelNode.fontName = "San Fransisco"
labelNode.position = CGPoint(x:100,y:100)
skScene.addChild(rectangle)
skScene.addChild(labelNode)
- Create your plane and set the scene as your material property
e.g.
let plane = SCNPlane(width: 20, height: 20)
let material = SCNMaterial()
material.isDoubleSided = true
material.diffuse.contents = skScene
plane.materials = [material]
let node = SCNNode(geometry: plane)
scene.rootNode.addChildNode(node)
- Animate your scene
e.g.
labelNode.run(SKAction.repeatForever(SKAction.rotate(byAngle: .pi, duration: 2)))

- 3,494
- 18
- 41
-
thanks for reply when i add this code in ARKit example it terminate when i try to add Plane node in my scene self.sceneView.scene.rootNode.addChildNode(node) It give this error "validateDepthStencilState:3675: failed assertion `MTLDepthStencilDescriptor uses frontFaceStencil but MTLRenderPassDescriptor has a nil stencilAttachment texture'" Any idea? please help – Developer Jul 26 '17 at 14:58
-
I only have testes the code in a SceneKit playground. I have no idea why it should not work in ARKit – jlsiewert Jul 26 '17 at 15:02
-
thanks for the help its because of this line skScene.addChild(rectangle) need to remove that line to run it – Developer Jul 27 '17 at 12:24
-
@orangenkopf you mention something about using an SCNLookAtConstraint but don't have that in your example, could you expound on that. also what if I want to present a scene `.presentScene(skScene)` – Aaron Halvorsen Aug 23 '17 at 22:14
-
2Thanks for this! I've implemented this into my AR testcase without the animation. When I run this, the text of SKLabelNode is mirrored. Do you have any clue why? here you can get an impression of what I'd tried to describe; https://imgur.com/a/RwZn4 – aofs Oct 26 '17 at 15:24
-
@aofs No, but you can mirror the material using the [`SCNMaterialProperty.contentsTransform`](https://developer.apple.com/documentation/scenekit/scnmaterialproperty/1395388-contentstransform) property. – jlsiewert Nov 02 '17 at 10:20
-
@aofs hey, I'm solving similar problem as you were, I'm able to display plane on screen, but didn't have any luck to display a SKScene as material to this plane, can you provide any help/sample code how did you solve this? Thanks in advance! – Mysiaq Feb 05 '18 at 12:47
-
1@Mysiaq I've switched back to the "View as image" method.. See here: https://gist.github.com/katunch/d251ad400911c6381b37c855da36cff7 – aofs Feb 06 '18 at 15:08
-
3If you stop rotating action, your text will be shown in *upside down* . To resolve it, you need to add `material.diffuse.contentsTransform = SCNMatrix4Translate(SCNMatrix4MakeScale(1, -1, 1), 0, 1, 0)` in step number 2. – Karthick Selvaraj Mar 04 '18 at 05:05
-
@aofs The issue with mirrored text from SKLabelNode sounds like the rotation of your plane. For example, if you're rotating by (-.pi/2), try changing it to (.pi/2) – GingerBreadMane Jul 03 '18 at 18:14
Probably worth mentioning that you can also use a couple of other things for contents... A list can be found here... https://developer.apple.com/documentation/scenekit/scnmaterialproperty/1395372-contents
I tried the code from the answer above and it worked fine, but was slowing down my FPS because I have many nodes that need it. And the SKScene is probable quite heavy.
I was able to use an SKView with a SKLabelNode but the problem was that the text would not update visually, My guess would be that I would have to call texture(from:) every time and I figured that would be just as slow SKView texture(from:) https://developer.apple.com/documentation/spritekit/skview/1520114-texture
I saw another way to do it with a CALayer but thought id have the same problem with changing text so I just went with SCNText.
Also worth mentioning SCNBillboardConstraint as an alternative to LookatConstraint https://developer.apple.com/documentation/scenekit/scnbillboardconstraint

- 594
- 5
- 15