1
0
Fork 0
mirror of https://github.com/DanielnetoDotCom/YouPHPTube synced 2025-10-05 10:49:36 +02:00
Oinktube/node_modules/cardboard-vr-display/src/cardboard-distorter.js
2023-12-11 11:59:56 -03:00

674 lines
22 KiB
JavaScript

/*
* Copyright 2016 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as Util from './util.js';
import WGLUPreserveGLState from 'gl-preserve-state';
var distortionVS = [
'attribute vec2 position;',
'attribute vec3 texCoord;',
'varying vec2 vTexCoord;',
'uniform vec4 viewportOffsetScale[2];',
'void main() {',
' vec4 viewport = viewportOffsetScale[int(texCoord.z)];',
' vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;',
' gl_Position = vec4( position, 1.0, 1.0 );',
'}',
].join('\n');
var distortionFS = [
'precision mediump float;',
'uniform sampler2D diffuse;',
'varying vec2 vTexCoord;',
'void main() {',
' gl_FragColor = texture2D(diffuse, vTexCoord);',
'}',
].join('\n');
/**
* A mesh-based distorter.
*
* @param {WebGLRenderingContext} gl
* @param {CardboardUI?} cardboardUI;
* @param {number} bufferScale;
* @param {boolean} dirtySubmitFrameBindings;
*/
function CardboardDistorter(gl, cardboardUI, bufferScale, dirtySubmitFrameBindings) {
this.gl = gl;
this.cardboardUI = cardboardUI;
this.bufferScale = bufferScale;
this.dirtySubmitFrameBindings = dirtySubmitFrameBindings;
this.ctxAttribs = gl.getContextAttributes();
this.instanceExt = gl.getExtension('ANGLE_instanced_arrays');
this.meshWidth = 20;
this.meshHeight = 20;
this.bufferWidth = gl.drawingBufferWidth;
this.bufferHeight = gl.drawingBufferHeight;
// Patching support
this.realBindFramebuffer = gl.bindFramebuffer;
this.realEnable = gl.enable;
this.realDisable = gl.disable;
this.realColorMask = gl.colorMask;
this.realClearColor = gl.clearColor;
this.realViewport = gl.viewport;
if (!Util.isIOS()) {
this.realCanvasWidth = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'width');
this.realCanvasHeight = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'height');
}
this.isPatched = false;
// State tracking
this.lastBoundFramebuffer = null;
this.cullFace = false;
this.depthTest = false;
this.blend = false;
this.scissorTest = false;
this.stencilTest = false;
this.viewport = [0, 0, 0, 0];
this.colorMask = [true, true, true, true];
this.clearColor = [0, 0, 0, 0];
this.attribs = {
position: 0,
texCoord: 1
};
this.program = Util.linkProgram(gl, distortionVS, distortionFS, this.attribs);
this.uniforms = Util.getProgramUniforms(gl, this.program);
this.viewportOffsetScale = new Float32Array(8);
this.setTextureBounds();
this.vertexBuffer = gl.createBuffer();
this.indexBuffer = gl.createBuffer();
this.indexCount = 0;
this.renderTarget = gl.createTexture();
this.framebuffer = gl.createFramebuffer();
this.depthStencilBuffer = null;
this.depthBuffer = null;
this.stencilBuffer = null;
if (this.ctxAttribs.depth && this.ctxAttribs.stencil) {
this.depthStencilBuffer = gl.createRenderbuffer();
} else if (this.ctxAttribs.depth) {
this.depthBuffer = gl.createRenderbuffer();
} else if (this.ctxAttribs.stencil) {
this.stencilBuffer = gl.createRenderbuffer();
}
this.patch();
this.onResize();
};
/**
* Tears down all the resources created by the distorter and removes any
* patches.
*/
CardboardDistorter.prototype.destroy = function() {
var gl = this.gl;
this.unpatch();
gl.deleteProgram(this.program);
gl.deleteBuffer(this.vertexBuffer);
gl.deleteBuffer(this.indexBuffer);
gl.deleteTexture(this.renderTarget);
gl.deleteFramebuffer(this.framebuffer);
if (this.depthStencilBuffer) {
gl.deleteRenderbuffer(this.depthStencilBuffer);
}
if (this.depthBuffer) {
gl.deleteRenderbuffer(this.depthBuffer);
}
if (this.stencilBuffer) {
gl.deleteRenderbuffer(this.stencilBuffer);
}
if (this.cardboardUI) {
this.cardboardUI.destroy();
}
};
/**
* Resizes the backbuffer to match the canvas width and height.
*/
CardboardDistorter.prototype.onResize = function() {
var gl = this.gl;
var self = this;
var glState = [
gl.RENDERBUFFER_BINDING,
gl.TEXTURE_BINDING_2D, gl.TEXTURE0
];
WGLUPreserveGLState(gl, glState, function(gl) {
// Bind real backbuffer and clear it once. We don't need to clear it again
// after that because we're overwriting the same area every frame.
self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null);
// Put things in a good state
if (self.scissorTest) { self.realDisable.call(gl, gl.SCISSOR_TEST); }
self.realColorMask.call(gl, true, true, true, true);
self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
self.realClearColor.call(gl, 0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// Now bind and resize the fake backbuffer
self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.framebuffer);
gl.bindTexture(gl.TEXTURE_2D, self.renderTarget);
gl.texImage2D(gl.TEXTURE_2D, 0, self.ctxAttribs.alpha ? gl.RGBA : gl.RGB,
self.bufferWidth, self.bufferHeight, 0,
self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, self.renderTarget, 0);
if (self.ctxAttribs.depth && self.ctxAttribs.stencil) {
gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthStencilBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL,
self.bufferWidth, self.bufferHeight);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT,
gl.RENDERBUFFER, self.depthStencilBuffer);
} else if (self.ctxAttribs.depth) {
gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16,
self.bufferWidth, self.bufferHeight);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT,
gl.RENDERBUFFER, self.depthBuffer);
} else if (self.ctxAttribs.stencil) {
gl.bindRenderbuffer(gl.RENDERBUFFER, self.stencilBuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8,
self.bufferWidth, self.bufferHeight);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT,
gl.RENDERBUFFER, self.stencilBuffer);
}
if (!gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) {
console.error('Framebuffer incomplete!');
}
self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer);
if (self.scissorTest) { self.realEnable.call(gl, gl.SCISSOR_TEST); }
self.realColorMask.apply(gl, self.colorMask);
self.realViewport.apply(gl, self.viewport);
self.realClearColor.apply(gl, self.clearColor);
});
if (this.cardboardUI) {
this.cardboardUI.onResize();
}
};
CardboardDistorter.prototype.patch = function() {
if (this.isPatched) {
return;
}
var self = this;
var canvas = this.gl.canvas;
var gl = this.gl;
if (!Util.isIOS()) {
canvas.width = Util.getScreenWidth() * this.bufferScale;
canvas.height = Util.getScreenHeight() * this.bufferScale;
Object.defineProperty(canvas, 'width', {
configurable: true,
enumerable: true,
get: function() {
return self.bufferWidth;
},
set: function(value) {
self.bufferWidth = value;
self.realCanvasWidth.set.call(canvas, value);
self.onResize();
}
});
Object.defineProperty(canvas, 'height', {
configurable: true,
enumerable: true,
get: function() {
return self.bufferHeight;
},
set: function(value) {
self.bufferHeight = value;
self.realCanvasHeight.set.call(canvas, value);
self.onResize();
}
});
}
this.lastBoundFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
if (this.lastBoundFramebuffer == null) {
this.lastBoundFramebuffer = this.framebuffer;
this.gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
}
this.gl.bindFramebuffer = function(target, framebuffer) {
self.lastBoundFramebuffer = framebuffer ? framebuffer : self.framebuffer;
// Silently make calls to bind the default framebuffer bind ours instead.
self.realBindFramebuffer.call(gl, target, self.lastBoundFramebuffer);
};
this.cullFace = gl.getParameter(gl.CULL_FACE);
this.depthTest = gl.getParameter(gl.DEPTH_TEST);
this.blend = gl.getParameter(gl.BLEND);
this.scissorTest = gl.getParameter(gl.SCISSOR_TEST);
this.stencilTest = gl.getParameter(gl.STENCIL_TEST);
gl.enable = function(pname) {
switch (pname) {
case gl.CULL_FACE: self.cullFace = true; break;
case gl.DEPTH_TEST: self.depthTest = true; break;
case gl.BLEND: self.blend = true; break;
case gl.SCISSOR_TEST: self.scissorTest = true; break;
case gl.STENCIL_TEST: self.stencilTest = true; break;
}
self.realEnable.call(gl, pname);
};
gl.disable = function(pname) {
switch (pname) {
case gl.CULL_FACE: self.cullFace = false; break;
case gl.DEPTH_TEST: self.depthTest = false; break;
case gl.BLEND: self.blend = false; break;
case gl.SCISSOR_TEST: self.scissorTest = false; break;
case gl.STENCIL_TEST: self.stencilTest = false; break;
}
self.realDisable.call(gl, pname);
};
this.colorMask = gl.getParameter(gl.COLOR_WRITEMASK);
gl.colorMask = function(r, g, b, a) {
self.colorMask[0] = r;
self.colorMask[1] = g;
self.colorMask[2] = b;
self.colorMask[3] = a;
self.realColorMask.call(gl, r, g, b, a);
};
this.clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
gl.clearColor = function(r, g, b, a) {
self.clearColor[0] = r;
self.clearColor[1] = g;
self.clearColor[2] = b;
self.clearColor[3] = a;
self.realClearColor.call(gl, r, g, b, a);
};
this.viewport = gl.getParameter(gl.VIEWPORT);
gl.viewport = function(x, y, w, h) {
self.viewport[0] = x;
self.viewport[1] = y;
self.viewport[2] = w;
self.viewport[3] = h;
self.realViewport.call(gl, x, y, w, h);
};
this.isPatched = true;
Util.safariCssSizeWorkaround(canvas);
};
CardboardDistorter.prototype.unpatch = function() {
if (!this.isPatched) {
return;
}
var gl = this.gl;
var canvas = this.gl.canvas;
if (!Util.isIOS()) {
Object.defineProperty(canvas, 'width', this.realCanvasWidth);
Object.defineProperty(canvas, 'height', this.realCanvasHeight);
}
canvas.width = this.bufferWidth;
canvas.height = this.bufferHeight;
gl.bindFramebuffer = this.realBindFramebuffer;
gl.enable = this.realEnable;
gl.disable = this.realDisable;
gl.colorMask = this.realColorMask;
gl.clearColor = this.realClearColor;
gl.viewport = this.realViewport;
// Check to see if our fake backbuffer is bound and bind the real backbuffer
// if that's the case.
if (this.lastBoundFramebuffer == this.framebuffer) {
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
}
this.isPatched = false;
setTimeout(function() {
Util.safariCssSizeWorkaround(canvas);
}, 1);
};
CardboardDistorter.prototype.setTextureBounds = function(leftBounds, rightBounds) {
if (!leftBounds) {
leftBounds = [0, 0, 0.5, 1];
}
if (!rightBounds) {
rightBounds = [0.5, 0, 0.5, 1];
}
// Left eye
this.viewportOffsetScale[0] = leftBounds[0]; // X
this.viewportOffsetScale[1] = leftBounds[1]; // Y
this.viewportOffsetScale[2] = leftBounds[2]; // Width
this.viewportOffsetScale[3] = leftBounds[3]; // Height
// Right eye
this.viewportOffsetScale[4] = rightBounds[0]; // X
this.viewportOffsetScale[5] = rightBounds[1]; // Y
this.viewportOffsetScale[6] = rightBounds[2]; // Width
this.viewportOffsetScale[7] = rightBounds[3]; // Height
};
/**
* Performs distortion pass on the injected backbuffer, rendering it to the real
* backbuffer.
*/
CardboardDistorter.prototype.submitFrame = function() {
var gl = this.gl;
var self = this;
var glState = [];
if (!this.dirtySubmitFrameBindings) {
glState.push(
gl.CURRENT_PROGRAM,
gl.ARRAY_BUFFER_BINDING,
gl.ELEMENT_ARRAY_BUFFER_BINDING,
gl.TEXTURE_BINDING_2D, gl.TEXTURE0
);
}
WGLUPreserveGLState(gl, glState, function(gl) {
// Bind the real default framebuffer
self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null);
var positionDivisor = 0;
var texCoordDivisor = 0;
if (self.instanceExt) {
positionDivisor = gl.getVertexAttrib(self.attribs.position, self.instanceExt.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
texCoordDivisor = gl.getVertexAttrib(self.attribs.texCoord, self.instanceExt.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
}
// Make sure the GL state is in a good place
if (self.cullFace) { self.realDisable.call(gl, gl.CULL_FACE); }
if (self.depthTest) { self.realDisable.call(gl, gl.DEPTH_TEST); }
if (self.blend) { self.realDisable.call(gl, gl.BLEND); }
if (self.scissorTest) { self.realDisable.call(gl, gl.SCISSOR_TEST); }
if (self.stencilTest) { self.realDisable.call(gl, gl.STENCIL_TEST); }
self.realColorMask.call(gl, true, true, true, true);
self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
// If the backbuffer has an alpha channel clear every frame so the page
// doesn't show through.
if (self.ctxAttribs.alpha || Util.isIOS()) {
self.realClearColor.call(gl, 0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
}
// Bind distortion program and mesh
gl.useProgram(self.program);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer);
gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer);
gl.enableVertexAttribArray(self.attribs.position);
gl.enableVertexAttribArray(self.attribs.texCoord);
gl.vertexAttribPointer(self.attribs.position, 2, gl.FLOAT, false, 20, 0);
gl.vertexAttribPointer(self.attribs.texCoord, 3, gl.FLOAT, false, 20, 8);
if (self.instanceExt) {
if (positionDivisor != 0) {
self.instanceExt.vertexAttribDivisorANGLE(self.attribs.position, 0);
}
if (texCoordDivisor != 0) {
self.instanceExt.vertexAttribDivisorANGLE(self.attribs.texCoord, 0);
}
}
gl.activeTexture(gl.TEXTURE0);
gl.uniform1i(self.uniforms.diffuse, 0);
gl.bindTexture(gl.TEXTURE_2D, self.renderTarget);
gl.uniform4fv(self.uniforms.viewportOffsetScale, self.viewportOffsetScale);
// Draws both eyes
gl.drawElements(gl.TRIANGLES, self.indexCount, gl.UNSIGNED_SHORT, 0);
if (self.cardboardUI) {
self.cardboardUI.renderNoState();
}
// Bind the fake default framebuffer again
self.realBindFramebuffer.call(self.gl, gl.FRAMEBUFFER, self.framebuffer);
// If preserveDrawingBuffer == false clear the framebuffer
if (!self.ctxAttribs.preserveDrawingBuffer) {
self.realClearColor.call(gl, 0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
}
if (!self.dirtySubmitFrameBindings) {
self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer);
}
// Restore state
if (self.cullFace) { self.realEnable.call(gl, gl.CULL_FACE); }
if (self.depthTest) { self.realEnable.call(gl, gl.DEPTH_TEST); }
if (self.blend) { self.realEnable.call(gl, gl.BLEND); }
if (self.scissorTest) { self.realEnable.call(gl, gl.SCISSOR_TEST); }
if (self.stencilTest) { self.realEnable.call(gl, gl.STENCIL_TEST); }
self.realColorMask.apply(gl, self.colorMask);
self.realViewport.apply(gl, self.viewport);
if (self.ctxAttribs.alpha || !self.ctxAttribs.preserveDrawingBuffer) {
self.realClearColor.apply(gl, self.clearColor);
}
if (self.instanceExt) {
if (positionDivisor != 0) {
self.instanceExt.vertexAttribDivisorANGLE(self.attribs.position, positionDivisor);
}
if (texCoordDivisor != 0) {
self.instanceExt.vertexAttribDivisorANGLE(self.attribs.texCoord, texCoordDivisor);
}
}
});
// Workaround for the fact that Safari doesn't allow us to patch the canvas
// width and height correctly. After each submit frame check to see what the
// real backbuffer size has been set to and resize the fake backbuffer size
// to match.
if (Util.isIOS()) {
var canvas = gl.canvas;
if (canvas.width != self.bufferWidth || canvas.height != self.bufferHeight) {
self.bufferWidth = canvas.width;
self.bufferHeight = canvas.height;
self.onResize();
}
}
};
/**
* Call when the deviceInfo has changed. At this point we need
* to re-calculate the distortion mesh.
*/
CardboardDistorter.prototype.updateDeviceInfo = function(deviceInfo) {
var gl = this.gl;
var self = this;
var glState = [gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING];
WGLUPreserveGLState(gl, glState, function(gl) {
var vertices = self.computeMeshVertices_(self.meshWidth, self.meshHeight, deviceInfo);
gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// Indices don't change based on device parameters, so only compute once.
if (!self.indexCount) {
var indices = self.computeMeshIndices_(self.meshWidth, self.meshHeight);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
self.indexCount = indices.length;
}
});
};
/**
* Build the distortion mesh vertices.
* Based on code from the Unity cardboard plugin.
*/
CardboardDistorter.prototype.computeMeshVertices_ = function(width, height, deviceInfo) {
var vertices = new Float32Array(2 * width * height * 5);
var lensFrustum = deviceInfo.getLeftEyeVisibleTanAngles();
var noLensFrustum = deviceInfo.getLeftEyeNoLensTanAngles();
var viewport = deviceInfo.getLeftEyeVisibleScreenRect(noLensFrustum);
var vidx = 0;
var iidx = 0;
for (var e = 0; e < 2; e++) {
for (var j = 0; j < height; j++) {
for (var i = 0; i < width; i++, vidx++) {
var u = i / (width - 1);
var v = j / (height - 1);
// Grid points regularly spaced in StreoScreen, and barrel distorted in
// the mesh.
var s = u;
var t = v;
var x = Util.lerp(lensFrustum[0], lensFrustum[2], u);
var y = Util.lerp(lensFrustum[3], lensFrustum[1], v);
var d = Math.sqrt(x * x + y * y);
var r = deviceInfo.distortion.distortInverse(d);
var p = x * r / d;
var q = y * r / d;
u = (p - noLensFrustum[0]) / (noLensFrustum[2] - noLensFrustum[0]);
v = (q - noLensFrustum[3]) / (noLensFrustum[1] - noLensFrustum[3]);
// Convert u,v to mesh screen coordinates.
var aspect = deviceInfo.device.widthMeters / deviceInfo.device.heightMeters;
// FIXME: The original Unity plugin multiplied U by the aspect ratio
// and didn't multiply either value by 2, but that seems to get it
// really close to correct looking for me. I hate this kind of "Don't
// know why it works" code though, and wold love a more logical
// explanation of what needs to happen here.
u = (viewport.x + u * viewport.width - 0.5) * 2.0; //* aspect;
v = (viewport.y + v * viewport.height - 0.5) * 2.0;
vertices[(vidx * 5) + 0] = u; // position.x
vertices[(vidx * 5) + 1] = v; // position.y
vertices[(vidx * 5) + 2] = s; // texCoord.x
vertices[(vidx * 5) + 3] = t; // texCoord.y
vertices[(vidx * 5) + 4] = e; // texCoord.z (viewport index)
}
}
var w = lensFrustum[2] - lensFrustum[0];
lensFrustum[0] = -(w + lensFrustum[0]);
lensFrustum[2] = w - lensFrustum[2];
w = noLensFrustum[2] - noLensFrustum[0];
noLensFrustum[0] = -(w + noLensFrustum[0]);
noLensFrustum[2] = w - noLensFrustum[2];
viewport.x = 1 - (viewport.x + viewport.width);
}
return vertices;
}
/**
* Build the distortion mesh indices.
* Based on code from the Unity cardboard plugin.
*/
CardboardDistorter.prototype.computeMeshIndices_ = function(width, height) {
var indices = new Uint16Array(2 * (width - 1) * (height - 1) * 6);
var halfwidth = width / 2;
var halfheight = height / 2;
var vidx = 0;
var iidx = 0;
for (var e = 0; e < 2; e++) {
for (var j = 0; j < height; j++) {
for (var i = 0; i < width; i++, vidx++) {
if (i == 0 || j == 0)
continue;
// Build a quad. Lower right and upper left quadrants have quads with
// the triangle diagonal flipped to get the vignette to interpolate
// correctly.
if ((i <= halfwidth) == (j <= halfheight)) {
// Quad diagonal lower left to upper right.
indices[iidx++] = vidx;
indices[iidx++] = vidx - width - 1;
indices[iidx++] = vidx - width;
indices[iidx++] = vidx - width - 1;
indices[iidx++] = vidx;
indices[iidx++] = vidx - 1;
} else {
// Quad diagonal upper left to lower right.
indices[iidx++] = vidx - 1;
indices[iidx++] = vidx - width;
indices[iidx++] = vidx;
indices[iidx++] = vidx - width;
indices[iidx++] = vidx - 1;
indices[iidx++] = vidx - width - 1;
}
}
}
}
return indices;
};
CardboardDistorter.prototype.getOwnPropertyDescriptor_ = function(proto, attrName) {
var descriptor = Object.getOwnPropertyDescriptor(proto, attrName);
// In some cases (ahem... Safari), the descriptor returns undefined get and
// set fields. In this case, we need to create a synthetic property
// descriptor. This works around some of the issues in
// https://github.com/borismus/webvr-polyfill/issues/46
if (descriptor.get === undefined || descriptor.set === undefined) {
descriptor.configurable = true;
descriptor.enumerable = true;
descriptor.get = function() {
return this.getAttribute(attrName);
};
descriptor.set = function(val) {
this.setAttribute(attrName, val);
};
}
return descriptor;
};
export default CardboardDistorter;