web-dev-qa-db-fra.com

Rendu d'une image WebGL en chrome sans tête, sans GPU

J'essaie d'exporter une image rendue avec WebGL sur un serveur Linux sans GPU. Pour ce faire, j'utilise un Chrome sans tête, mais l'image exportée est en noir ( exemple d'image exportée , en prenant une capture d'écran de la page, il affiche uniquement le canevas noir ). J'espérais un peu d'aide pour comprendre pourquoi cela se produit.

Pour exporter l'image, je la restitue dans un canevas, exportez des données via canvas.toDataURL('image/jpeg'), puis publiez-les sur le serveur. J'utilise Pixi.js pour le rendu, si j'utilise canvas renderer, tout fonctionne sur le serveur. C'est le rendu WebGL qui ne fonctionne pas. Il convient de noter que le rendu WebGL fonctionne correctement dans Chrome 63 sur un Macbook.

Pour contrôler Chrome, j'utilise Puppeteer . Je ne fais qu'ouvrir une page, attendre une seconde, puis la refermer:

puppeteer
  .launch({
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
    ],
  })
  .then(browser => {
    return browser.newPage().then(page => {
      return page
        .goto(url)
        .then(() => page.waitFor(1000))
        .then(() => browser.close())
        .catch(err => console.error('Failed', err));
    });
  })

Voici les arguments que le marionnettiste transmet à Chrome:

[
  '--disable-background-networking',
  '--disable-background-timer-throttling',
  '--disable-client-side-phishing-detection',
  '--disable-default-apps',
  '--disable-extensions',
  '--disable-hang-monitor',
  '--disable-popup-blocking',
  '--disable-Prompt-on-repost',
  '--disable-sync',
  '--disable-translate',
  '--metrics-recording-only',
  '--no-first-run',
  '--remote-debugging-port=0',
  '--safebrowsing-disable-auto-update',
  '--enable-automation',
  '--password-store=basic',
  '--use-mock-keychain',
  '--user-data-dir=/tmp/puppeteer_dev_profile-GhEAXZ',
  '--headless',
  '--disable-gpu',
  '--hide-scrollbars',
  '--mute-audio',
  '--no-sandbox',
  '--disable-setuid-sandbox'
]

L’auteur swiftshader a déclaré en juin que le rendu WebGL sans tête est possible et il semble être confirmé par ce numéro de Chromium donc je suppose que je manque quelque chose. Quelqu'un a-t-il une idée de ce que je fais mal?

Quelques choses que j'ai essayées:

  • Ne pas passer --disable-gpu
  • --use-gl=swiftshader-webgl, --use-gl=swiftshader, --use-gl=osmesa
  • Prendre une capture d'écran en plein écran pour voir si c'est juste une toile. Tout l'écran est juste noir.

Les versions

  • Chrome: linux-515411
  • marionnettiste: 0.13.0
  • noeud: 8.2.1
  • Linux: CentOS 7

C’est ce que j’avais besoin d’installer sur mon serveur pour que chrome s’exécute ( Source )

yum install cups-libs dbus-glib libXrandr libXcursor libXinerama cairo cairo-gobject pango ffmpeg
rpm -ivh --nodeps http://mirror.centos.org/centos/7/os/x86_64/Packages/atk-2.22.0-3.el7.x86_64.rpm
rpm -ivh --nodeps http://mirror.centos.org/centos/7/os/x86_64/Packages/at-spi2-atk-2.22.0-2.el7.x86_64.rpm
rpm -ivh --nodeps http://mirror.centos.org/centos/7/os/x86_64/Packages/at-spi2-core-2.22.0-1.el7.x86_64.rpm
rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/Fedora/linux/releases/20/Fedora/x86_64/os/Packages/g/GConf2-3.2.6-7.fc20.x86_64.rpm
rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/Fedora/linux/releases/20/Fedora/x86_64/os/Packages/l/libXScrnSaver-1.2.2-6.fc20.x86_64.rpm
rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/Fedora/linux/releases/20/Fedora/x86_64/os/Packages/l/libxkbcommon-0.3.1-1.fc20.x86_64.rpm
rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/Fedora/linux/releases/20/Fedora/x86_64/os/Packages/l/libwayland-client-1.2.0-3.fc20.x86_64.rpm
rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/Fedora/linux/releases/20/Fedora/x86_64/os/Packages/l/libwayland-cursor-1.2.0-3.fc20.x86_64.rpm
rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/Fedora/linux/releases/20/Fedora/x86_64/os/Packages/g/gtk3-3.10.4-1.fc20.x86_64.rpm
rpm -ivh --nodeps http://dl.fedoraproject.org/pub/archive/Fedora/linux/releases/16/Fedora/x86_64/os/Packages/gdk-pixbuf2-2.24.0-1.fc16.x86_64.rpm
22
James Hollingworth

J'ai donc partiellement résolu le problème en définissant premultipliedAlpha sur false. Quand c'est vrai (par défaut), toDataURL retournera une image vide. Lorsque la valeur est false, l'image renvoyée est renvoyée. 

<!DOCTYPE html>
<html>
<body>
  <canvas id="canvas" width="1080" height="1080"></canvas>
  <script type="text/javascript">
    var canvas = document.getElementById('canvas');
    var gl = canvas.getContext('webgl', {
        premultipliedAlpha: false
    });

    gl.viewportWidth = canvas.width;
    gl.viewportHeight = canvas.height;
    gl.clearColor(0.99, 0, 1, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);

    var IMAGE_PREFIX = 'data:image/png;base64,';
    var image = canvas.toDataURL('image/png').substring(IMAGE_PREFIX.length);

    // save(image)
  </script>
</body>
</html>

Ce qui est intéressant, c’est que si je prends une capture d’écran en utilisant puppeteer, je peux voir l’image rendue, que premultipliedAlpha soit vrai ou faux.

6
James Hollingworth

Un bogue ouvert affecte les systèmes dépourvus de bibliothèques X11: crbug.com/swiftshader/79 . Cela empêche Chrome OS de fonctionner avec SwiftShader, mais le même problème se produirait également sur un système Linux sans tête qui ne prend pas en charge X11.

Heureusement, il devrait être possible d'installer X11 et de faire fonctionner les choses. Je ne suis pas sûr à 100% des paquets qui fournissent les bibliothèques nécessaires, mais essayez ceux-ci: xorg xserver-xorg xvfb libx11-dev libxext-dev libxext-dev:i386

Finalement, le bogue SwiftShader sera corrigé afin qu'il ne nécessite absolument pas X11.

5
Nicolas Capens

Si vous voulez l'exécuter sur le serveur et qu'aucun GPU n'y est disponible, vous devez utiliser quelque chose à la place.

WebGL 1.0 est basé sur la spécification OpenGL ES 2.0, basée sur la spécification OpenGL 2.1. Il existe une bibliothèque Mesa ( https://en.wikipedia.org/wiki/Mesa_(computer_graphics) ), qui implémente le rendu du logiciel et est utilisée pour la validation de l'implémentation OpenGL par les fournisseurs. Je pense qu’il supporte OpenGL jusqu’à la version 3.1, mais je peux me tromper et il prend maintenant en charge une version encore plus haute.

Il est possible d'installer Mesa en tant que pilote dans * nix et de le faire effectuer un rendu OpenGL à l'aide de la mise en œuvre logicielle. 

Je suggère de vérifier la réponse acceptée ici: comment forcer Chrome à utiliser le pilote logiciel Mesa pour Webgl Je suis sûr que cela résoudra votre problème.

1
Dmitry Tolmachov

Je ne sais pas si cela peut vous aider, mais vous pouvez définir des options lors de la création d'un contexte WebGL. Selon l'implémentation du navigateur, vous pouvez avoir différentes valeurs par défaut.

Avez-vous essayé de forcer preserveDrawingBuffer à true?

var gl = canvas.getContext( "webgl", {
    preserveDrawingBuffer: true
});

Voici ce que MDN dit à propos de cette option:

preserveDrawingBuffer: si la valeur est true, les tampons ne seront pas effacés et conserveront leurs valeurs jusqu'à ce qu'ils soient effacés ou remplacés par l'auteur.

0
Tolokoban