Whitebox Plugin - Three.js for VideoJS¶
This is a plugin for whitebox that provides Three.js integration VideoJS players.
Video360 projection and leveling contract¶
DualFisheyeProjectedVideo keeps the horizontal 2:1 dual-fisheye layout
identified by whitebox.video360.dual-fisheye-hstack.v1: stream 0 is the
left square half and stream 1 is the right square half. The shader owns that
projection; equirectangular inputs are not supported.
The optional projection prop defaults to that profile. The optional
onLevelingReady callback receives a generation-bound capability after the
Three.js sphere and renderer are ready, and receives null when that generation
is retired. Existing options and onReady behavior is unchanged.
The capability contains only:
{
projection: "whitebox.video360.dual-fisheye-hstack.v1",
frame: "whitebox.video360.leveling-root.v1",
apply({ frame, gravity }),
clear(),
}
The leveling-root frame is the right-handed Three.js root/world frame: +X
world (viewer-left with the current +Z camera target), +Y up, and +Z
target-forward. Device producers own camera-specific raw-to-root calibration.
gravity is a finite three-element unit vector expressed in that frame. The
renderer defensively normalizes values within 1e-3 of unit length and rejects
all other values. Gravity contains no yaw information; root leveling applies
the shortest deterministic rotation directly from root gravity to world down
[0, -1, 0] and adds no intentional twist. OrbitControls and the user camera
remain independent of leveling.
Independently, the shader source direction and THREE.SphereGeometry vertex
use different numeric bases for the same UV. The dual-fisheye projection domain
maps source (x, y, z) to sphere vertex (z, y, -x) using the fixed +90° Y
basis matrix:
This basis belongs only to panorama texture sampling and projection tests. It must not be applied to root leveling, OrbitControls, or the camera. Keeping the projection mapping separate preserves shader presentation while canonical side and front/back gravity rotate around the visible roll and pitch axes.
SphereGeometry stores its vertical UV as 1-v. The shader therefore uses
(vUv.y - 0.5) * pi for its internal source latitude so source and geometry Y
have the same sign. Its final fisheye texture V calculation uses the paired
opposite sign, 0.5 - fy * 0.5; these two signs must change together. Their
effects cancel algebraically, preserving the existing sampled texture exactly.
apply and clear return promises. A promise resolves true only after a
render used that exact latest root transform. Superseded or retired work
resolves false; invalid frame/vector input rejects and resets the source root
to neutral. Leveling never modifies the camera, OrbitControls, Video.js player,
texture, or shader resources.
Each post-initialization Video.js loadstart retires the old leveling source
generation, resets its root to neutral, and publishes a fresh capability. When
the tech and video element are unchanged, this does not recreate player or
Three.js resources.
Installation¶
Install the plugin to whitebox: