Skip to content

Commit a592737

Browse files
Use XRMediaBinding.createQuadLayer to render flat video on a layer (#5709)
1 parent fa52fb5 commit a592737

File tree

1 file changed

+30
-60
lines changed

1 file changed

+30
-60
lines changed

src/components/layer.js

Lines changed: 30 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* global XRRigidTransform, XRWebGLBinding */
1+
/* global XRMediaBinding, XRRigidTransform, XRWebGLBinding */
22
import * as THREE from 'three';
33
import { registerComponent } from '../core/component.js';
44
import * as utils from '../utils/index.js';
@@ -14,14 +14,10 @@ export var Component = registerComponent('layer', {
1414
},
1515

1616
init: function () {
17-
var gl = this.el.sceneEl.renderer.getContext();
18-
1917
this.quaternion = new THREE.Quaternion();
2018
this.position = new THREE.Vector3();
2119

2220
this.bindMethods();
23-
this.needsRedraw = false;
24-
this.frameBuffer = gl.createFramebuffer();
2521

2622
var webxrData = this.el.sceneEl.getAttribute('webxr');
2723
var requiredFeaturesArray = webxrData.requiredFeatures;
@@ -45,7 +41,9 @@ export var Component = registerComponent('layer', {
4541

4642
updateSrc: function () {
4743
var type = this.data.type;
44+
this.destroyLayer();
4845
this.texture = undefined;
46+
this.textureIsVideo = this.data.src.tagName === 'VIDEO';
4947
if (type === 'quad') {
5048
this.loadQuadImage();
5149
return;
@@ -97,12 +95,6 @@ export var Component = registerComponent('layer', {
9795
this.el.sceneEl.systems.material.loadTexture(src, {src: src}, function textureLoaded (texture) {
9896
self.el.sceneEl.renderer.initTexture(texture);
9997
self.texture = texture;
100-
if (src.tagName === 'VIDEO') { setTimeout(function () { self.textureIsVideo = true; }, 1000); }
101-
if (self.layer) {
102-
self.layer.height = self.data.height / 2 || self.texture.image.height / 1000;
103-
self.layer.width = self.data.width / 2 || self.texture.image.width / 1000;
104-
self.needsRedraw = true;
105-
}
10698
self.updateQuadPanel();
10799
});
108100
},
@@ -217,9 +209,9 @@ export var Component = registerComponent('layer', {
217209
if (!this.layer && (this.el.sceneEl.is('vr-mode') || this.el.sceneEl.is('ar-mode'))) { this.initLayer(); }
218210
this.updateTransform();
219211
if (this.data.src.complete && (this.pendingCubeMapUpdate || this.loadingScreen || this.visibilityChanged)) { this.loadCubeMapImages(); }
220-
if (!this.needsRedraw && !this.layer.needsRedraw && !this.textureIsVideo) { return; }
212+
if (!this.layer.needsRedraw) { return; }
213+
if (this.textureIsVideo) { return; }
221214
if (this.data.type === 'quad') { this.draw(); }
222-
this.needsRedraw = false;
223215
},
224216

225217
initLayer: function () {
@@ -242,17 +234,25 @@ export var Component = registerComponent('layer', {
242234
},
243235

244236
initQuadLayer: function () {
245-
var sceneEl = this.el.sceneEl;
246-
var gl = sceneEl.renderer.getContext();
247-
var xrGLFactory = this.xrGLFactory = new XRWebGLBinding(sceneEl.xrSession, gl);
248237
if (!this.texture) { return; }
249-
this.layer = xrGLFactory.createQuadLayer({
250-
space: this.referenceSpace,
251-
viewPixelHeight: 2048,
252-
viewPixelWidth: 2048,
253-
height: this.data.height / 2 || this.texture.image.height / 1000,
254-
width: this.data.width / 2 || this.texture.image.width / 1000
255-
});
238+
var sceneEl = this.el.sceneEl;
239+
if (this.textureIsVideo) {
240+
var mediaBinding = new XRMediaBinding(sceneEl.xrSession);
241+
this.layer = mediaBinding.createQuadLayer(this.data.src, {
242+
space: this.referenceSpace,
243+
height: this.data.height / 2 || this.texture.image.height / 1000,
244+
width: this.data.width / 2 || this.texture.image.width / 1000
245+
});
246+
} else {
247+
var xrGLFactory = this.xrGLFactory = sceneEl.renderer.xr.getBinding();
248+
this.layer = xrGLFactory.createQuadLayer({
249+
space: this.referenceSpace,
250+
viewPixelHeight: this.texture.image.height,
251+
viewPixelWidth: this.texture.image.width,
252+
height: this.data.height / 2 || this.texture.image.height / 1000,
253+
width: this.data.width / 2 || this.texture.image.width / 1000
254+
});
255+
}
256256
sceneEl.renderer.xr.addLayer(this.layer);
257257
},
258258

@@ -262,7 +262,7 @@ export var Component = registerComponent('layer', {
262262
var gl = sceneEl.renderer.getContext();
263263
var glSizeLimit = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
264264
var cubeFaceSize = this.cubeFaceSize = Math.min(glSizeLimit, Math.min(src.width, src.height));
265-
var xrGLFactory = this.xrGLFactory = new XRWebGLBinding(sceneEl.xrSession, gl);
265+
var xrGLFactory = this.xrGLFactory = sceneEl.renderer.xr.getBinding();
266266
this.layer = xrGLFactory.createCubeLayer({
267267
space: this.referenceSpace,
268268
viewPixelWidth: cubeFaceSize,
@@ -337,19 +337,14 @@ export var Component = registerComponent('layer', {
337337
},
338338

339339
draw: function () {
340-
var sceneEl = this.el.sceneEl;
341340
var gl = this.el.sceneEl.renderer.getContext();
341+
var sceneEl = this.el.sceneEl;
342+
var textureEl = this.data.src;
342343
var glayer = this.xrGLFactory.getSubImage(this.layer, sceneEl.frame);
343-
var texture = sceneEl.renderer.properties.get(this.texture).__webglTexture;
344-
var previousFrameBuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
345-
346-
gl.viewport(glayer.viewport.x, glayer.viewport.y, glayer.viewport.width, glayer.viewport.height);
347-
gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer);
348-
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, glayer.colorTexture, 0);
349-
350-
blitTexture(gl, texture, glayer, this.data.src);
351-
352-
gl.bindFramebuffer(gl.FRAMEBUFFER, previousFrameBuffer);
344+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
345+
gl.bindTexture(gl.TEXTURE_2D, glayer.colorTexture);
346+
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, textureEl.width, textureEl.height, gl.RGBA, gl.UNSIGNED_BYTE, textureEl);
347+
gl.bindTexture(gl.TEXTURE_2D, null);
353348
},
354349

355350
updateTransform: function () {
@@ -389,28 +384,3 @@ export var Component = registerComponent('layer', {
389384
this.referenceSpace = referenceSpace;
390385
}
391386
});
392-
393-
function blitTexture (gl, texture, subImage, textureEl) {
394-
var xrReadFramebuffer = gl.createFramebuffer();
395-
var x1offset = subImage.viewport.x;
396-
var y1offset = subImage.viewport.y;
397-
var x2offset = subImage.viewport.x + subImage.viewport.width;
398-
var y2offset = subImage.viewport.y + subImage.viewport.height;
399-
400-
// Update video texture.
401-
if (textureEl.tagName === 'VIDEO') {
402-
gl.bindTexture(gl.TEXTURE_2D, texture);
403-
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, textureEl.width, textureEl.height, gl.RGB, gl.UNSIGNED_BYTE, textureEl);
404-
}
405-
406-
// Bind texture to read framebuffer.
407-
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, xrReadFramebuffer);
408-
gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
409-
410-
// Blit into layer buffer.
411-
gl.readBuffer(gl.COLOR_ATTACHMENT0);
412-
gl.blitFramebuffer(0, 0, textureEl.width, textureEl.height, x1offset, y1offset, x2offset, y2offset, gl.COLOR_BUFFER_BIT, gl.NEAREST);
413-
414-
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
415-
gl.deleteFramebuffer(xrReadFramebuffer);
416-
}

0 commit comments

Comments
 (0)