Skip to content

Release 3.0.0 — renderer - #384

Merged
doranteseduardo merged 117 commits into
mainfrom
develop
Sep 19, 2026
Merged

doranteseduardo merged 117 commits into
mainfrom
develop

Conversation

@doranteseduardo

@doranteseduardo doranteseduardo commented Sep 18, 2026 •

Copy link
Copy Markdown
Member

Summary

Release 3.0.0 of the ViroCore renderer. Merges 101 commits from develop. main contains no commits absent from develop.

Features

Area Description
Co-location VROColocationSession as the platform-neutral holder, Colocation_JNI for Android, VROColocationBridge for iOS and visionOS, shared spatial anchors on Quest via xrShareSpacesMETA.
Quest Plane detection through XR_EXT_plane_detection, per-ray drag ownership, passthrough, input controller work.
Web target WASM build under wasm/: the C API consumed by @reactvision/viro-web-renderer, scene bindings, and supporting renderer changes.
Renderer parity Compound physics shapes with volume-weighted mass distribution, alpha cutoff bound only for Mask transparency mode, vertex colour support, glTF doubleSided, drag-plane tolerance handling.

Breaking changes

Change Impact
iOS pod deployment targets raised to 15.0 A post_install hook rewrites every pod target. Required by Xcode 26+, which rejects lower targets outright.
Web renderer font replaced wasm/preload/Helvetica.ttc removed in favour of Roboto.ttf (Apache 2.0). Web text metrics change accordingly. Aligns the web target with Android and Quest, which already render in Roboto.
Android shader assets generated at build time android/shaders.gradle regenerates sharedCode/src/main/assets/*.glsl from ViroRenderer/ during preBuild. The generated files remain tracked, so a build following a shader change modifies the working tree.

Release order

This release spans three repositories. Merge in sequence; each produces the build input for the next.

  1. ReactVision/rvca#10
  2. This pull request
  3. Release 3.0.0 viro#531

Pre-merge checklist

Verification

  • ViroKit.framework and ViroKit.xcframework build clean on Xcode 27 and link 103 ReactVisionCCA co-location symbols.
  • The Android AAR ships shader assets identical to ViroRenderer/, verified by extraction.
  • The WASM target builds reproducibly from develop; the emitted binary is stamped with the commit it was built from.

doranteseduardo and others added 30 commits July 2, 2026 14:06
benmotanoti and others added 24 commits September 15, 2026 21:10
GVRAudioSDK still declares iOS 8.0, PromisesObjC 9.0, GTMSessionFetcher
10.0, the Firebase family 12.0 and ARCore 13.0. Xcode 26+ errors on each
one before compiling a single file, so ViroKit could not be built at all.
The post_install hook rewrites them to the Podfile platform.
ARKit builds getProjection() for the viewport it is handed, but ARCore
answers for the display geometry and ignores the viewport, so on Android a
projection read against the camera image describes the screen's aspect.
Photogrammetry on the image wants the pinhole numbers themselves.

VROARCamera gains getImageIntrinsics(), false by default. The ARCore camera
answers it without acquiring a CPU image: the old isImageDataAvailable()
guard held the one image ARCore hands out and starved the snapshot's later
luma copy. The frame snapshot forwards the values, because that copy is the
only camera the background thread ever sees.
The feature extractor pairs the snapshot's camera pose with the landscape
CPU image, but getRotation() is ARCore's display-oriented pose, which on a
portrait phone is rolled 90 degrees about the optical axis relative to that
image. Rays were cast rotated and only near-axis points survived
triangulation: 8% against iOS's 32%.

arcore::Frame gains getCameraPose(), the ARCore camera keeps the
image-aligned rotation and position beside the display ones, and the
snapshot takes those. ARKit's transform is already the sensor pose, so iOS
is unchanged.
The pass is only built on the HDR path, while this branch runs whenever the
driver's colour mode is not NonLinear, so with HDR off it dereferenced null.
Resolving on a phone is multi-frame SIFT over a 30 second window, and
between issuing the resolve and its callback a caller had nothing to show.
VROARSession gains getCloudAnchorStatus(), answered by the ARCore and ARKit
sessions from the ReactVision provider's active operation, and surfaced to
Java as "progress|message" through ARScene.getCloudAnchorStatus().
Localisation runs off updateFrame's per-frame update, so the frame handed to
the provider is ignored and a resolve issued before ARKit's first frame is
early, not doomed. Gating on it failed every join that mounted with the
anchor id already known, which is how a second device joins.
UIApplication.statusBarOrientation is deprecated and returns Unknown in a
scene-based app, and toCameraOrientation maps Unknown to PortraitUpsideDown,
so the whole AR view rendered 180 degrees out. The view now asks its own
window scene, falling back to the first foreground-active scene and then to
Portrait until orientationDidChange corrects it.
The class is asked whether co-location is available before any AR view has
loaded the renderer, so nativeIsAvailable() threw UnsatisfiedLinkError on
the first open of a scene and the bridge cached "unavailable".
libreactvisioncca is loaded by name as well: Android runs JNI_OnLoad only for
libraries named in System.loadLibrary, and that hook caches the
RVWebSocketSupport class the transport needs.
…on exists

The session is created on a scene's first rendered frame, so a resolve,
host, scan or credentials call issued on mount raced it and the JNI handler
returned without a word: the promise never settled and the anchor id stayed
marked in progress.

VROARScene::runWhenARSessionReady() queues such work and setARSession()
flushes it in order, so a config sent before a resolve still lands first. A
request on a destroyed scene or a non-ARCore session now answers with a
failure, as does a host or resolve while cloud anchors are disabled, and a
duplicate resolve of the same id fails instead of being dropped.
Android .so and iOS .a rebuilt from reactvisioncca with the reflected
transform fix, the yaw-only refinement and vote, and camera intrinsics.
Web render parity: C API, post-processing flags and the JPEG abort
iOS: unblock the ViroKit build on Xcode 26+, and refresh the CCA archives
Carries the relay endpoint default, the x-rv-client build header, the fail-fast
on a refused handshake, the client address the relay counts a device against,
and the 20 Hz pose rate. None of them reach an app until these are rebuilt,
because the renderer links the static libraries rather than the sources.
wasm/preload is baked into viro-web.data with --preload-file, so everything in
it is redistributed with the package — and what was in it was Helvetica.ttc,
2.2 MB copied off macOS. That is the whole of what has been holding
@reactvision/viro-web-renderer at unpublished.

Roboto instead: Apache 2.0, so it can travel with the binary, and it is already
what Viro renders text in on Android and Quest. The web player was the third
different typeface of three; now it agrees with two of them. The preload set
drops from 2.3 MB to 460 KB, which is almost all of the data blob.

The face is named in one place on each side — kSystemFont in VROTypefaceWasm and
kWebSystemFont in VROSceneWeb, which had it typed in at the call site. The
loader now tries .ttf and .ttc for each name rather than assuming the suffix,
because that is a property of the file someone preloaded and not of the name a
scene asked for.
web: render text in Roboto, not a font we cannot ship
doranteseduardo and others added 3 commits September 18, 2026 14:46
Fix head pose delivery to the camera on headset
The README covered build.sh and the CLion setup for the test targets, and never
mentioned build_web.sh — the one that produces the three files
@reactvision/viro-web-renderer publishes. Someone following it would build the
wrong thing.

Adds that path, the copy-and-test step in the package beside it, why the tree
should be clean before building, and what preload/ means: everything in there is
baked into viro-web.data and redistributed, which is how a font we were not
licensed to ship stayed in the bundle for weeks.
@doranteseduardo
doranteseduardo merged commit e75ddff into main Sep 19, 2026
5 checks passed
@doranteseduardo
doranteseduardo deleted the develop branch September 19, 2026 04:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants