Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Commit e05071e

Browse files
committed
When in XRSession and bindFramebuffer gets null frameBufferObject, use the XRWebGLLayer FBO instead
1 parent 8895240 commit e05071e

File tree

2 files changed

+120
-68
lines changed

2 files changed

+120
-68
lines changed

Assets/WebGLTemplates/WebXR/webxr.js

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434
this.vrImmersiveRefSpace = null;
3535
this.xrInlineRefSpace = null;
3636
this.rAFCB = null;
37-
this.originalWidth = null;
38-
this.originalHeight = null;
3937
this.init();
4038
}
4139

@@ -55,8 +53,9 @@
5553
XRManager.prototype.resize = function () {
5654
if (!this.canvas) return;
5755

58-
this.canvas.width = window.innerWidth;
59-
this.canvas.height = window.innerHeight;
56+
// TODO: The webxr script is bound to the full window view css style, need to allow more styles
57+
this.canvas.width = window.innerWidth * window.devicePixelRatio;
58+
this.canvas.height = window.innerHeight * window.devicePixelRatio;
6059
this.gameContainer.style.transform = '';
6160
}
6261

@@ -106,8 +105,8 @@
106105
this.gameInstance.SendMessage(this.unityObjectName, 'OnEndXR');
107106
this.isInVRSession = false;
108107
this.notifiedStartToUnity = false;
109-
this.canvas.width = this.originalWidth;
110-
this.canvas.height = this.originalHeight;
108+
this.canvas.width = window.innerWidth * window.devicePixelRatio;
109+
this.canvas.height = window.innerHeight * window.devicePixelRatio;
111110
}
112111

113112
XRManager.prototype.toggleVR = function () {
@@ -152,6 +151,7 @@
152151
} else if (thisXRMananger.inlineSession) {
153152
return thisXRMananger.inlineSession.requestAnimationFrame((time, xrFrame) =>
154153
{
154+
thisXRMananger.animate(time, xrFrame);
155155
if (func) {
156156
func(time);
157157
}
@@ -160,6 +160,24 @@
160160
window.requestAnimationFrame(func);
161161
}
162162
};
163+
164+
// When using Unity's URP, it tends to call bindFrameBuffer with null frameBufferObject.
165+
// In WebGL it means to draw to the canvas FBO.
166+
// Some platforms consider that when in XR and draw to the XRWebGLLayer FBO when getting null FBO,
167+
// others needs to explicitly get the XRWebGLLayer FBO instead of null.
168+
this.ctx.bindFramebuffer = (oldBindFramebuffer => function bindFramebuffer(target, fbo) {
169+
if (!fbo) {
170+
if (thisXRMananger.vrSession && thisXRMananger.isInVRSession) {
171+
if (thisXRMananger.vrSession.renderState.baseLayer) {
172+
fbo = thisXRMananger.vrSession.renderState.baseLayer.framebuffer;
173+
}
174+
} else if (thisXRMananger.inlineSession &&
175+
thisXRMananger.inlineSession.renderState.baseLayer) {
176+
fbo = thisXRMananger.inlineSession.renderState.baseLayer.framebuffer;
177+
}
178+
}
179+
return oldBindFramebuffer.call(this, target, fbo);
180+
})(this.ctx.bindFramebuffer);
163181
}
164182
}
165183

@@ -228,24 +246,25 @@
228246
for (let source of frame.session.inputSources) {
229247
if (source.gripSpace && source.gamepad) {
230248
let sourcePose = frame.getPose(source.gripSpace, refSpace);
231-
232-
var position = sourcePose.transform.position;
233-
var orientation = sourcePose.transform.orientation;
234-
235-
// Structure of this corresponds with WebXRControllerData.cs
236-
gamepads.push({
237-
id: source.gamepad.id,
238-
index: source.gamepad.index,
239-
hand: source.handedness,
240-
buttons: this.getGamepadButtons(source.gamepad),
241-
axes: this.getGamepadAxes(source.gamepad),
242-
hasOrientation: true,
243-
hasPosition: true,
244-
orientation: this.GLQuaternionToUnity([orientation.x, orientation.y, orientation.z, orientation.w]),
245-
position: this.GLVec3ToUnity([position.x, position.y, position.z]),
246-
linearAcceleration: [0, 0, 0],
247-
linearVelocity: [0, 0, 0]
248-
});
249+
if (sourcePose) {
250+
var position = sourcePose.transform.position;
251+
var orientation = sourcePose.transform.orientation;
252+
253+
// Structure of this corresponds with WebXRControllerData.cs
254+
gamepads.push({
255+
id: source.gamepad.id,
256+
index: source.gamepad.index,
257+
hand: source.handedness,
258+
buttons: this.getGamepadButtons(source.gamepad),
259+
axes: this.getGamepadAxes(source.gamepad),
260+
hasOrientation: true,
261+
hasPosition: true,
262+
orientation: this.GLQuaternionToUnity([orientation.x, orientation.y, orientation.z, orientation.w]),
263+
position: this.GLVec3ToUnity([position.x, position.y, position.z]),
264+
linearAcceleration: [0, 0, 0],
265+
linearVelocity: [0, 0, 0]
266+
});
267+
}
249268
}
250269
}
251270
return gamepads;
@@ -295,8 +314,6 @@
295314
let refSpaceType = 'viewer';
296315
if (session.isImmersive){
297316
refSpaceType = 'local-floor';
298-
this.originalWidth = this.canvas.width;
299-
this.originalHeight = this.canvas.height;
300317
this.canvas.width = glLayer.framebufferWidth;
301318
this.canvas.height = glLayer.framebufferHeight;
302319
}
@@ -315,7 +332,23 @@
315332
XRManager.prototype.animate = function (t, frame) {
316333
let session = frame.session;
317334

318-
if (!session && !session.isImmersive)
335+
if (!session)
336+
{
337+
return;
338+
}
339+
340+
let glLayer = session.renderState.baseLayer;
341+
if (this.canvas.width != glLayer.framebufferWidth ||
342+
this.canvas.height != glLayer.framebufferHeight)
343+
{
344+
this.canvas.width = glLayer.framebufferWidth;
345+
this.canvas.height = glLayer.framebufferHeight;
346+
}
347+
348+
this.ctx.bindFramebuffer(this.ctx.FRAMEBUFFER, glLayer.framebuffer);
349+
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT);
350+
351+
if (!session.isImmersive)
319352
{
320353
return;
321354
}
@@ -326,13 +359,6 @@
326359
if (!pose) {
327360
return;
328361
}
329-
330-
let glLayer = session.renderState.baseLayer;
331-
this.canvas.width = glLayer.framebufferWidth;
332-
this.canvas.height = glLayer.framebufferHeight;
333-
334-
this.ctx.bindFramebuffer(this.ctx.FRAMEBUFFER, glLayer.framebuffer);
335-
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT);
336362

337363
var xrData = this.xrData;
338364

Build/webxr.js

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434
this.vrImmersiveRefSpace = null;
3535
this.xrInlineRefSpace = null;
3636
this.rAFCB = null;
37-
this.originalWidth = null;
38-
this.originalHeight = null;
3937
this.init();
4038
}
4139

@@ -55,8 +53,9 @@
5553
XRManager.prototype.resize = function () {
5654
if (!this.canvas) return;
5755

58-
this.canvas.width = window.innerWidth;
59-
this.canvas.height = window.innerHeight;
56+
// TODO: The webxr script is bound to the full window view css style, need to allow more styles
57+
this.canvas.width = window.innerWidth * window.devicePixelRatio;
58+
this.canvas.height = window.innerHeight * window.devicePixelRatio;
6059
this.gameContainer.style.transform = '';
6160
}
6261

@@ -106,8 +105,8 @@
106105
this.gameInstance.SendMessage(this.unityObjectName, 'OnEndXR');
107106
this.isInVRSession = false;
108107
this.notifiedStartToUnity = false;
109-
this.canvas.width = this.originalWidth;
110-
this.canvas.height = this.originalHeight;
108+
this.canvas.width = window.innerWidth * window.devicePixelRatio;
109+
this.canvas.height = window.innerHeight * window.devicePixelRatio;
111110
}
112111

113112
XRManager.prototype.toggleVR = function () {
@@ -152,6 +151,7 @@
152151
} else if (thisXRMananger.inlineSession) {
153152
return thisXRMananger.inlineSession.requestAnimationFrame((time, xrFrame) =>
154153
{
154+
thisXRMananger.animate(time, xrFrame);
155155
if (func) {
156156
func(time);
157157
}
@@ -160,6 +160,24 @@
160160
window.requestAnimationFrame(func);
161161
}
162162
};
163+
164+
// When using Unity's URP, it tends to call bindFrameBuffer with null frameBufferObject.
165+
// In WebGL it means to draw to the canvas FBO.
166+
// Some platforms consider that when in XR and draw to the XRWebGLLayer FBO when getting null FBO,
167+
// others needs to explicitly get the XRWebGLLayer FBO instead of null.
168+
this.ctx.bindFramebuffer = (oldBindFramebuffer => function bindFramebuffer(target, fbo) {
169+
if (!fbo) {
170+
if (thisXRMananger.vrSession && thisXRMananger.isInVRSession) {
171+
if (thisXRMananger.vrSession.renderState.baseLayer) {
172+
fbo = thisXRMananger.vrSession.renderState.baseLayer.framebuffer;
173+
}
174+
} else if (thisXRMananger.inlineSession &&
175+
thisXRMananger.inlineSession.renderState.baseLayer) {
176+
fbo = thisXRMananger.inlineSession.renderState.baseLayer.framebuffer;
177+
}
178+
}
179+
return oldBindFramebuffer.call(this, target, fbo);
180+
})(this.ctx.bindFramebuffer);
163181
}
164182
}
165183

@@ -228,24 +246,25 @@
228246
for (let source of frame.session.inputSources) {
229247
if (source.gripSpace && source.gamepad) {
230248
let sourcePose = frame.getPose(source.gripSpace, refSpace);
231-
232-
var position = sourcePose.transform.position;
233-
var orientation = sourcePose.transform.orientation;
234-
235-
// Structure of this corresponds with WebXRControllerData.cs
236-
gamepads.push({
237-
id: source.gamepad.id,
238-
index: source.gamepad.index,
239-
hand: source.handedness,
240-
buttons: this.getGamepadButtons(source.gamepad),
241-
axes: this.getGamepadAxes(source.gamepad),
242-
hasOrientation: true,
243-
hasPosition: true,
244-
orientation: this.GLQuaternionToUnity([orientation.x, orientation.y, orientation.z, orientation.w]),
245-
position: this.GLVec3ToUnity([position.x, position.y, position.z]),
246-
linearAcceleration: [0, 0, 0],
247-
linearVelocity: [0, 0, 0]
248-
});
249+
if (sourcePose) {
250+
var position = sourcePose.transform.position;
251+
var orientation = sourcePose.transform.orientation;
252+
253+
// Structure of this corresponds with WebXRControllerData.cs
254+
gamepads.push({
255+
id: source.gamepad.id,
256+
index: source.gamepad.index,
257+
hand: source.handedness,
258+
buttons: this.getGamepadButtons(source.gamepad),
259+
axes: this.getGamepadAxes(source.gamepad),
260+
hasOrientation: true,
261+
hasPosition: true,
262+
orientation: this.GLQuaternionToUnity([orientation.x, orientation.y, orientation.z, orientation.w]),
263+
position: this.GLVec3ToUnity([position.x, position.y, position.z]),
264+
linearAcceleration: [0, 0, 0],
265+
linearVelocity: [0, 0, 0]
266+
});
267+
}
249268
}
250269
}
251270
return gamepads;
@@ -295,8 +314,6 @@
295314
let refSpaceType = 'viewer';
296315
if (session.isImmersive){
297316
refSpaceType = 'local-floor';
298-
this.originalWidth = this.canvas.width;
299-
this.originalHeight = this.canvas.height;
300317
this.canvas.width = glLayer.framebufferWidth;
301318
this.canvas.height = glLayer.framebufferHeight;
302319
}
@@ -315,7 +332,23 @@
315332
XRManager.prototype.animate = function (t, frame) {
316333
let session = frame.session;
317334

318-
if (!session && !session.isImmersive)
335+
if (!session)
336+
{
337+
return;
338+
}
339+
340+
let glLayer = session.renderState.baseLayer;
341+
if (this.canvas.width != glLayer.framebufferWidth ||
342+
this.canvas.height != glLayer.framebufferHeight)
343+
{
344+
this.canvas.width = glLayer.framebufferWidth;
345+
this.canvas.height = glLayer.framebufferHeight;
346+
}
347+
348+
this.ctx.bindFramebuffer(this.ctx.FRAMEBUFFER, glLayer.framebuffer);
349+
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT);
350+
351+
if (!session.isImmersive)
319352
{
320353
return;
321354
}
@@ -326,13 +359,6 @@
326359
if (!pose) {
327360
return;
328361
}
329-
330-
let glLayer = session.renderState.baseLayer;
331-
this.canvas.width = glLayer.framebufferWidth;
332-
this.canvas.height = glLayer.framebufferHeight;
333-
334-
this.ctx.bindFramebuffer(this.ctx.FRAMEBUFFER, glLayer.framebuffer);
335-
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT);
336362

337363
var xrData = this.xrData;
338364

0 commit comments

Comments
 (0)