1

I tried loading an .hdr file to use it as a skybox and use its lighting informations. This is the code I used:

backgroundColor = UIColor.gray 
// check if a default skybox is added

let environment = UIImage(named: "studio_small_09_2k.hdr")
scene?.lightingEnvironment.contents = environment
scene?.lightingEnvironment.intensity = 1.0
scene?.background.contents = environment

Unfortunately I recieve a grey screen and also no errors. Has anyone experience in using hdr files in SceneKit?

XCode Version: 13.2.1 iOS version: 15.3.1 hdr file: https://polyhaven.com/a/studio_small_09

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220

1 Answers1

1

I usually use a Cube Texture Set, where each of 6 images is square (height == width).

Also, the following cube map representations are supported:

  • Vertical strip as single image (height == 6 * width)
  • Horizontal strip as single image (6 * height == width)
  • Spherical projection as single image (2 * height == width)

Here's a SwiftUI code:

func makeUIView(context: Context) -> SCNView {

    let sceneView = SCNView(frame: .zero)
    sceneView.scene = SCNScene()
    // if EXR or HDR is 2:1 spherical map, it really meets the requirements
    sceneView.scene?.lightingEnvironment.contents = UIImage(named: "std.exr")
    sceneView.backgroundColor = .black
    sceneView.autoenablesDefaultLighting = true
    sceneView.allowsCameraControl = true
    
    let node = SCNNode()
    node.geometry = SCNSphere(radius: 0.1)
    node.geometry?.firstMaterial?.lightingModel = .physicallyBased
    node.geometry?.firstMaterial?.metalness.contents = 1.0
    sceneView.scene?.rootNode.addChildNode(node)
    return sceneView
}

Pay particular attention – you need .physicallyBased lighting model to get HDR or EXR reflections.

enter image description here

And let's set it for BG:

sceneView.scene?.background.contents = UIImage(named: "std.exr")

enter image description here


Why your .exr doesn't work?

The solutions is simple: delete your .exr from project, empty the Trash and after that drag-and-drop .exr file, in Choose options for adding these files window choose Add to targets:

enter image description here

Now your .exr must work.

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
  • 1
    Thanks! I'll go for a cube texture set then and don't use the asset in my example. So the hdr format simply is not going to work in this context? But I was kind of irritated because the image I was using looks quite a lot like a spherical projection and has 2048 × 1024 pixels. Shouldn't it work already then? – Mario P. Waxenegger Apr 13 '22 at 13:53
  • Both `.hdr` and `.exr` images work in SceneKit. – Andy Jazz Apr 13 '22 at 14:23
  • 1
    Thanks for your update. After setting `autoenablesDefaultLighting = true` the ambient light information from hdr works perfectly fine. But still I don't get the desired result for `scene?.background.contents = UIImage(named: "std.hdr")`. – Mario P. Waxenegger Apr 13 '22 at 14:27
  • 1
    No I’m still sticking to my example and have the UIImage stored in a variable. So no copy/paste/name errors. Maybe it’s because there’s a background Color set? – Mario P. Waxenegger Apr 13 '22 at 14:49
  • Then use `Shift`+`Command`+`K` to clean your Xcode project. Or delete a build and rebuild app again. As you can see my `.hdr` BG is ok. – Andy Jazz Apr 13 '22 at 14:51
  • 2
    note that it is better to use a file path or URL to avoid having the image data several times in memory (once for for `UImage`, once for SceneKit's internal handling of Metal texture contents) – mnuages Apr 14 '22 at 10:48
  • Totally agree.. – Andy Jazz Apr 14 '22 at 10:49
  • 1
    @AndyJazz Did a clean build. Even rebooted everything... still no success with the background. Really weird. @mnuages so you'd recommend to put: `sceneView.scene?.lightingEnvironment.contents = "std.hdr"` to avoid using memory for having the UIImage instance? – Mario P. Waxenegger Apr 15 '22 at 09:51
  • 1
    Mario, try my project – https://dropmefiles.com/mBNwI – (password `123`) – Andy Jazz Apr 15 '22 at 10:26
  • 1
    Thanks that works. Actually I did my own ViewClass by inheriting from `SCNView` so i had a `init(coder: NSCoder)` constructor and set `frame = .zero` inside that initializer. Might that be the issue? – Mario P. Waxenegger Apr 15 '22 at 12:23
  • potentially yes – Andy Jazz Apr 15 '22 at 12:25
  • 1
    I tried a little bit longer with different approaches, no success. That feels a little bit weird to me. Why should this function not work when I initialize my SCNView differently? I mean it's still a SCNView object, should its behaviour not be consistent? I've also had no success altering `scene?.lightingEnvironment.intensity` even cranking it up to `1000` did'n change anything. I also tried using SCNView by adding it with storyboard and then setting the default scene of that. – Mario P. Waxenegger Apr 20 '22 at 15:17
  • 1
    A behavior must be consistent. Could you share your code? – Andy Jazz Apr 20 '22 at 15:25
  • 1
    https://dropmefiles.com/mBbFY at least vignette is working in this minimal example now (thanks to your other reply). But I noticed that even the reflections in the sphere don't match the loaded environment - it looks much more like the default lightEnv. – Mario P. Waxenegger Apr 21 '22 at 09:29
  • 1
    I'm so sorry. Here we go again: https://dropmefiles.com/cfkO6 Pw: 123 – Mario P. Waxenegger Apr 21 '22 at 11:17
  • 1
    Thank you very much! Now everything works fine! – Mario P. Waxenegger Apr 21 '22 at 13:00