> axiom-scenekit-ref

SceneKit → RealityKit concept mapping, complete API cross-reference for migration, scene graph API, materials, lighting, camera, physics, animation, constraints

fetch
$curl "https://skillshub.wtf/CharlesWiltgen/Axiom/axiom-scenekit-ref?format=md"
SKILL.mdaxiom-scenekit-ref

SceneKit API Reference & Migration Mapping

Complete API reference for SceneKit with RealityKit equivalents for every major concept.

When to Use This Reference

Use this reference when:

  • Looking up SceneKit → RealityKit API equivalents during migration
  • Checking specific SceneKit class properties or methods
  • Planning which SceneKit features have direct RealityKit counterparts
  • Understanding architectural differences between scene graph and ECS

Part 1: SceneKit → RealityKit Concept Mapping

Core Architecture

SceneKitRealityKitNotes
SCNSceneRealityViewContent / Entity (root)RealityKit scenes are entity hierarchies
SCNNodeEntityLightweight container in both
SCNViewRealityView (SwiftUI)ARView for UIKit on iOS
SceneView (SwiftUI)RealityViewSceneView deprecated iOS 26
SCNRendererRealityRendererLow-level Metal rendering
Node propertiesComponentsECS separates data from hierarchy
SCNSceneRendererDelegateSystem / SceneEvents.UpdateFrame-level updates
.scn files.usdz / .usda filesConvert with xcrun scntool

Geometry & Rendering

SceneKitRealityKitNotes
SCNGeometryMeshResourceRealityKit generates from code or loads USD
SCNBox, SCNSphere, etc.MeshResource.generateBox(), .generateSphere()Similar built-in shapes
SCNMaterialSimpleMaterial, PhysicallyBasedMaterialPBR-first in RealityKit
SCNMaterial.lightingModel = .physicallyBasedPhysicallyBasedMaterialDefault in RealityKit
SCNMaterial.diffusePhysicallyBasedMaterial.baseColorDifferent property name
SCNMaterial.metalnessPhysicallyBasedMaterial.metallicDifferent property name
SCNMaterial.roughnessPhysicallyBasedMaterial.roughnessSame concept
SCNMaterial.normalPhysicallyBasedMaterial.normalSame concept
Shader modifiersShaderGraphMaterial / CustomMaterialNo direct port — must rewrite
SCNProgram (custom shaders)CustomMaterial with Metal functionsDifferent API surface
SCNGeometrySourceMeshResource.ContentsLow-level mesh data

Transforms & Hierarchy

SceneKitRealityKitNotes
node.positionentity.positionBoth SCNVector3 / SIMD3<Float>
node.eulerAnglesentity.orientation (quaternion)RealityKit prefers quaternions
node.scaleentity.scaleBoth SIMD3<Float>
node.transformentity.transform4×4 matrix
node.worldTransformentity.transform(relativeTo: nil)World-space transform
node.addChildNode(_:)entity.addChild(_:)Same hierarchy concept
node.removeFromParentNode()entity.removeFromParent()Same concept
node.childNodesentity.childrenChildren collection
node.parententity.parentParent reference
node.childNode(withName:recursively:)entity.findEntity(named:)Named lookup

Lighting

SceneKitRealityKitNotes
SCNLight (.omni)PointLightComponentPoint light
SCNLight (.directional)DirectionalLightComponentSun/directional light
SCNLight (.spot)SpotLightComponentCone light
SCNLight (.area)No direct equivalentUse multiple point lights
SCNLight (.ambient)EnvironmentResource (IBL)Image-based lighting preferred
SCNLight (.probe)EnvironmentResourceEnvironment probes
SCNLight (.IES)No direct equivalentUse light intensity profiles

Camera

SceneKitRealityKitNotes
SCNCameraPerspectiveCamera entityEntity with camera component
camera.fieldOfViewPerspectiveCameraComponent.fieldOfViewInDegreesSame concept
camera.zNear / camera.zFarPerspectiveCameraComponent.near / .farClipping planes
camera.wantsDepthOfFieldPost-processing effectsDifferent mechanism
camera.motionBlurIntensityPost-processing effectsDifferent mechanism
allowsCameraControlCustom gesture handlingNo built-in orbit camera

Physics

SceneKitRealityKitNotes
SCNPhysicsBodyPhysicsBodyComponentComponent-based
.dynamic.dynamicSame mode
.static.staticSame mode
.kinematic.kinematicSame mode
SCNPhysicsShapeCollisionComponent / ShapeResourceSeparate from body in RealityKit
categoryBitMaskCollisionGroupNamed groups vs raw bitmasks
collisionBitMaskCollisionFilterFilter-based
contactTestBitMaskCollisionEvents.Began subscriptionEvent-based contacts
SCNPhysicsContactDelegatescene.subscribe(to: CollisionEvents.Began.self)Combine-style events
SCNPhysicsFieldPhysicsBodyComponent forcesApply forces directly
SCNPhysicsJointPhysicsJointSimilar joint types

Animation

SceneKitRealityKitNotes
SCNActionentity.move(to:relativeTo:duration:)Transform animation
SCNAction.sequenceAnimation chainingLess declarative in RealityKit
SCNAction.groupParallel animationsApply to different entities
SCNAction.repeatForeverAnimationPlaybackController repeatDifferent API
SCNTransaction (implicit)No direct equivalentExplicit animations only
CAAnimation bridgeentity.playAnimation()Load from USD
SCNAnimationPlayerAnimationPlaybackControllerPlayback control
Morph targetsBlend shapes in USDLoad via USD files

Interaction

SceneKitRealityKitNotes
hitTest(_:options:)RealityViewContent.entities(at:)Different API
Gesture recognizers on SCNViewManipulationComponentBuilt-in drag/rotate/scale
allowsCameraControlCustom implementationNo built-in orbit

AR Integration

SceneKitRealityKitNotes
ARSCNViewRealityView + AnchorEntityLegacy → modern
ARSCNViewDelegateAnchorEntity auto-trackingEvent-driven
renderer(_:didAdd:for:)AnchorEntity(.plane)Declarative anchoring
ARWorldTrackingConfigurationSpatialTrackingSessioniOS 18+

Part 2: Scene Graph API

SCNScene

// Loading
let scene = SCNScene(named: "scene.usdz")!
let scene = try SCNScene(url: url, options: [
    .checkConsistency: true,
    .convertToYUp: true
])

// Properties
scene.rootNode                    // Root of node hierarchy
scene.background.contents        // Skybox (UIImage, UIColor, MDLSkyCubeTexture)
scene.lightingEnvironment.contents // IBL environment map
scene.fogStartDistance            // Fog near
scene.fogEndDistance              // Fog far
scene.fogColor                   // Fog color
scene.isPaused                   // Pause simulation

SCNNode

// Creation
let node = SCNNode()
let node = SCNNode(geometry: SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0))

// Transform
node.position = SCNVector3(x, y, z)
node.eulerAngles = SCNVector3(pitch, yaw, roll)
node.scale = SCNVector3(1, 1, 1)
node.simdPosition = SIMD3<Float>(x, y, z)  // SIMD variants available
node.pivot = SCNMatrix4MakeTranslation(0, -0.5, 0) // Offset pivot point

// Visibility
node.isHidden = false
node.opacity = 1.0
node.castsShadow = true
node.renderingOrder = 0   // Lower = rendered first

// Hierarchy
node.addChildNode(child)
node.removeFromParentNode()
node.childNodes
node.childNode(withName: "name", recursively: true)
node.enumerateChildNodes { child, stop in }

Part 3: Materials

Lighting Models

ModelDescriptionUse Case
.physicallyBasedPBR metallic-roughnessRealistic rendering (recommended)
.blinnBlinn-Phong specularSimple shiny surfaces
.phongPhong specularClassic specular highlight
.lambertDiffuse only, no specularMatte surfaces
.constantUnlit, flat colorUI elements, debug visualization
.shadowOnlyInvisible, receives shadowsAR ground plane

Material Properties

let mat = SCNMaterial()
mat.lightingModel = .physicallyBased

// Textures or scalar values
mat.diffuse.contents = UIImage(named: "albedo")    // Base color
mat.metalness.contents = 0.0                        // 0 = dielectric, 1 = metal
mat.roughness.contents = 0.5                        // 0 = mirror, 1 = rough
mat.normal.contents = UIImage(named: "normal")      // Normal map
mat.ambientOcclusion.contents = UIImage(named: "ao") // AO map
mat.emission.contents = UIColor.blue                // Glow
mat.displacement.contents = UIImage(named: "height") // Height map

// Options
mat.isDoubleSided = false        // Render both sides
mat.writesToDepthBuffer = true
mat.readsFromDepthBuffer = true
mat.blendMode = .alpha           // .add, .subtract, .multiply, .screen
mat.transparencyMode = .aOne     // .rgbZero for pre-multiplied alpha

Part 4: Physics

Body Types and Properties

// Dynamic body with custom shape
let shape = SCNPhysicsShape(geometry: SCNSphere(radius: 0.5), options: nil)
let body = SCNPhysicsBody(type: .dynamic, shape: shape)
body.mass = 1.0
body.friction = 0.5
body.restitution = 0.3       // Bounciness
body.damping = 0.1            // Linear damping
body.angularDamping = 0.1     // Angular damping
body.isAffectedByGravity = true
body.allowsResting = true     // Sleep optimization
node.physicsBody = body

// Compound shapes
let compound = SCNPhysicsShape(shapes: [shape1, shape2],
    transforms: [transform1, transform2])

// Concave (static only)
let concave = SCNPhysicsShape(geometry: mesh, options: [
    .type: SCNPhysicsShape.ShapeType.concavePolyhedron
])

Joint Types

JointDescription
SCNPhysicsHingeJointSingle-axis rotation (door)
SCNPhysicsBallSocketJointFree rotation around point (pendulum)
SCNPhysicsSliderJointLinear movement along axis (drawer)
SCNPhysicsConeTwistJointLimited rotation (ragdoll limb)

Part 5: Animation API

SCNAction Catalog

CategoryActions
Movementmove(by:duration:), move(to:duration:)
Rotationrotate(by:around:duration:), rotateTo(x:y:z:duration:)
Scalescale(by:duration:), scale(to:duration:)
FadefadeIn(duration:), fadeOut(duration:), fadeOpacity(to:duration:)
Visibilityhide(), unhide()
AudioplayAudio(source:waitForCompletion:)
Customrun { node in }, customAction(duration:action:)
Compositionsequence([]), group([]), repeat(_:count:), repeatForever(_:)
Controlwait(duration:), removeFromParentNode()

Timing Functions

action.timingMode = .linear        // Default
action.timingMode = .easeIn        // Slow start
action.timingMode = .easeOut       // Slow end
action.timingMode = .easeInEaseOut // Slow start and end
action.timingFunction = { t in     // Custom curve
    return t * t  // Quadratic ease-in
}

Part 6: Constraints

ConstraintPurpose
SCNLookAtConstraintNode always faces target
SCNBillboardConstraintNode always faces camera
SCNDistanceConstraintMaintains min/max distance
SCNReplicatorConstraintCopies transform of target
SCNAccelerationConstraintSmooths transform changes
SCNSliderConstraintLocks to axis
SCNIKConstraintInverse kinematics chain
let lookAt = SCNLookAtConstraint(target: targetNode)
lookAt.isGimbalLockEnabled = true  // Prevent roll
lookAt.influenceFactor = 0.8       // Partial constraint
node.constraints = [lookAt]

In RealityKit: No direct constraint system. Implement with System update logic or entity.look(at:from:relativeTo:).


Part 7: Scene Configuration

SCNView Configuration

PropertyDefaultDescription
antialiasingMode.multisampling4XMSAA level
preferredFramesPerSecond60Target frame rate
allowsCameraControlfalseBuilt-in orbit/pan/zoom
autoenablesDefaultLightingfalseAdd default light if none
showsStatisticsfalseFPS/node/draw count overlay
isTemporalAntialiasingEnabledfalseTAA smoothing
isJitteringEnabledfalseTemporal jitter for TAA
debugOptions[].showPhysicsShapes, .showBoundingBoxes, .renderAsWireframe

Resources

WWDC: 2014-609, 2014-610, 2017-604, 2019-612

Docs: /scenekit, /scenekit/scnscene, /scenekit/scnnode, /scenekit/scnmaterial, /scenekit/scnphysicsbody, /scenekit/scnaction

Skills: axiom-scenekit, axiom-realitykit, axiom-realitykit-ref

┌ stats

installs/wk0
░░░░░░░░░░
github stars641
██████████
first seenMar 17, 2026
└────────────

┌ repo

CharlesWiltgen/Axiom
by CharlesWiltgen
└────────────

┌ tags

└────────────