From 039a0f2b0b824ef7ce222a22063db158eceb265c Mon Sep 17 00:00:00 2001 From: Vincent Fretin Date: Fri, 25 Apr 2025 18:07:42 +0200 Subject: [PATCH 1/3] Add support for equirect layer --- src/components/layer.js | 54 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/components/layer.js b/src/components/layer.js index bef96972f82..617cfd3e981 100644 --- a/src/components/layer.js +++ b/src/components/layer.js @@ -6,8 +6,9 @@ var warn = utils.debug('components:layer:warn'); export var Component = registerComponent('layer', { schema: { - type: {default: 'quad', oneOf: ['quad', 'monocubemap', 'stereocubemap']}, + type: {default: 'quad', oneOf: ['mono-equirect', 'stereo-left-right-equirect', 'stereo-top-bottom-equirect', 'quad', 'monocubemap', 'stereocubemap']}, src: {type: 'map'}, + is180: {default: false, if: {type: ['mono-equirect', 'stereo-left-right-equirect', 'stereo-top-bottom-equirect']}}, rotateCubemap: {default: false}, width: {default: 0}, height: {default: 0} @@ -59,6 +60,11 @@ export var Component = registerComponent('layer', { this.destroyLayer(); this.texture = undefined; this.textureIsVideo = this.data.src.tagName === 'VIDEO'; + if (type.endsWith('equirect')) { + this.loadEquirectImage(); + return; + } + if (type === 'quad') { this.loadQuadImage(); return; @@ -104,6 +110,15 @@ export var Component = registerComponent('layer', { } }, + loadEquirectImage: function () { + var src = this.data.src; + var self = this; + this.el.sceneEl.systems.material.loadTexture(src, {src: src}, function textureLoaded (texture) { + self.el.sceneEl.renderer.initTexture(texture); + self.texture = texture; + }); + }, + loadQuadImage: function () { var src = this.data.src; var self = this; @@ -226,7 +241,7 @@ export var Component = registerComponent('layer', { if (this.data.src.complete && (this.pendingCubeMapUpdate || this.loadingScreen || this.visibilityChanged)) { this.loadCubeMapImages(); } if (!this.needsRedraw && !this.layer.needsRedraw) { return; } if (this.textureIsVideo) { return; } - if (this.data.type === 'quad') { this.draw(); } + if (this.data.type === 'quad' || this.data.type.endsWith('equirect')) { this.draw(); } }, initLayer: function () { @@ -237,6 +252,11 @@ export var Component = registerComponent('layer', { self.visibilityChanged = evt.session.visibilityState !== 'hidden'; }; + if (type.endsWith('equirect')) { + this.initEquirectLayer(); + return; + } + if (type === 'quad') { this.initQuadLayer(); return; @@ -248,6 +268,36 @@ export var Component = registerComponent('layer', { } }, + initEquirectLayer: function () { + if (!this.texture) { return; } + var sceneEl = this.el.sceneEl; + var eqrtIs180 = this.data.is180; + var eqrtRadius = 10; + var eqrtLayout = this.data.type.replace('-equirect', ''); // mono stereo-left-right stereo-top-bottom + if (this.textureIsVideo) { + var mediaBinding = new XRMediaBinding(sceneEl.xrSession); + this.layer = mediaBinding.createEquirectLayer(this.data.src, { + space: this.referenceSpace, + layout: eqrtLayout + }); + } else { + var eqrtTextureWidth = this.texture.image.width; + var eqrtTextureHeight = this.texture.image.height; + var xrGLFactory = this.xrGLFactory = sceneEl.renderer.xr.getBinding(); + this.layer = xrGLFactory.createEquirectLayer({ + space: this.referenceSpace, + viewPixelWidth: eqrtTextureWidth / (eqrtLayout === 'stereo-left-right' ? 2 : 1), + viewPixelHeight: eqrtTextureHeight / (eqrtLayout === 'stereo-top-bottom' ? 2 : 1), + layout: eqrtLayout + }); + } + this.layer.centralHorizontalAngle = Math.PI * (eqrtIs180 ? 1 : 2); + this.layer.upperVerticalAngle = Math.PI / 2.0; + this.layer.lowerVerticalAngle = -Math.PI / 2.0; + this.layer.radius = eqrtRadius; + sceneEl.renderer.xr.addLayer(this.layer); + }, + initQuadLayer: function () { if (!this.texture) { return; } var sceneEl = this.el.sceneEl; From 092525345d87dcf6125304b5250b7b3cfcf2e390 Mon Sep 17 00:00:00 2001 From: Vincent Fretin Date: Sat, 3 May 2025 10:15:52 +0200 Subject: [PATCH 2/3] Add layer-equirect example, stereo-top-bottom 360 video by default for now --- examples/test/layer-equirect/index.html | 50 ++++++++++++++++++++ examples/test/layer-equirect/toggle-layer.js | 9 ++++ 2 files changed, 59 insertions(+) create mode 100644 examples/test/layer-equirect/index.html create mode 100644 examples/test/layer-equirect/toggle-layer.js diff --git a/examples/test/layer-equirect/index.html b/examples/test/layer-equirect/index.html new file mode 100644 index 00000000000..f53023c7782 --- /dev/null +++ b/examples/test/layer-equirect/index.html @@ -0,0 +1,50 @@ + + + + + Compositor Equirect Layer Example • A-Frame + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/test/layer-equirect/toggle-layer.js b/examples/test/layer-equirect/toggle-layer.js new file mode 100644 index 00000000000..0ed242ef714 --- /dev/null +++ b/examples/test/layer-equirect/toggle-layer.js @@ -0,0 +1,9 @@ +/* global AFRAME */ +AFRAME.registerComponent('toggle-layer', { + init: function () { + var layerEl = document.querySelector('[layer]'); + this.el.addEventListener('thumbstickdown', function () { + layerEl.components.layer.toggleCompositorLayer(); + }); + } +}); From 4718e0e6dcfe3a92e2343286240ff53af0b89d1b Mon Sep 17 00:00:00 2001 From: Vincent Fretin Date: Sat, 3 May 2025 10:20:56 +0200 Subject: [PATCH 3/3] Add property to set sphere radius, 198 by default (lower value than default environment sky radius that is 200) --- src/components/layer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/layer.js b/src/components/layer.js index 617cfd3e981..76d7e81b615 100644 --- a/src/components/layer.js +++ b/src/components/layer.js @@ -9,6 +9,7 @@ export var Component = registerComponent('layer', { type: {default: 'quad', oneOf: ['mono-equirect', 'stereo-left-right-equirect', 'stereo-top-bottom-equirect', 'quad', 'monocubemap', 'stereocubemap']}, src: {type: 'map'}, is180: {default: false, if: {type: ['mono-equirect', 'stereo-left-right-equirect', 'stereo-top-bottom-equirect']}}, + radius: {default: 198, if: {type: ['mono-equirect', 'stereo-left-right-equirect', 'stereo-top-bottom-equirect']}}, rotateCubemap: {default: false}, width: {default: 0}, height: {default: 0} @@ -272,7 +273,7 @@ export var Component = registerComponent('layer', { if (!this.texture) { return; } var sceneEl = this.el.sceneEl; var eqrtIs180 = this.data.is180; - var eqrtRadius = 10; + var eqrtRadius = this.data.radius; var eqrtLayout = this.data.type.replace('-equirect', ''); // mono stereo-left-right stereo-top-bottom if (this.textureIsVideo) { var mediaBinding = new XRMediaBinding(sceneEl.xrSession);