playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
175 lines (174 loc) • 5.85 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
class XrBridge {
/**
* @param {GraphicsDevice} device - The graphics device.
* @param {EventHandler} eventHandler - Target for firing XR-related errors.
*/
constructor(device, eventHandler) {
/**
* @type {GraphicsDevice}
*/
__publicField(this, "device");
/**
* Receives XR presentation-related events (for example {@link EventHandler#fire} with name `"error"`).
*
* @type {EventHandler}
*/
__publicField(this, "eventHandler");
/**
* @type {object}
*/
__publicField(this, "impl");
/**
* @type {EventHandle|null}
* @private
*/
__publicField(this, "_evtDeviceLost", null);
/**
* @type {EventHandle|null}
* @private
*/
__publicField(this, "_evtDeviceRestored", null);
/**
* Active XR session for presentation (shared across graphics backends).
*
* @type {XRSession|null}
* @private
*/
__publicField(this, "_session", null);
/**
* Resolved framebuffer scale from the last {@link XrBridge#attachPresentation}.
*
* @type {number}
* @private
*/
__publicField(this, "_framebufferScaleFactor", 1);
/**
* Callback when backend GPU binding construction fails.
*
* @type {Function|undefined}
* @private
*/
__publicField(this, "_onBindingError");
this.device = device;
this.eventHandler = eventHandler;
this.impl = device.createXrBridgeImpl(this);
this._evtDeviceLost = device.on("devicelost", this._onDeviceLost, this);
this._evtDeviceRestored = device.on("devicerestored", this._onDeviceRestored, this);
}
destroy() {
const device = this.device;
if (device) {
this._evtDeviceLost?.off();
this._evtDeviceLost = null;
this._evtDeviceRestored?.off();
this._evtDeviceRestored = null;
this.impl.endFrame();
this.impl.destroy(device);
this.impl = null;
this._session = null;
this._framebufferScaleFactor = 1;
this._onBindingError = void 0;
this.device = null;
this.eventHandler = null;
}
}
/** @private */
_onDeviceLost() {
this.impl.onGraphicsDeviceLost();
}
/** @private */
_onDeviceRestored() {
this.impl.onGraphicsDeviceRestored();
}
/**
* @param {XRSession} session - XR session.
* @param {object} options - Presentation options (backend-specific; includes framebufferScaleFactor, depthNear, depthFar).
*/
attachPresentation(session, options) {
this._session = session;
this._framebufferScaleFactor = options.framebufferScaleFactor;
this._onBindingError = options.onBindingError;
this.impl.attachPresentation(session, options);
}
releasePresentation() {
this.impl.releasePresentation();
}
/**
* Called once per XR frame before rendering to set the backend render target for this frame.
*
* @param {XRFrame} frame - Current XR frame.
* @param {XRReferenceSpace|null} referenceSpace - Active XR reference space (WebGPU path uses
* it for subimages).
*/
beginFrame(frame, referenceSpace) {
this.impl.beginFrame(frame, referenceSpace);
}
/**
* Resets the backend render target after the XR session ends.
*/
endFrame() {
this.impl.endFrame();
}
/**
* Writes immersive framebuffer size in pixels for this frame (backend-specific source)
* into {@link Vec2#x} (width) and {@link Vec2#y} (height).
*
* @param {XRFrame} frame - Current XR frame.
* @param {Vec2} out - Receives width and height; reused by the caller to avoid per-frame allocation.
*/
getFramebufferSize(frame, out) {
this.impl.getFramebufferSize(frame, out);
}
/**
* Viewport rectangle for an XR view within the immersive framebuffer (or per-view texture).
*
* @param {XRFrame} frame - Current XR frame.
* @param {XRView} xrView - WebXR view.
* @returns {XRViewport} Viewport for this view.
*/
getViewport(frame, xrView) {
return this.impl.getViewport(frame, xrView);
}
/**
* Copies the XR passthrough camera image for the given `XRCamera` into a PlayCanvas
* {@link Texture}. Delegates to the backend implementation; no-ops if not supported.
*
* @param {any} xrCamera - The XR camera whose image should be copied (XRCamera from WebXR API).
* @param {Texture} texture - Destination engine texture.
*/
syncCameraColorTexture(xrCamera, texture) {
this.impl?.syncCameraColorTexture?.(xrCamera, texture);
}
/**
* Binds XR GPU depth information to the engine depth texture on backends that support it
* (WebGL). No-ops on WebGPU until a binding API exists.
*
* @param {any} depthInfo - Depth information from WebXR (`getDepthInformation`).
* @param {Texture} texture - Destination engine texture.
* @param {number} depthPixelFormat - Resolved depth pixel format constant (`PIXELFORMAT_*`).
*/
syncCameraDepthTexture(depthInfo, texture, depthPixelFormat) {
this.impl?.syncCameraDepthTexture?.(depthInfo, texture, depthPixelFormat);
}
/**
* @returns {XRLayer|null} Backend output layer (e.g. XRWebGLLayer), if any.
*/
get presentationLayer() {
return this.impl.presentationLayer ?? null;
}
/**
* Backend graphics binding for camera/depth when available (for example WebGL
* {@link XRWebGLBinding} or WebGPU `XRGPUBinding` when exposed by the user agent).
*
* @returns {Object|null} The binding object, or null.
*/
get graphicsBinding() {
return this.impl.graphicsBinding ?? null;
}
}
export {
XrBridge
};