This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
ShaderGraphStereo is a visionOS sample app demonstrating stereoscopic image rendering using RealityKit and a ShaderGraph material. It loads left/right image pairs into a ShaderGraphMaterial (StereoMaker.usda) applied to a plane entity, displaying each eye's texture independently.
Xcode project, no Makefile. Build via Xcode or xcodebuild:
xcodebuild -project "ShaderGraph Stereo.xcodeproj" -scheme "ShaderGraph Stereo" \
-destination 'platform=visionOS Simulator,name=Apple Vision Pro' buildNo tests are configured.
StereoPair— plain struct withleftImageName,rightImageName,comment,id; four static examples bundled as asset catalog imagesImageViewer— top-level view; holds@State var selectedPair: StereoPair; cycles through pairs via a "Next" buttonStereoView—RealityView-based view; loadsStereoMaker.usdaShaderGraphMaterial in the asyncmake:closure; applies textures per image pair inupdateStereo
StereoViewloadsShaderGraphMaterialnamed/Root/StereoImagefromStereoMaker.usda(local RealityKitContent package)- Sets
LeftImageandRightImageparameters withTextureResourceobjects - Scales a plane
ModelEntitybased on right image aspect ratio - Entity name is set to
imagePair.id; theupdate:closure early-exits if name matches (avoids redundant reloads on window resize)
- RealityKitContent — local package at
Packages/RealityKitContent/providingStereoMaker.usda
visionOS 2.0.
- Duplicate
struct StereoView: BothStereoView_revised.swiftandStereoView_simple.swiftdefinestruct StereoViewand are both in the Xcode Compile Sources phase. RemoveStereoView_simple.swiftfrom the target (or delete it). The revised file is strictly better — it has theimagePair.idearly-exit guard.
TextureResourceload blocks render thread (StereoView_revised.swiftupdateStereo):TextureResource.load(named:)is the synchronous overload, called from theupdate:closure which runs on the render thread. Move texture loading into a.task(id: imagePair.id)modifier using the async overload; store results in@State var leftTexture/@State var rightTexture; theupdate:closure should only apply already-loaded textures to the material.TextureResourcememory leak (StereoView_revised.swift:78, marked// !!!: Replacing the materials array leaks memory): old textures are abandoned when the image changes. Storing them in@State(see above) gives ARC the opportunity to release old values when replaced.- Aspect ratio inversion for portrait images (
StereoView_revised.swift:71–73): the portrait branch setsplaneWidth = planeSideLength * aspectRatio(too wide) andplaneHeight = planeSideLength(too short). Should beplaneWidth = planeSideLength / aspectRatio.
@Environment(\.openWindow) var openWindow(line 19) — never calledGeometryReader { geometry inwrapper (lines 25, 45) —geometrynever referenced; causes greedy layout expansionlet _ = Self._printChanges()(line 29) — debug API, logs to stdout on every body evaluation; remove before shipping@State private var leftTexture/@State private var rightTexture(lines 16–17) — declared but never assigned (localletconstants shadow them inupdateStereo); wire them up as part of the async texture-loading fix or remove
StereoView_simple.swift— superseded byStereoView_revised.swift; causes compile error (see above); delete
StereoPairdefines a free==operator (line 22) but does not declare: Equatableconformance; addEquatableto the struct declaration so the type works in generic contexts
ImageViewercycles pairs via a manual if/else chain — fragile; add aStereoPairall-pairs array and index arithmetic insteadShaderGraphMaterialis loaded perStereoViewinstance; if multiple instances exist it should be cached and shared (only texture parameters change per image)