|
@@ -184,8 +184,8 @@
|
|
|
public textureLOD: boolean;
|
|
|
public drawBuffersExtension;
|
|
|
}
|
|
|
-
|
|
|
- export interface EngineOptions extends WebGLContextAttributes{
|
|
|
+
|
|
|
+ export interface EngineOptions extends WebGLContextAttributes {
|
|
|
limitDeviceRatio?: number;
|
|
|
}
|
|
|
|
|
@@ -311,6 +311,17 @@
|
|
|
public enableOfflineSupport = true;
|
|
|
public scenes = new Array<Scene>();
|
|
|
|
|
|
+ //WebVR
|
|
|
+
|
|
|
+ //The new WebVR uses promises.
|
|
|
+ //this promise resolves with the current devices available.
|
|
|
+ public vrDisplaysPromise;
|
|
|
+
|
|
|
+ private _vrDisplays;
|
|
|
+ private _vrDisplayEnabled;
|
|
|
+ private _oldSize: BABYLON.Size;
|
|
|
+ private _oldHardwareScaleFactor: number;
|
|
|
+
|
|
|
// Private Members
|
|
|
public _gl: WebGLRenderingContext;
|
|
|
private _renderingCanvas: HTMLCanvasElement;
|
|
@@ -328,7 +339,7 @@
|
|
|
private _caps: EngineCapabilities;
|
|
|
private _pointerLockRequested: boolean;
|
|
|
private _alphaTest: boolean;
|
|
|
- private _isStencilEnable: boolean;
|
|
|
+ private _isStencilEnable: boolean;
|
|
|
|
|
|
private _loadingScreen: ILoadingScreen;
|
|
|
|
|
@@ -382,7 +393,7 @@
|
|
|
|
|
|
private _externalData: StringDictionary<Object>;
|
|
|
private _bindedRenderFunction: any;
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* @constructor
|
|
|
* @param {HTMLCanvasElement} canvas - the canvas to be used for rendering
|
|
@@ -396,7 +407,7 @@
|
|
|
|
|
|
options = options || {};
|
|
|
|
|
|
- if(antialias != null){
|
|
|
+ if (antialias != null) {
|
|
|
options.antialias = antialias;
|
|
|
}
|
|
|
|
|
@@ -552,6 +563,9 @@
|
|
|
//default loading screen
|
|
|
this._loadingScreen = new DefaultLoadingScreen(this._renderingCanvas);
|
|
|
|
|
|
+ //Load WebVR Devices
|
|
|
+ this._getVRDisplays();
|
|
|
+
|
|
|
Tools.Log("Babylon.js engine (v" + Engine.Version + ") launched");
|
|
|
}
|
|
|
|
|
@@ -698,11 +712,11 @@
|
|
|
public setStencilFunction(stencilFunc: number) {
|
|
|
this._stencilState.stencilFunc = stencilFunc;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public setStencilFunctionReference(reference: number) {
|
|
|
this._stencilState.stencilFuncRef = reference;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public setStencilFunctionMask(mask: number) {
|
|
|
this._stencilState.stencilFuncMask = mask;
|
|
|
}
|
|
@@ -770,7 +784,7 @@
|
|
|
|
|
|
if (this._activeRenderLoops.length > 0) {
|
|
|
// Register new frame
|
|
|
- Tools.QueueNewFrame(this._bindedRenderFunction);
|
|
|
+ Tools.QueueNewFrame(this._bindedRenderFunction, this._getFrameRequester());
|
|
|
} else {
|
|
|
this._renderingQueueLaunched = false;
|
|
|
}
|
|
@@ -803,19 +817,19 @@
|
|
|
* @param {boolean} requestPointerLock - should a pointer lock be requested from the user
|
|
|
* @param {any} options - an options object to be sent to the requestFullscreen function
|
|
|
*/
|
|
|
- public switchFullscreen(requestPointerLock: boolean, options?: any): void {
|
|
|
+ public switchFullscreen(requestPointerLock: boolean): void {
|
|
|
if (this.isFullscreen) {
|
|
|
- Tools.ExitFullscreen();
|
|
|
+ Tools.ExitFullscreen(this._vrDisplayEnabled);
|
|
|
} else {
|
|
|
this._pointerLockRequested = requestPointerLock;
|
|
|
- Tools.RequestFullscreen(this._renderingCanvas, options);
|
|
|
+ Tools.RequestFullscreen(this._renderingCanvas, this._vrDisplayEnabled);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public clear(color: any, backBuffer: boolean, depth: boolean, stencil:boolean = false): void {
|
|
|
+ public clear(color: any, backBuffer: boolean, depth: boolean, stencil: boolean = false): void {
|
|
|
this.applyStates();
|
|
|
|
|
|
- var mode = 0;
|
|
|
+ var mode = 0;
|
|
|
if (backBuffer) {
|
|
|
this._gl.clearColor(color.r, color.g, color.b, color.a !== undefined ? color.a : 1.0);
|
|
|
mode |= this._gl.COLOR_BUFFER_BIT;
|
|
@@ -892,6 +906,11 @@
|
|
|
|
|
|
public endFrame(): void {
|
|
|
//this.flushFramebuffer();
|
|
|
+
|
|
|
+ //submit frame to the vr device, if enabled
|
|
|
+ if(this._vrDisplayEnabled && this._vrDisplayEnabled.isPresenting) {
|
|
|
+ this._vrDisplayEnabled.submitFrame()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -935,14 +954,73 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ //WebVR functions
|
|
|
+
|
|
|
+ public enableVR(vrDevice) {
|
|
|
+ this._vrDisplayEnabled = vrDevice;
|
|
|
+ window.addEventListener('vrdisplaypresentchange', this._onVRFullScreenTriggered, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ public disableVR() {
|
|
|
+ if (this._vrDisplayEnabled) {
|
|
|
+ this._vrDisplayEnabled = null;
|
|
|
+ window.removeEventListener('vrdisplaypresentchange', this._onVRFullScreenTriggered, false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private _onVRFullScreenTriggered = () => {
|
|
|
+ if (this._vrDisplayEnabled && this._vrDisplayEnabled.isPresenting) {
|
|
|
+ //get the old size before we change
|
|
|
+ this._oldSize = new BABYLON.Size(this.getRenderWidth(), this.getRenderHeight());
|
|
|
+ this._oldHardwareScaleFactor = this.getHardwareScalingLevel();
|
|
|
+
|
|
|
+ //get the width and height, change the render size
|
|
|
+ var leftEye = this._vrDisplayEnabled.getEyeParameters('left');
|
|
|
+ var width, height;
|
|
|
+ this.setHardwareScalingLevel(1);
|
|
|
+ this.setSize(leftEye.renderWidth * 2, leftEye.renderHeight);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ this.setHardwareScalingLevel(this._oldHardwareScaleFactor);
|
|
|
+ this.setSize(this._oldSize.width, this._oldSize.height);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private _getFrameRequester() {
|
|
|
+ if (this._vrDisplayEnabled && this._vrDisplayEnabled.isPresenting) {
|
|
|
+ return this._vrDisplayEnabled;
|
|
|
+ } else {
|
|
|
+ return window;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private _getVRDisplays() {
|
|
|
+ var getWebVRDevices = (devices: Array<any>) => {
|
|
|
+ var size = devices.length;
|
|
|
+ var i = 0;
|
|
|
+
|
|
|
+ this._vrDisplays = devices.filter(function (device) {
|
|
|
+ return devices[i] instanceof VRDisplay;
|
|
|
+ });
|
|
|
+
|
|
|
+ return this._vrDisplays;
|
|
|
+ }
|
|
|
+
|
|
|
+ //using a key due to typescript
|
|
|
+ if (navigator.getVRDisplays) {
|
|
|
+ this.vrDisplaysPromise = navigator.getVRDisplays().then(getWebVRDevices);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public bindFramebuffer(texture: WebGLTexture, faceIndex?: number, requiredWidth?: number, requiredHeight?: number): void {
|
|
|
this._currentRenderTarget = texture;
|
|
|
this.bindUnboundFramebuffer(texture._framebuffer);
|
|
|
var gl = this._gl;
|
|
|
if (texture.isCube) {
|
|
|
-
|
|
|
+
|
|
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture, 0);
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
gl.viewport(0, 0, requiredWidth || texture._width, requiredHeight || texture._height);
|
|
|
|
|
@@ -1134,12 +1212,12 @@
|
|
|
var offset = 0;
|
|
|
for (var index = 0; index < attributesCount; index++) {
|
|
|
|
|
|
- if(index < vertexDeclaration.length){
|
|
|
+ if (index < vertexDeclaration.length) {
|
|
|
|
|
|
var order = effect.getAttributeLocation(index);
|
|
|
|
|
|
if (order >= 0) {
|
|
|
- if(!this._vertexAttribArraysEnabled[order]){
|
|
|
+ if (!this._vertexAttribArraysEnabled[order]) {
|
|
|
this._gl.enableVertexAttribArray(order);
|
|
|
this._vertexAttribArraysEnabled[order] = true;
|
|
|
}
|
|
@@ -1148,11 +1226,11 @@
|
|
|
|
|
|
offset += vertexDeclaration[index] * 4;
|
|
|
|
|
|
- }else{
|
|
|
+ } else {
|
|
|
|
|
|
//disable effect attributes that have no data
|
|
|
var order = effect.getAttributeLocation(index);
|
|
|
- if(this._vertexAttribArraysEnabled[order]){
|
|
|
+ if (this._vertexAttribArraysEnabled[order]) {
|
|
|
this._gl.disableVertexAttribArray(order);
|
|
|
this._vertexAttribArraysEnabled[order] = false;
|
|
|
}
|
|
@@ -1183,14 +1261,14 @@
|
|
|
var vertexBuffer = vertexBuffers[attributes[index]];
|
|
|
|
|
|
if (!vertexBuffer) {
|
|
|
- if(this._vertexAttribArraysEnabled[order]){
|
|
|
+ if (this._vertexAttribArraysEnabled[order]) {
|
|
|
this._gl.disableVertexAttribArray(order);
|
|
|
this._vertexAttribArraysEnabled[order] = false;
|
|
|
}
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- if(!this._vertexAttribArraysEnabled[order]){
|
|
|
+ if (!this._vertexAttribArraysEnabled[order]) {
|
|
|
this._gl.enableVertexAttribArray(order);
|
|
|
this._vertexAttribArraysEnabled[order] = true;
|
|
|
}
|
|
@@ -1269,7 +1347,7 @@
|
|
|
for (let i = 0; i < offsetLocations.length; i++) {
|
|
|
let ai = <InstancingAttributeInfo>offsetLocations[i];
|
|
|
|
|
|
- if(!this._vertexAttribArraysEnabled[ai.index]){
|
|
|
+ if (!this._vertexAttribArraysEnabled[ai.index]) {
|
|
|
this._gl.enableVertexAttribArray(ai.index);
|
|
|
this._vertexAttribArraysEnabled[ai.index] = true;
|
|
|
}
|
|
@@ -1283,7 +1361,7 @@
|
|
|
for (let index = 0; index < 4; index++) {
|
|
|
let offsetLocation = <number>offsetLocations[index];
|
|
|
|
|
|
- if(!this._vertexAttribArraysEnabled[offsetLocation]){
|
|
|
+ if (!this._vertexAttribArraysEnabled[offsetLocation]) {
|
|
|
this._gl.enableVertexAttribArray(offsetLocation);
|
|
|
this._vertexAttribArraysEnabled[offsetLocation] = true;
|
|
|
}
|
|
@@ -2104,7 +2182,7 @@
|
|
|
this.bindUnboundFramebuffer(framebuffer);
|
|
|
|
|
|
// Manage attachments
|
|
|
- if (generateStencilBuffer) {
|
|
|
+ if (generateStencilBuffer) {
|
|
|
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
|
|
|
}
|
|
|
else if (generateDepthBuffer) {
|
|
@@ -2134,7 +2212,7 @@
|
|
|
texture.references = 1;
|
|
|
texture.samplingMode = samplingMode;
|
|
|
texture.type = type;
|
|
|
-
|
|
|
+
|
|
|
this.resetTextureCache();
|
|
|
|
|
|
this._loadedTexturesCache.push(texture);
|
|
@@ -2201,7 +2279,7 @@
|
|
|
this.bindUnboundFramebuffer(framebuffer);
|
|
|
|
|
|
// Manage attachments
|
|
|
- if (generateStencilBuffer) {
|
|
|
+ if (generateStencilBuffer) {
|
|
|
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencilBuffer);
|
|
|
}
|
|
|
else if (generateDepthBuffer) {
|
|
@@ -2768,6 +2846,9 @@
|
|
|
|
|
|
this._gl = null;
|
|
|
|
|
|
+ //WebVR
|
|
|
+ this.disableVR();
|
|
|
+
|
|
|
// Events
|
|
|
window.removeEventListener("blur", this._onBlur);
|
|
|
window.removeEventListener("focus", this._onFocus);
|