VisionOS Portal: How to make Entities stick out?

271 Views Asked by At

In the WWDC talk "Enhance your spatial computing app with RealityKit." we see how to create a portal effect with RealityKit. In the "Encounter Dinosaurs" experience on Vision Pro there is a similar portal, except this portal allows entities to stick out of the portal. Using the provided example code, I have been unable to replicate this effect. With the example code, anything that sticks out of the portal gets clipped.

How do I get entities to stick out of the portal in a way similar to the "Encounter Dinosaurs" experience?

I am familiar with the old way of using OcclusionMaterial to create portals, but if the camera gets between the OcclusionMaterial and the entity (such as walking behind the portal), this can break the effect, and I was unable to break the effect in the "Encounter Dinosaurs" experience.

If it helps at all: I have noticed that if you look from the edge of the portal very closely, the rocks will not stick out the way that the dinosaurs do; The rocks get clipped. Therefore, the dinosaurs are somehow being rendered differently.

I tried setting the scene up as described in the WWDC talk "Enhance your spatial computing app with RealityKit." I created a portal and gave it a PortalMaterial and PortalComponent targeting my world. I created a world and gave it a WorldComponent. I added everything to the scene with content.add and got the same effect as the WWDC talk, but cannot get entities to stick out of the portal. Adjusting the clippingPlane of the PortalComponent did not seem to help at all.

1

There are 1 best solutions below

0
Andy Jazz On

Of course, the portal in the Encounter Dinosaurs app is not the same as the one here, i.e. portal effect based on PortalMaterial. To reproduce a similar portal effect (where a character sticks out of the portal), I used Maya model consisting of interior walls (with normals pointing inward), exterior walls (with normals pointing outward) and an elephant model. The code is as simple as that:

enter image description here

import SwiftUI
import RealityKit

struct ContentView : View {
    var body: some View {
        RealityView { content in
            if let portal = try? await Entity(named: "portal") {
                portal.scale *= 5
                portal.position.z = -2
                content.add(portal)
                
                // There are 3 models inside – inner, outer, elephant
                print(portal)
                
                let inner = portal.findEntity(named: "inner") as! ModelEntity
                var pbrMaterial = PhysicallyBasedMaterial()
                pbrMaterial.faceCulling = .none
                pbrMaterial.baseColor.tint = .systemRed
                inner.model?.materials = [pbrMaterial]
                
                let outer = portal.findEntity(named: "outer") as! ModelEntity
                let occlusionMaterial = OcclusionMaterial()
                outer.model?.materials = [occlusionMaterial]
                
                let elephant = portal.findEntity(named: "elephant") as! ModelEntity
                let goldenMaterial = SimpleMaterial(color: .yellow, isMetallic: true)
                elephant.model?.materials = [goldenMaterial]
            }
        }
    }
}

The USDZ model you can download from here.

enter image description here