diff --git a/tabs/magnetometer.js b/tabs/magnetometer.js index 314f29fe2..7951fb91e 100644 --- a/tabs/magnetometer.js +++ b/tabs/magnetometer.js @@ -630,15 +630,84 @@ TABS.magnetometer.initialize3D = function () { canvas = $('.model-and-info #canvas'); wrapper = $('.model-and-info #canvas_wrapper'); - // webgl capability detector - // it would seem the webgl "enabling" through advanced settings will be ignored in the future - // and webgl will be supported if gpu supports it by default (canary 40.0.2175.0), keep an eye on this one - var detector_canvas = document.createElement('canvas'); - if (window.WebGLRenderingContext && (detector_canvas.getContext('webgl') || detector_canvas.getContext('experimental-webgl'))) { - renderer = new THREE.WebGLRenderer({canvas: canvas.get(0), alpha: true, antialias: true}); - useWebGlRenderer = true; + // Robust WebGL capability detection with fallback + function tryCreateWebGLContext() { + if (!window.WebGLRenderingContext) { + return null; + } + + const detector_canvas = document.createElement('canvas'); + let gl = null; + let renderMethod = null; + + // Try 1: Hardware-accelerated WebGL (best performance) + try { + gl = detector_canvas.getContext('webgl') || detector_canvas.getContext('experimental-webgl'); + if (gl) { + renderMethod = 'hardware'; + console.log('[3D Magnetometer] Using hardware-accelerated WebGL'); + } + } catch (e) { + console.warn('[3D Magnetometer] Hardware WebGL failed:', e); + } + + // Try 2: Software-rendered WebGL (slower but more compatible) + if (!gl) { + try { + gl = detector_canvas.getContext('webgl', { failIfMajorPerformanceCaveat: false }) || + detector_canvas.getContext('experimental-webgl', { failIfMajorPerformanceCaveat: false }); + if (gl) { + renderMethod = 'software'; + console.log('[3D Magnetometer] Using software-rendered WebGL (slower performance)'); + } + } catch (e) { + console.warn('[3D Magnetometer] Software WebGL failed:', e); + } + } + + return gl ? { context: gl, method: renderMethod } : null; } - + + const webglResult = tryCreateWebGLContext(); + + if (webglResult) { + try { + renderer = new THREE.WebGLRenderer({canvas: canvas.get(0), alpha: true, antialias: true}); + useWebGlRenderer = true; + + // Show performance notice if using software rendering + if (webglResult.method === 'software') { + GUI_control.prototype.log('3D view using software rendering (slower). Consider updating graphics drivers or disabling hardware acceleration in Options.'); + } + } catch (e) { + console.error('[3D Magnetometer] Failed to create THREE.WebGLRenderer:', e); + renderer = null; + useWebGlRenderer = false; + } + } + + // Check if WebGL is available + if (!renderer) { + // WebGL not supported - show fallback message + wrapper.html('
' + + '
' + + '

3D view unavailable

' + + '

WebGL could not be initialized. This may be due to:

' + + '' + + '

Try: Options → Disable 3D Hardware Acceleration, then restart

' + + '
' + + '
'); + + // Provide no-op functions so the rest of the tab doesn't break + this.render3D = function () {}; + this.resize3D = function () {}; + return; + } + // initialize render size for current canvas size renderer.setSize(wrapper.width() * 2, wrapper.height() * 2); diff --git a/tabs/setup.js b/tabs/setup.js index cb05fee3c..4f112bd8f 100755 --- a/tabs/setup.js +++ b/tabs/setup.js @@ -225,14 +225,84 @@ TABS.setup.initialize3D = function () { canvas = $('.model-and-info #canvas'); wrapper = $('.model-and-info #canvas_wrapper'); - // webgl capability detector - // it would seem the webgl "enabling" through advanced settings will be ignored in the future - // and webgl will be supported if gpu supports it by default (canary 40.0.2175.0), keep an eye on this one - var detector_canvas = document.createElement('canvas'); - if (window.WebGLRenderingContext && (detector_canvas.getContext('webgl') || detector_canvas.getContext('experimental-webgl'))) { - renderer = new THREE.WebGLRenderer({canvas: canvas.get(0), alpha: true, antialias: true}); - useWebGlRenderer = true; + // Robust WebGL capability detection with fallback + function tryCreateWebGLContext() { + if (!window.WebGLRenderingContext) { + return null; + } + + const detector_canvas = document.createElement('canvas'); + let gl = null; + let renderMethod = null; + + // Try 1: Hardware-accelerated WebGL (best performance) + try { + gl = detector_canvas.getContext('webgl') || detector_canvas.getContext('experimental-webgl'); + if (gl) { + renderMethod = 'hardware'; + console.log('[3D] Using hardware-accelerated WebGL'); + } + } catch (e) { + console.warn('[3D] Hardware WebGL failed:', e); + } + + // Try 2: Software-rendered WebGL (slower but more compatible) + if (!gl) { + try { + gl = detector_canvas.getContext('webgl', { failIfMajorPerformanceCaveat: false }) || + detector_canvas.getContext('experimental-webgl', { failIfMajorPerformanceCaveat: false }); + if (gl) { + renderMethod = 'software'; + console.log('[3D] Using software-rendered WebGL (slower performance)'); + } + } catch (e) { + console.warn('[3D] Software WebGL failed:', e); + } + } + + return gl ? { context: gl, method: renderMethod } : null; } + + const webglResult = tryCreateWebGLContext(); + + if (webglResult) { + try { + renderer = new THREE.WebGLRenderer({canvas: canvas.get(0), alpha: true, antialias: true}); + useWebGlRenderer = true; + + // Show performance notice if using software rendering + if (webglResult.method === 'software') { + GUI.log('3D view using software rendering (slower). Consider updating graphics drivers or disabling hardware acceleration in Options.'); + } + } catch (e) { + console.error('[3D] Failed to create THREE.WebGLRenderer:', e); + renderer = null; + useWebGlRenderer = false; + } + } + + // Check if WebGL is available + if (!renderer) { + // WebGL not supported - show fallback message + wrapper.html('
' + + '
' + + '

3D view unavailable

' + + '

WebGL could not be initialized. This may be due to:

' + + '' + + '

Try: Options → Disable 3D Hardware Acceleration, then restart

' + + '
' + + '
'); + + // Provide no-op functions so the rest of the tab doesn't break + this.render3D = function () {}; + this.resize3D = function () {}; + return; + } + // initialize render size for current canvas size renderer.setSize(wrapper.width()*2, wrapper.height()*2);