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(); + }); + } +}); diff --git a/src/components/layer.js b/src/components/layer.js index bef96972f82..76d7e81b615 100644 --- a/src/components/layer.js +++ b/src/components/layer.js @@ -6,8 +6,10 @@ 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']}}, + radius: {default: 198, if: {type: ['mono-equirect', 'stereo-left-right-equirect', 'stereo-top-bottom-equirect']}}, rotateCubemap: {default: false}, width: {default: 0}, height: {default: 0} @@ -59,6 +61,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 +111,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 +242,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 +253,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 +269,36 @@ export var Component = registerComponent('layer', { } }, + initEquirectLayer: function () { + if (!this.texture) { return; } + var sceneEl = this.el.sceneEl; + var eqrtIs180 = this.data.is180; + 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); + 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;