Releases: ReactVision/viro
v2.53.1
v2.53.0
@reactvision/react-viro v2.53.0 — Release Notes
⚠️ Breaking Changes
ViroARSceneNavigator — provider replaces cloudAnchorProvider and geospatialAnchorProvider
The two separate props are merged into a single provider prop that controls both backends simultaneously. provider defaults to "reactvision" so the prop can be omitted entirely in most cases.
Before:
<ViroARSceneNavigator
cloudAnchorProvider="reactvision"
geospatialAnchorProvider="reactvision"
initialScene={{ scene: MyARScene }}
/>After:
// defaults to "reactvision" — prop can be omitted
<ViroARSceneNavigator initialScene={{ scene: MyARScene }} />
// Or to override:
<ViroARSceneNavigator provider="arcore" initialScene={{ scene: MyARScene }} />ViroCloudAnchorProvider and ViroGeospatialAnchorProvider are now deprecated aliases for the new ViroProvider type. They still compile with a deprecation warning.
Expo plugin (withViro) — provider replaces cloudAnchorProvider and geospatialAnchorProvider
Before:
["@reactvision/react-viro", {
"cloudAnchorProvider": "reactvision",
"geospatialAnchorProvider": "reactvision",
"rvApiKey": "...",
"rvProjectId": "..."
}]After:
["@reactvision/react-viro", {
"provider": "reactvision",
"rvApiKey": "...",
"rvProjectId": "..."
}]ViroARPlaneSelector requires manual anchor wiring
The component no longer self-discovers planes. You must now forward ViroARScene anchor events to it via a ref:
const selectorRef = useRef<ViroARPlaneSelector>(null);
<ViroARScene
anchorDetectionTypes={["PlanesHorizontal", "PlanesVertical"]}
onAnchorFound={(a) => selectorRef.current?.handleAnchorFound(a)}
onAnchorUpdated={(a) => selectorRef.current?.handleAnchorUpdated(a)}
onAnchorRemoved={(a) => a && selectorRef.current?.handleAnchorRemoved(a)}
>
<ViroARPlaneSelector ref={selectorRef} alignment="Both" onPlaneSelected={...}>
<MyContent />
</ViroARPlaneSelector>
</ViroARScene>What's new
ReactVision Cloud Anchors (RVCA)
Place persistent AR content that other users can find — no Google Cloud account required. RVCA is a proprietary closed-source SDK; its implementation is not part of the open-source ViroCore or react-viro distribution.
The "reactvision" provider routes hostCloudAnchor / resolveCloudAnchor through the ReactVision platform. The existing hostCloudAnchor, resolveCloudAnchor, and onCloudAnchorStateChange API is unchanged.
- Hosting: scan your environment briefly, then call
hostCloudAnchor. Returns an error immediately if the environment has not been sufficiently observed — no silent fallback. - Resolving: the SDK matches the live camera feed against stored anchor data and returns a pose once a confident localisation is established. Cross-platform (iOS host → Android resolve and vice versa) is fully supported.
- TTL:
hostCloudAnchoraccepts attlDaysparameter (1–365) to control anchor expiry on the backend. - GPS tagging: set the device location before hosting to embed GPS coordinates as anchor metadata. Enables proximity search via
rvFindNearbyCloudAnchors.
8 new methods on arSceneNavigator for full CRUD and analytics on cloud anchors:
| Method | Description |
|---|---|
rvGetCloudAnchor(anchorId) |
Fetch a single anchor record |
rvListCloudAnchors(limit, offset) |
Paginated list of all project anchors |
rvUpdateCloudAnchor(id, name, desc, isPublic) |
Rename / re-describe an anchor |
rvDeleteCloudAnchor(anchorId) |
Permanently delete an anchor and its assets |
rvFindNearbyCloudAnchors(lat, lng, radius, limit) |
GPS proximity search |
rvAttachAssetToCloudAnchor(id, url, size, name, type, userId) |
Attach a hosted file |
rvRemoveAssetFromCloudAnchor(anchorId, assetId) |
Remove an attached asset |
rvTrackCloudAnchorResolution(...) |
Record resolve analytics manually |
ReactVision Geospatial Anchor Management
5 new management methods for GPS-tagged anchors (backed by the proprietary RVCA SDK):
| Method | Description |
|---|---|
rvListGeospatialAnchors(limit, offset) |
Paginated list |
rvGetGeospatialAnchor(anchorId) |
Fetch a single geospatial anchor |
rvFindNearbyGeospatialAnchors(lat, lng, radius, limit) |
GPS proximity search |
rvUpdateGeospatialAnchor(id, sceneAssetId, sceneId, name) |
Update metadata |
rvDeleteGeospatialAnchor(anchorId) |
Permanently delete |
createGeospatialAnchor, createTerrainAnchor, and createRooftopAnchor are now supported with provider="reactvision". No VPS, no ARCore Geospatial API, and no ARCore pods are required.
Asset upload:
rvUploadAsset(assetType, filename, data, appUserId) — uploads a file to ReactVision storage and returns a URL and asset ID. Supported assetType values: "3d-model", "image", "video", "audio". The returned asset ID can be linked to a geospatial anchor via rvUpdateGeospatialAnchor or to a cloud anchor via rvAttachAssetToCloudAnchor.
New geospatial utilities
gpsToArWorld(devicePose, lat, lng, alt)— converts a GPS coordinate to an AR world-space[x, y, z]offset from the device's current geospatial pose.latLngToMercator(lat, lng)— converts a GPS coordinate to a metric 2D position. Building block forgpsToArWorldand custom geo math.
Both are exported from @reactvision/react-viro.
New ViroProvider type
Canonical union type "none" | "arcore" | "reactvision" exported from the package. Replaces the deprecated ViroCloudAnchorProvider and ViroGeospatialAnchorProvider types.
Shader modifier system — major expansion
Shader modifiers now support the full range of custom GPU effects:
- Custom textures — declare
uniform sampler2Din modifier code and pass textures viamaterialUniforms. Swap them at runtime withupdateShaderUniform. - Vertex → fragment data — use the new
varyingsfield to pass typed values from a Geometry modifier to a Surface or Fragment modifier (e.g. displacement amount driving roughness). - Scene depth access — set
requiresSceneDepth: trueon a fragment modifier to receivescene_depth_textureautomatically. Enables soft particles, contact glow, and intersection effects. - Live camera feed on geometry — set
requiresCameraTexture: trueto sample the AR camera on any surface. Platform differences (samplerExternalOESvssampler2D) handled invisibly. Enables magnifying glass, portal, refraction, and warp effects. - Deterministic ordering — modifiers now have a
priorityfield so engine internals never override your effects regardless of attachment order.
AR plane detection improvements
- Plane detection now defaults to both horizontal and vertical — no need to set
anchorDetectionTypesexplicitly. - Objects placed via
ViroARPlaneSelectornow appear at the exact tap point, not the plane centre. onPlaneSelectedreceives the tap position as a third argument:(plane, tapPosition?) => void.- New props:
onPlaneRemoved,hideOverlayOnSelection,material. useActualShapenow defaults totrue— polygon boundary used instead of bounding rect.- New public method
handleAnchorRemovedonViroARPlaneSelectorfor use in theonAnchorRemovedcallback.
Depth sensor access
ViroARSceneNavigator has three new props for apps that need depth data without full occlusion:
depthEnabled— activates LiDAR / monocular depth / ARCore Depth forDepthPointhit tests.depthDebugEnabled— overlays the depth map on the camera feed.preferMonocularDepth(iOS only) — forces monocular depth even on LiDAR devices.
Bug fixes
- Models with washed-out / overexposed colours — GLB and other 3D assets appeared too bright due to an emissive colour value being incorrectly added to all materials. Fixed.
- iOS video recording silent failure —
startVideoRecording/stopVideoRecordingwere broken on iOS 17+ with the New Architecture. MultipleAVAssetWriterandAVAudioSessionissues fixed; recording now falls back to video-only if audio fails. - Android crash when closing a scene with physics — null pointer dereference on scene close for physics-enabled nodes. Fixed.
- Android New Architecture dev menu error — "You should not use ReactNativeHost directly" error on startup. Fixed.
- Ghost planes in
ViroARPlaneSelector— pre-allocated slot index mapping was non-deterministic causing planes to appear in wrong positions or persist after removal. Fully rewritten. - Selected plane disappeared immediately on tap — opacity logic inversion fixed.
- Children rendered on every plane slot — children now rendered once, only on the selected plane.
onPlaneDetectedreturn value ignored — returningfalsefromonPlaneDetectedpreviously had no effect. Now correctly prevents the plane from being added to the visible set.- Removed planes not cleaned up — disappeared planes were never removed from internal state, accumulating over time.
handleAnchorRemovednow deletes the entry and resets selection if needed. - Plane updates silently dropped for large surfaces — ARKit update threshold logic was AND instead of OR; large planes (floors, walls) rarely updated. Fixed.
- Rapid plane updates dropped on initial detection — fixed 100 ms throttle replaced with adaptive rate (33 ms for first 20 updates, 66 ms thereafter).
v2.52.1
What's Changed
- Fix ARCORE crashes and depth issues. by @doranteseduardo in #439
Full Changelog: v2.52.0...v2.52.1
v2.52.0 - Shader System & Memory Improvements
Summary
This release adds shader customization support for iOS and Android, fixes critical memory leaks, and improves AR depth functionality.
Key Features
Shader System (New)
- Cross-platform shader support
- Real-time shader customization for iOS and Android
- Shader propagation down node trees
- Standardized fragment output
- Texture and animation support in shaders
- Optimized material sharing for better performance
AR & Depth Improvements
- Depth-based AR hit testing
- Monocular depth fallback for non-LiDAR devices
- Fixed depth frame alignment issues
Critical Bug Fixes
- iOS Memory Leaks (Critical): Fixed all memory leaks on iOS platform
- Material Overflow: Fixed cloned materials array overflow crashes
- Portal Crashes: Fixed crashes when unmounting portals on iOS
- Gravity Type Crash: Fixed Android crash (gravity now uses 3D vector
[x, y, z]instead of number) - VRX Asset Loading: Fixed VRX asset loading issues on iOS
- hitResultId: Fixed availability in AR hit tests
Other Improvements
- Performance throttle to prevent system overload
- Refactored thread lock implementation
- Removed debug logs from production code
- Improved TypeScript type definitions
v2.51.0
What's Changed
- Merge develop → main (AR stability + depth estimation for non-LiDAR) by @doranteseduardo in #428
Full Changelog: v2.50.1...v2.51.0
v2.50.1
What's Changed
- Update README.md by @oliedis in #414
- Weak Linking for ARcore Pods by @doranteseduardo in #417
Full Changelog: v2.50.0...v2.50.1
v2.50.0
ReactVision 2.50.0 Release Notes
New Features
All features from ViroCore 2.50.0 are included, plus React Native specific bug fixes.
Cloud Anchors
Cross-platform AR anchor sharing between iOS and Android devices.
- Cross-Platform: Share anchors between iOS and Android devices
- Persistent: Anchors can be stored for 1-365 days
- Accurate: Sub-centimeter accuracy in good conditions
- Scalable: Supports multiple concurrent users
<ViroARSceneNavigator cloudAnchorProvider="arcore">
{/* Use sceneNavigator.hostCloudAnchor() and resolveCloudAnchor() */}
</ViroARSceneNavigator>API Highlights:
hostCloudAnchor(anchorId, ttlDays)- Upload anchor to Google's serversresolveCloudAnchor(cloudAnchorId)- Retrieve anchor on another devicecancelCloudAnchorOperations()- Cancel pending operations
Geospatial API
Location-based AR with GPS coordinates using Google's ARCore Geospatial API.
- Earth Tracking: Track device position using GPS and Visual Positioning System (VPS)
- Three Anchor Types: WGS84 (absolute altitude), Terrain (relative to ground), and Rooftop (relative to buildings)
- VPS Availability Check: Verify if enhanced positioning is available at a location
<ViroARSceneNavigator geospatialAnchorProvider="arcore">
{/* Use createGeospatialAnchor(), createTerrainAnchor(), createRooftopAnchor() */}
</ViroARSceneNavigator>API Highlights:
createGeospatialAnchor(lat, lng, altitude, quaternion)- WGS84 anchorcreateTerrainAnchor(lat, lng, altitudeAboveTerrain, quaternion)- Ground-relative anchorcreateRooftopAnchor(lat, lng, altitudeAboveRooftop, quaternion)- Building-relative anchorgetCameraGeospatialPose()- Get current location with accuracy metricscheckVPSAvailability(lat, lng)- Check VPS support at location
Scene Semantics
ML-based scene understanding with 12 semantic labels.
- 12 Semantic Labels: sky, building, tree, road, sidewalk, terrain, structure, object, vehicle, person, water, unlabeled
- Real-time Processing: Per-frame label fractions
- Use Cases: Outdoor detection, environment-aware content, safety warnings
// Enable via cloudAnchorProvider or geospatialAnchorProvider
// Use getSemanticLabelFractions() for environment detection
const { fractions } = await arSceneNavigator.getSemanticLabelFractions();
if (fractions.sky > 0.1) {
console.log("User is outdoors!");
}Depth Occlusion
Visual occlusion behind real-world objects for realistic AR blending.
- Three Modes: Disabled, DepthBased, PeopleOnly
- Realistic Blending: Virtual objects hidden behind real surfaces
- People Segmentation: Option to only occlude behind detected people
<ViroARSceneNavigator occlusionMode="depthBased">
{/* Virtual content properly occluded behind real surfaces */}
</ViroARSceneNavigator>Occlusion Modes:
"disabled"- No occlusion (virtual objects always on top)"depthBased"- Use depth data to occlude behind real surfaces"peopleOnly"- Only occlude behind detected people
Extended glTF Support
Expanded glTF 2.0 support with 17 additional features for improved 3D model compatibility.
Core Geometry & Materials
- Non-indexed geometry support - Primitives without index buffers
- LINE_LOOP primitive type - Converted to line strip with closing segment
- TRIANGLE_FAN primitive type - Converted to individual triangles
- Mipmap filter modes - Proper separation of min/mip filtering
- Alpha masking (MASK mode) - With alphaCutoff support
- Emissive materials - emissiveFactor and emissiveTexture
- STEP animation interpolation - Discrete keyframe transitions
- Sparse accessor support - Override specific buffer values
Camera & Scene
- Perspective cameras - FOV, near/far planes, aspect ratio
- Orthographic cameras - xmag, ymag, clipping planes
- Default scene selection - Respects model.defaultScene
Lighting (KHR_lights_punctual)
- Directional lights - Color, intensity
- Point lights - Color, intensity, range/attenuation
- Spot lights - Color, intensity, range, inner/outer cone angles
Material Extensions
- KHR_materials_unlit - Constant/unlit lighting model
- Normal texture scale - Controls bump intensity
- Occlusion texture strength - Controls AO influence
Bug Fixes
Memory Leak Fix
- Enhanced memory safety across 8 Java modules through Fabric architecture migration
- Fixed null reference issues in prop application during React Native's pre-attachment phase
- Improved stability during AR session transitions and low-end device scenarios
- Migrated 30 methods to use Fabric's
UIBlockpattern for safer memory management
Affected Modules:
- ARSceneModule
- ARSceneNavigatorModule
- CameraModule
- ControllerModule
- NodeModule
- SceneModule
- SceneNavigatorModule
- VRT3DSceneNavigatorModule
onClick iOS Fix
- Fixed ViroText onClick event handling on iOS
- Resolved issue where onClick prop was incorrectly passed to native code, interfering with event delegation
- Fixes GitHub issue #272
AR Image Marker Fix
- Improved ARImageMarker lifecycle management with proper weak reference patterns
- Prevents retain cycles and memory leaks during image target tracking
- Proper cleanup via
removeARImageTarget()when updating targets
Setup
Expo Projects
{
"expo": {
"plugins": [
[
"@reactvision/react-viro",
{
"googleCloudApiKey": "YOUR_API_KEY",
"cloudAnchorProvider": "arcore",
"geospatialAnchorProvider": "arcore",
"android": {
"xRMode": ["AR"]
}
}
]
]
}
}Then rebuild:
npx expo prebuild --clean
npx expo run:ios
# or
npx expo run:androidBare React Native Projects
iOS - Podfile:
use_frameworks! :linkage => :dynamic
pod 'ARCore/CloudAnchors', '~> 1.51.0'
pod 'ARCore/Geospatial', '~> 1.51.0'
pod 'ARCore/Semantics', '~> 1.51.0'iOS - Info.plist:
<key>GARAPIKey</key>
<string>YOUR_GOOGLE_CLOUD_API_KEY</string>Android - AndroidManifest.xml:
<meta-data
android:name="com.google.android.ar.API_KEY"
android:value="YOUR_GOOGLE_CLOUD_API_KEY" />Requirements
- iOS: iOS 12.0+, ARKit-capable device
- Android: Android 7.0+ (API 24), ARCore-supported device
- Google Cloud: Valid API key with ARCore API enabled
- Depth Features: LiDAR (iOS) or ToF sensor/ARCore Depth API (Android)
v2.44.2
This is a minor patch update that removes some layers in the Android side to get 1:1 plane detection compared with direct ARCore implementations.
See at v2.44.1 for more details.
v2.44.1
Release Notes – v2.44.1
AR Plane Detection & Selection – Major Update
ViroARPlaneSelector – Complete Rewrite
Accurate Plane Shape Rendering
- Planes now render using their actual geometric boundaries from ARKit/ARCore (via boundary vertices).
- Automatic fallback to rectangular visualisation when vertex data is not available.
- New
useActualShapeproperty to control rendering mode (default:true).
Map-Based Plane Tracking
- Replaced array-based tracking with
Map<string, ViroARPlaneType>for reliable and deterministic plane handling. - Plane identification now uses
anchorId, eliminating index-based race conditions. - Improved stability for both plane selection and update cycles.
Multi-Alignment Detection
- Added new alignment mode:
"Both"for concurrent horizontal and vertical plane detection. - 25 detectors per alignment type for broader and more consistent scene coverage.
- Enhanced scene understanding through simultaneous multi-plane detection.
Plane Classification Support (iOS)
- ARKit plane classification now exposed, including: Wall, Floor, Ceiling, Table, Seat, Door, Window.
- Classification data is included in all plane update callbacks.
- Enables semantic placement and surface-specific logic.
Enhanced Properties & Callbacks
onPlaneDetected?: (updateMap) => boolean— Validate planes before adding them.disableClickSelection?: boolean— Enables visual-only mode.useActualShape?: boolean— Controls shape rendering behaviour.
Visual Improvements
- Updated material to a bright, translucent blue (
rgba(0, 122, 255, 0.5)) for improved visibility. cullMode: "None"enabled for better Android rendering compatibility.- Corrected alpha blending and depth buffer behaviour.
ViroARPlane Improvements
Improved Vertex Handling
- More accurate 3D-to-2D vertex conversion for shape mapping.
- Unified coordinate system handling across iOS and Android.
- Corrected rotation logic for horizontal and vertical surfaces.
Enhanced Anchor Data
- Plane anchors now provide full metadata: position, rotation, scale, centre, and dimensions.
- Classification and vertex data included in all callbacks.
- Consistent and reliable
anchorIdtracking throughout the plane lifecycle.
Architecture & Performance
16KB Page Size Support
- Full compatibility with modern Android devices using 16KB memory pages.
Breaking Changes
Removed Properties (ViroARPlaneSelector)
maxPlanesremoved (replaced by dynamic 25-detector-per-alignment behaviour).ViroCommonPropsandViroObjectPropsremoved from type definitions.- These properties were previously documented but non-functional.
- The component now exposes only explicit, fully supported props.
Internal State Refactor
- Internal state has been migrated from an array to a
Map.- (This affects only direct internal state access and does not impact typical usage.)
v2.43.6
This is a patch release targeting the pod installation issues happening in EAS mainly. We have tested this update in different installation scenarios all with success.