web-dev-qa-db-fra.com

Moyen correct de détecter le support WebGL?

J'essaie de détecter la prise en charge de WebGL sur plusieurs navigateurs et j'ai rencontré le scénario suivant. La version actuelle de Firefox semble signaler un support positif en utilisant la vérification suivante, même lorsque la carte vidéo du visiteur est sur liste noire et/ou que WebGL est désactivé:

if (window.WebGLRenderingContext) {
    // This is true in Firefox under certain circumstances,
    // even when WebGL is disabled...
}

J'ai essayé de demander à mes utilisateurs d'activer WebGL en procédant comme suit. Cela a fonctionné dans certains cas, mais pas toujours. Évidemment, ce n'est pas quelque chose que je peux demander au grand public:

  1. Tapez about: config} _ dans la barre d’adresse de Firefox
  2. Pour activer WebGL, définissez webgl.force-enabled} sur true.

Cela m’a amené à créer ma propre méthode de détection du support, qui utilise jQuery pour injecter un élément de canevas afin de détecter le support. Cela fait appel à un certain nombre de techniques que j'ai trouvées dans diverses bibliothèques et plugins WebGL. Le problème, c’est qu’il est extrêmement difficile à tester (tout commentaire sur le fonctionnement du lien ci-dessous est très apprécié!). Pour en faire une question objective, j'aimerais savoir s'il existe un moyen universellement accepté de détecter la prise en charge de WebGL par tous les navigateurs.

URL de test:

http://jsfiddle.net/Jn49q/5/

49
Derek Hunziker

[Oct 2014] J'ai mis à jour l'exemple de modernizrs pour qu'il corresponde à leur implémentation actuelle , qui est une version nettoyée de http://get.webgl.org/ plus loin.

Modernizr fait,

var canvas;
var ctx;
var exts;

try {
  canvas = createElement('canvas');
  ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
  exts = ctx.getSupportedExtensions();
}
catch (e) {
  return;
}

if (ctx !== undefined) {
  Modernizr.webglextensions = new Boolean(true);
}

for (var i = -1, len = exts.length; ++i < len; ){
  Modernizr.webglextensions[exts[i]] = true;
}

canvas = undefined;

Chromium pointe vers http://get.webgl.org/ pour l'implémentation du support canonique, 

try { gl = canvas.getContext("webgl"); }
catch (x) { gl = null; }

if (gl == null) {
    try { gl = canvas.getContext("experimental-webgl"); experimental = true; }
    catch (x) { gl = null; }
}
34
Andrew

L’excellente bibliothèque Three possède en effet un mécanisme permettant de détecter les éléments suivants: 

  1. Support WebGL
  2. Prise en charge de l'API de fichier
  3. Soutien des travailleurs

Pour WebGL, en particulier, voici le code utilisé:

function webgl_support () { 
   try {
    var canvas = document.createElement('canvas'); 
    return !!window.WebGLRenderingContext &&
      (canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
   } catch(e) {
     return false;
   }
 };

Cet extrait de code fait partie d’une classe Detector qui peut également afficher les messages d’erreur correspondants à l’utilisateur.

32
oabarca

Comme on le voit dans http://www.browserleaks.com/webgl#howto-detect-webgl

Il s'agit d'une fonction javascript appropriée pour détecter la prise en charge de WebGL, avec toutes sortes de noms de contextes WebGL expérimentaux et avec la vérification de cas particuliers, tels que le blocage de fonctions WebGL par NoScript ou TorBrowser.

Il signalera l'un des trois états de capacité WebGL:

  • WebGL est activé - renvoie VRAI ou retourne 
  • Objet WebGL, si le premier argument a été passé
  • WebGL est désactivé - retournez FALSE, vous pouvez le changer si vous avez besoin de>
  • WebGL n'est pas implémenté - retourne FALSE
function webgl_detect(return_context)
{
    if (!!window.WebGLRenderingContext) {
        var canvas = document.createElement("canvas"),
             names = ["webgl2", "webgl", "experimental-webgl", "moz-webgl", "webkit-3d"],
           context = false;

        for(var i=0;i< names.length;i++) {
            try {
                context = canvas.getContext(names[i]);
                if (context && typeof context.getParameter == "function") {
                    // WebGL is enabled
                    if (return_context) {
                        // return WebGL object if the function's argument is present
                        return {name:names[i], gl:context};
                    }
                    // else, return just true
                    return true;
                }
            } catch(e) {}
        }

        // WebGL is supported, but disabled
        return false;
    }

    // WebGL not supported
    return false;
}
18
Juan Arias

En plus de @Andrew answer, il existe également un mode expérimental qui peut être pris en charge. J'ai écrit l'extrait de code suivant:

var canvasID = 'webgl',
    canvas = document.getElementById(canvasID),
    gl,
    glExperimental = false;

function hasWebGL() {

    try { gl = canvas.getContext("webgl"); }
    catch (x) { gl = null; }

    if (gl === null) {
        try { gl = canvas.getContext("experimental-webgl"); glExperimental = true; }
        catch (x) { gl = null; }
    }

    if(gl) { return true; }
    else if ("WebGLRenderingContext" in window) { return true; } // not a best way, as you're not 100% sure, so you can change it to false
    else { return false; }
}

Changez la variable canvasID en fonction de votre ID.

Testé sur Chrome, Safari, Firefox, Opera et IE (8 à 10). Dans le cas de Safari, rappelez-vous qu'il est disponible, mais vous devez activer WebGL explicitement (activez le menu du développeur et activez l'option Web GL après).

8
Karol

Afin de détecter les navigateurs prenant en charge WebGL, mais en laissant de côté les anciens navigateurs, la prise en charge risque de ne pas être prise en charge correctement (si nécessaire dans WebGL est détecté comme étant pris en charge alors qu'il n'est pas utilisé pour éliminer les appareils Android 4.4.2), j'ajoute un contrôle plus étroit, bien que non lié:

function hasWebGL() {
    var supported;

    try {
        var canvas = document.createElement('canvas');
        supported = !! window.WebGLRenderingContext && (canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
    } catch(e) { supported = false; }

    try {
        // let is by no means required, but will help us rule out some old browsers/devices with potentially buggy implementations: http://caniuse.com/#feat=let
        eval('let foo = 123;');
    } catch (e) { supported = false; }

    if (supported === false) {
        console.log("WebGL is not supported");
    }

    canvas = undefined;

    return supported;
},
2
Jose Gómez
// this code will detect WebGL version until WebGL Version maxVersionTest 
var
maxVersionTest = 5,
canvas = document.createElement('canvas'),
webglVersion = (canvas.getContext('webgl') || canvas.getContext('experimental-webgl')) ? 1 : null,
canvas = null; // free context

// range: if maxVersionTest = 5 makes [5, 4, 3, 2]
Array.apply(null, Array(maxVersionTest - 1))
.map(function (_, idx) {return idx + 2;})
.reverse()
.some(function(version){
    // cant reuse canvas, potential to exceed contexts or mem limit *
    if (document.createElement('canvas').getContext('webgl'+version))
        return !!(webglVersion = version);
});

console.log(webglVersion);

* re "potentiel de dépasser les contextes ou la limite de mémoire" voir https://bugs.chromium.org/p/chromium/issues/detail?id=226868

1
ekerner

De MDN :

// Run everything inside window load event handler, to make sure
// DOM is fully loaded and styled before trying to manipulate it.
window.addEventListener("load", function() {
  var paragraph = document.querySelector("p"),
    button = document.querySelector("button");
  // Adding click event handler to button.
  button.addEventListener("click", detectWebGLContext, false);
  function detectWebGLContext () {
    // Create canvas element. The canvas is not added to the
    // document itself, so it is never displayed in the
    // browser window.
    var canvas = document.createElement("canvas");
    // Get WebGLRenderingContext from canvas element.
    var gl = canvas.getContext("webgl")
      || canvas.getContext("experimental-webgl");
    // Report the result.
    if (gl && gl instanceof WebGLRenderingContext) {
      paragraph.innerHTML =
        "Congratulations! Your browser supports WebGL.";
    } else {
      paragraph.innerHTML = "Failed to get WebGL context. "
        + "Your browser or device may not support WebGL.";
    }
  }
}, false);
body {
  text-align : center;
}
button {
  display : block;
  font-size : inherit;
  margin : auto;
  padding : 0.6em;
}
<p>[ Here would go the result of WebGL feature detection ]</p>
<button>Press here to detect WebGLRenderingContext</button>

0
Tomasz Mularczyk