123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- import { WebXRFeatureName, WebXRFeaturesManager } from "../webXRFeaturesManager.js";
- import { WebXRAbstractFeature } from "./WebXRAbstractFeature.js";
- import { Matrix } from "../../Maths/math.vector.js";
- import { RenderTargetTexture } from "../../Materials/Textures/renderTargetTexture.js";
- import { ShaderMaterial } from "../../Materials/shaderMaterial.js";
- import "../../Shaders/velocity.fragment.js";
- import "../../Shaders/velocity.vertex.js";
- /**
- * Used for Space Warp render process
- */
- export class XRSpaceWarpRenderTarget extends RenderTargetTexture {
- /**
- * Creates a Space Warp render target
- * @param motionVectorTexture WebGLTexture provided by WebGLSubImage
- * @param depthStencilTexture WebGLTexture provided by WebGLSubImage
- * @param scene scene used with the render target
- * @param size the size of the render target (used for each view)
- */
- constructor(motionVectorTexture, depthStencilTexture, scene, size = 512) {
- super("spacewarp rtt", size, scene, false, true, 2, false, undefined, false, false, true, undefined, true);
- this._originalPairing = [];
- this._previousWorldMatrices = [];
- this._previousTransforms = [Matrix.Identity(), Matrix.Identity()];
- this._renderTarget = this.getScene().getEngine().createMultiviewRenderTargetTexture(this.getRenderWidth(), this.getRenderHeight(), motionVectorTexture, depthStencilTexture);
- this._renderTarget._disposeOnlyFramebuffers = true;
- this._texture = this._renderTarget.texture;
- this._texture.isMultiview = true;
- this._texture.format = 5;
- if (scene) {
- this._velocityMaterial = new ShaderMaterial("velocity shader material", scene, {
- vertex: "velocity",
- fragment: "velocity",
- }, {
- uniforms: ["world", "previousWorld", "viewProjection", "viewProjectionR", "previousViewProjection", "previousViewProjectionR"],
- });
- this._velocityMaterial._materialHelperNeedsPreviousMatrices = true;
- this._velocityMaterial.onBindObservable.add((mesh) => {
- // mesh. getWorldMatrix can be incorrect under rare conditions (e.g. when using a effective mesh in the render function).
- // If the case arise that will require changing it we will need to change the bind process in the material class to also provide the world matrix as a parameter
- this._previousWorldMatrices[mesh.uniqueId] = this._previousWorldMatrices[mesh.uniqueId] || mesh.getWorldMatrix();
- this._velocityMaterial.getEffect().setMatrix("previousWorld", this._previousWorldMatrices[mesh.uniqueId]);
- this._previousWorldMatrices[mesh.uniqueId] = mesh.getWorldMatrix();
- // now set the scene's previous matrix
- this._velocityMaterial.getEffect().setMatrix("previousViewProjection", this._previousTransforms[0]);
- // multiview for sure
- this._velocityMaterial.getEffect().setMatrix("previousViewProjectionR", this._previousTransforms[1]);
- // store the previous (current, to be exact) transforms
- this._previousTransforms[0].copyFrom(scene.getTransformMatrix());
- this._previousTransforms[1].copyFrom(scene._transformMatrixR);
- });
- this._velocityMaterial.freeze();
- }
- }
- render(useCameraPostProcess = false, dumpForDebug = false) {
- // Swap to use velocity material
- this._originalPairing.length = 0;
- const scene = this.getScene();
- // set the velocity material to render the velocity RTT
- if (scene && this._velocityMaterial) {
- scene.getActiveMeshes().forEach((mesh) => {
- this._originalPairing.push([mesh, mesh.material]);
- mesh.material = this._velocityMaterial;
- });
- }
- super.render(useCameraPostProcess, dumpForDebug);
- // Restore original materials
- this._originalPairing.forEach((tuple) => {
- tuple[0].material = tuple[1];
- });
- }
- /**
- * @internal
- */
- _bindFrameBuffer() {
- if (!this._renderTarget) {
- return;
- }
- this.getScene().getEngine().bindSpaceWarpFramebuffer(this._renderTarget);
- }
- /**
- * Gets the number of views the corresponding to the texture (eg. a SpaceWarpRenderTarget will have > 1)
- * @returns the view count
- */
- getViewCount() {
- return 2;
- }
- dispose() {
- super.dispose();
- this._velocityMaterial.dispose();
- this._previousTransforms.length = 0;
- this._previousWorldMatrices.length = 0;
- this._originalPairing.length = 0;
- }
- }
- /**
- * WebXR Space Warp Render Target Texture Provider
- */
- export class WebXRSpaceWarpRenderTargetTextureProvider {
- constructor(_scene, _xrSessionManager, _xrWebGLBinding) {
- this._scene = _scene;
- this._xrSessionManager = _xrSessionManager;
- this._xrWebGLBinding = _xrWebGLBinding;
- this._lastSubImages = new Map();
- this._renderTargetTextures = new Map();
- this._engine = _scene.getEngine();
- }
- _getSubImageForView(view) {
- const layerWrapper = this._xrSessionManager._getBaseLayerWrapper();
- if (!layerWrapper) {
- throw new Error("For Space Warp, the base layer should be a WebXR Projection Layer.");
- }
- if (layerWrapper.layerType !== "XRProjectionLayer") {
- throw new Error('For Space Warp, the base layer type should "XRProjectionLayer".');
- }
- const layer = layerWrapper.layer;
- return this._xrWebGLBinding.getViewSubImage(layer, view);
- }
- _setViewportForSubImage(viewport, subImage) {
- viewport.x = 0;
- viewport.y = 0;
- viewport.width = subImage.motionVectorTextureWidth;
- viewport.height = subImage.motionVectorTextureHeight;
- }
- _createRenderTargetTexture(width, height, framebuffer, motionVectorTexture, depthStencilTexture) {
- if (!this._engine) {
- throw new Error("Engine is disposed");
- }
- const textureSize = { width, height };
- // Create render target texture from the internal texture
- const renderTargetTexture = new XRSpaceWarpRenderTarget(motionVectorTexture, depthStencilTexture, this._scene, textureSize);
- const renderTargetWrapper = renderTargetTexture.renderTarget;
- if (framebuffer) {
- renderTargetWrapper._framebuffer = framebuffer;
- }
- // Create internal texture
- renderTargetWrapper._colorTextureArray = motionVectorTexture;
- renderTargetWrapper._depthStencilTextureArray = depthStencilTexture;
- renderTargetTexture.disableRescaling();
- renderTargetTexture.renderListPredicate = () => true;
- return renderTargetTexture;
- }
- _getRenderTargetForSubImage(subImage, view) {
- const lastSubImage = this._lastSubImages.get(view);
- let renderTargetTexture = this._renderTargetTextures.get(view.eye);
- const width = subImage.motionVectorTextureWidth;
- const height = subImage.motionVectorTextureHeight;
- if (!renderTargetTexture || lastSubImage?.textureWidth !== width || lastSubImage?.textureHeight != height) {
- renderTargetTexture = this._createRenderTargetTexture(width, height, null, subImage.motionVectorTexture, subImage.depthStencilTexture);
- this._renderTargetTextures.set(view.eye, renderTargetTexture);
- this._framebufferDimensions = {
- framebufferWidth: width,
- framebufferHeight: height,
- };
- }
- this._lastSubImages.set(view, subImage);
- return renderTargetTexture;
- }
- trySetViewportForView(viewport, view) {
- const subImage = this._lastSubImages.get(view) || this._getSubImageForView(view);
- if (subImage) {
- this._setViewportForSubImage(viewport, subImage);
- return true;
- }
- return false;
- }
- /**
- * Access the motion vector (which will turn on Space Warp)
- * @param view the view to access the motion vector texture for
- */
- accessMotionVector(view) {
- const subImage = this._getSubImageForView(view);
- if (subImage) {
- // Meta Quest Browser uses accessing these textures as a sign for turning on Space Warp
- subImage.motionVectorTexture;
- subImage.depthStencilTexture;
- }
- }
- getRenderTargetTextureForEye(_eye) {
- return null;
- }
- getRenderTargetTextureForView(view) {
- const subImage = this._getSubImageForView(view);
- if (subImage) {
- return this._getRenderTargetForSubImage(subImage, view);
- }
- return null;
- }
- dispose() {
- this._renderTargetTextures.forEach((rtt) => rtt.dispose());
- this._renderTargetTextures.clear();
- }
- }
- /**
- * the WebXR Space Warp feature.
- */
- export class WebXRSpaceWarp extends WebXRAbstractFeature {
- /**
- * constructor for the space warp feature
- * @param _xrSessionManager the xr session manager for this feature
- */
- constructor(_xrSessionManager) {
- super(_xrSessionManager);
- this._onAfterRenderObserver = null;
- this.dependsOn = [WebXRFeatureName.LAYERS];
- this.xrNativeFeatureName = "space-warp";
- this._xrSessionManager.scene.needsPreviousWorldMatrices = true;
- }
- /**
- * Attach this feature.
- * Will usually be called by the features manager.
- *
- * @returns true if successful.
- */
- attach() {
- if (!super.attach()) {
- return false;
- }
- const engine = this._xrSessionManager.scene.getEngine();
- this._glContext = engine._gl;
- this._xrWebGLBinding = new XRWebGLBinding(this._xrSessionManager.session, this._glContext);
- this.spaceWarpRTTProvider = new WebXRSpaceWarpRenderTargetTextureProvider(this._xrSessionManager.scene, this._xrSessionManager, this._xrWebGLBinding);
- this._onAfterRenderObserver = this._xrSessionManager.scene.onAfterRenderObservable.add(() => this._onAfterRender());
- return true;
- }
- detach() {
- this._xrSessionManager.scene.onAfterRenderObservable.remove(this._onAfterRenderObserver);
- return super.detach();
- }
- _onAfterRender() {
- if (this.attached && this._renderTargetTexture) {
- this._renderTargetTexture.render(false, false);
- }
- }
- isCompatible() {
- return this._xrSessionManager.scene.getEngine().getCaps().colorBufferHalfFloat || false;
- }
- dispose() {
- super.dispose();
- }
- _onXRFrame(_xrFrame) {
- const pose = _xrFrame.getViewerPose(this._xrSessionManager.referenceSpace);
- if (!pose) {
- return;
- }
- // get the first view to which we will create a texture (or update it)
- const view = pose.views[0];
- this._renderTargetTexture = this._renderTargetTexture || this.spaceWarpRTTProvider.getRenderTargetTextureForView(view);
- this.spaceWarpRTTProvider.accessMotionVector(view);
- }
- }
- /**
- * The module's name
- */
- WebXRSpaceWarp.Name = WebXRFeatureName.SPACE_WARP;
- /**
- * The (Babylon) version of this module.
- * This is an integer representing the implementation version.
- * This number does not correspond to the WebXR specs version
- */
- WebXRSpaceWarp.Version = 1;
- //register the plugin
- WebXRFeaturesManager.AddWebXRFeature(WebXRSpaceWarp.Name, (xrSessionManager) => {
- return () => new WebXRSpaceWarp(xrSessionManager);
- }, WebXRSpaceWarp.Version, false);
- //# sourceMappingURL=WebXRSpaceWarp.js.map
|