Lab 017 – Exploring a Skybox Material with Shader Graph

Swapping a Skybox Material and an Occlusion Material to jump between worlds.

Over the weekend I asked on Bluesky about the possibility of creating a living moving skybox material in RealityKit. Several folks had ideas and @dreamwieber.bsky.social even stepped up with a tutorial.

Maybe I should do a video at some point on something like cloud shaders specifically 🤔You can get something basic going quickly if you use the fractal noise node,

— Gregory (@dreamwieber.bsky.social) 2024-12-08T15:09:29.784Z

This was a great prompt – video is live!bsky.app/profile/drea…

— Gregory (@dreamwieber.bsky.social) 2024-12-08T23:03:14.238Z

You should definitely watch the full video on YouTube. As someone with no background in shaders, I found it immensely helpful. Looking at completed shaders or graphs hasn’t been useful to me. Seeing Gregory assemble this node by node while talking through it was just what I needed.

My version of the Shader is more or less a copy of the one in the video. I’ve adjusted some of the parameters and colors but the nodes are the same.

A screenshot of the Shader Graph Nodes in Reality Composer Pro.

Video Demo

Video demo of an immersive space on Apple Vision Pro. The scene switches back and forth between a video pass-through feed and a skybox material

Lab Code

This lab just just a few things

  • Load a scene from the RealityKitContent bundle
  • Add a tap gesture to toggle the sky from a small sphere to a skybox sphere
  • The update closure will take care of the swap. This is a bit of a hack. I just swapped their scales and match their positions.
struct Lab017: View {

    @State var showSkyLarge: Bool = false

    var body: some View {
        RealityView { content in

            if let scene = try? await Entity(named: "Lab017Scene", in: realityKitContentBundle) {
                content.add(scene)
            }

        } update: {content in

            guard let root = content.entities.first else { return }
            if let skySphere = root.findEntity(named: "SkySphere"), let occSphere = root.findEntity(named: "OccSphere") {

                skySphere.scale = showSkyLarge ? [10, 10, 10] : [0.5, 0.5, 0.5]
                occSphere.scale = showSkyLarge ? [0.5, 0.5, 0.5] : [10, 10, 10]

                if(showSkyLarge) {
                    occSphere.position = skySphere.position
                } else {
                    skySphere.position = occSphere.position
                }

            }

        }
        .gesture(tap)
        .modifier(DragGestureImproved())

    }

    var tap: some Gesture {
        TapGesture()
            .targetedToAnyEntity()
            .onEnded {_ in
                showSkyLarge.toggle()
            }
    }
}

I’m thankful to Gregory for getting me started with Shader Graph. I have a lot to learn and explore and I’m excited to see what I can build with it.

Support our work so we can continue to bring you new examples and articles.

Questions or feedback?