在没有GPU的无头镀铬中渲染WebGL图像

时间:2017-12-28 17:15:58

标签: javascript google-chrome webgl pixi.js puppeteer

我正在尝试在没有GPU的Linux服务器上导出使用WebGL渲染的图像。为此,我使用无头Chrome,但导出的图像为黑色(example exported imagetaking a screenshot of page shows its just canvas that is black)。我希望得到一些帮助,弄清楚为什么会发生这种情况。

要导出图像,我将图像渲染到画布中,通过canvas.toDataURL('image/jpeg')导出数据,然后将数据发布到服务器。我正在使用Pixi.js进行渲染,如果我使用canvas渲染器,那么一切都可以在服务器上运行;它的WebGL渲染不起作用。值得注意的是,WebGL渲染在Macbook上的Chrome 63中运行良好。

要控制Chrome,我正在使用Puppeteer。我正在做的就是打开一个页面,等待一秒钟,然后再次关闭它:

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));
    });
  })

这是puppeteer传递给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'
]

swiftshader author said in June headless WebGL rendering is possible似乎是confirmed by this Chromium issue所以我想我错过了一些东西。有没有人知道我做错了什么?

我尝试了几件事:

  • Not passing in --disable-gpu
  • --use-gl=swiftshader-webgl--use-gl=swiftshader--use-gl=osmesa
  • 拍摄全屏截图,看看它是否只是画布。整个屏幕只是黑色。

版本

  • Chrome:linux-515411
  • puppeteer:0.13.0
  • node:8.2.1
  • Linux:CentOS 7

这是我需要在我的服务器上安装才能运行chrome(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

5 个答案:

答案 0 :(得分:6)

所以我通过将premultipliedAlpha设置为false来部分解决了这个问题。当它为真(默认)时,toDataURL将返回一个空图像。如果为false,则返回渲染图像。

<!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>

有趣的是,如果我使用puppeteer截取屏幕截图,无论premultipliedAlpha是真还是假,我都可以看到渲染的图像。

答案 1 :(得分:5)

有一个开放的bug会影响没有X11库的系统:crbug.com/swiftshader/79。它阻止Chrome操作系统与SwiftShader一起运行,但是在没有X11支持的无头Linux系统上也会出现同样的问题。

幸运的是,安装X11并使其运行应该是可行的。我不是100%确定哪些软件包提供了必要的库,但请尝试以下方法:xorg xserver-xorg xvfb libx11-dev libxext-dev libxext-dev:i386

最终将修复SwiftShader错误,因此它不需要任何X11。

答案 2 :(得分:1)

如果你想在服务器上运行它并且没有可用的GPU,你需要使用一些东西而不是它。

WebGL 1.0基于OpenGL ES 2.0规范,该规范基于OpenGL 2.1规范。有Mesa库(https://en.wikipedia.org/wiki/Mesa_(computer_graphics)),它实现了软件渲染器,用于供应商验证OpenGL实现。我认为它支持OpenGL高达3.1,但我可能错了,现在它支持更高版本。

可以在* nix中安装Mesa作为驱动程序,并使用软件实现进行OpenGL渲染。

我建议您在此处查看已接受的答案:how to force chrome to use mesa software driver for webgl我非常确定它会解决您的问题

答案 3 :(得分:0)

我不知道这是否对您有所帮助,但您可以在创建WebGL上下文时设置选项。根据浏览器的实现,您可以使用不同的默认值。

您是否尝试将 preserveDrawingBuffer 强制为 true

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

以下是MDN对此选项的说法:

  

preserveDrawingBuffer :如果值为true,则不会清除缓冲区并保留其值,直到作者清除或覆盖为止。

答案 4 :(得分:0)

preserveDrawingBuffer设置为true可以为我解决问题