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;