Before I am going mad I'd like to ask here about the following issue.
I wrote an iOS test app in SwiftUI that shows a SpriteView
and a SceneView
. The SpriteView
shows (among other things) two SK3DNode
nodes that display one and the same SCNScene
from different camera positions. The SceneView
renders the very same SCNScene
.
The problem is that the rendered scene in both SK3DNode's are shown darker than in SceneView.
The scenes in SpriteKit are unusable because they are too dark.
This is a screenshot from the iPad simulator:
I expected both SK3DNode
's (at the top half) to render the scene at the same brightness as the SceneView
(bottom half).
If I simply increase the ambient light, objects are shown way too bright.
I thought the problem is the texture or the material, but the problem also occurs with colours. Hence the red/green/blue shapes.
I have disabled SK3DNode
's built-in lighting by setting autoenablesDefaultLighting
to false
. Somehow SceneView
(or its internal SCNView
) must add its own lighting but I cannot figure how. The scene's rootNode
only shows my nodes from the .scn file.
I've disabled the environment in the scene file so there is no sky cube. There is one ambient light source, one spot light, and one omni light. No matter which lights I am using, both SK3DNode
's still present the scene much darker than the SceneView
.
Here is the function that creates the two SK3DNode
s:
func make3DNode(camPos: SCNVector3) -> SK3DNode {
// Add SceneKit scene in 3D node
let node3d = SK3DNode(viewportSize: CGSize(width: 300, height: 200))
node3d.scnScene = scnScene
node3d.autoenablesDefaultLighting = false
let camera = SCNCamera()
let cameraNode = SCNNode()
cameraNode.camera = camera
if let lookAtTarget = scnScene.rootNode.childNode(withName: "red_texture", recursively: false) {
let constraint = SCNLookAtConstraint(target: lookAtTarget)
// why does this not work?
cameraNode.constraints = [constraint]
}
cameraNode.position = camPos
node3d.pointOfView = cameraNode
return node3d
}
On a side note: the camera lookAt constraint does not seem to work either.
Code to add the nodes to the scene:
// Add SceneKit nodes
let node3d_1 = make3DNode(camPos: SCNVector3(x: -5, y: -2, z: 14))
node3d_1.name = "3d_1"
node3d_1.position = CGPoint(x: 150, y: 110)
spriteScene.addChild(node3d_1)
let node3d_2 = make3DNode(camPos: SCNVector3(x: 5, y: 2, z: 14))
node3d_2.name = "3d_2"
node3d_2.position = CGPoint(x: 150, y: -110)
spriteScene.addChild(node3d_2)
Full project source: https://github.com/biochill/test-spritekit
It includes both the SpriteKit scene file and the SceneKit file. The SK3DNode
s are added programmatically. I can't paste code for the scenes because I have created scene files both for SpriteKit and SceneKit. Best if you download the GitHub project and hit Cmd+R in Xcode for some iPad simulator.
Thanks for any help in advance.
Here is what I did, to make both scenes (upper SpriteKit
embedded and lower part SceneKit
of the screen) to look the same:
Enabled: autoenablesDefaultLighting
(you could also add lighting manually and then set autoenablesDefaultLighting
to false
)
in file: ContentView.swift
func make3DNode(camPos: SCNVector3) -> SK3DNode {
// Add SceneKit scene in 3D node
let node3d = SK3DNode(viewportSize: CGSize(width: 300, height: 200))
node3d.scnScene = scnScene
node3d.autoenablesDefaultLighting = true // <-- set to true
I also re-enabled the code-line: MySceneView(scene: scnScene)...
in file: MySceneView.swift
struct MySceneView: UIViewRepresentable {
var scene: SCNScene
// var visibleSize: CGSize
func makeUIView(context: Context) -> SCNView {
// SLog.print("DiceView.makeUIView size=\(visibleSize)")
let scnView = context.coordinator
scnView.scene = scene
scnView.delegate = scnView
scnView.autoenablesDefaultLighting = true // <-- set to true
The most important part comes here, which effectively fixed the issue in my testings.
You need to add a valid info.plist
file to the project.
Add this content: SCNDisableLinearSpaceRendering = YES/true
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SCNDisableLinearSpaceRendering</key>
<true/>
</dict>
</plist>
Note: you will not see this setting listed here:
And this is how it looks like on my iPad mini:
Further adjustments: As already mentioned, you could manage the Lighting manually.
I hope this resolves the issue with the dark scene.