繁体   English   中英

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

[英]Rendering WebGL image in headless chrome without a GPU

我正在尝试在没有 GPU 的 linux 服务器上导出使用 WebGL 渲染的图像。 为此,我使用了无头 Chrome,但导出的图像是黑色的(例如导出的图像截取页面的屏幕截图显示其只是黑色的画布)。 我希望得到一些帮助来弄清楚为什么会发生这种情况。

为了导出图像,我将图像渲染到画布中,通过canvas.toDataURL('image/jpeg')导出数据,然后将数据发布到服务器。 我使用 Pixi.js 进行渲染,如果我使用画布渲染器,那么一切都在服务器上运行; 这是 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 的作者在 6 月表示,无头 WebGL 渲染是可能的,并且似乎已被 Chromium 问题证实,所以我想我遗漏了一些东西。 有没有人知道我做错了什么?

我尝试过的几件事:

  • 不传入--disable-gpu
  • --use-gl=swiftshader-webgl , --use-gl=swiftshader , --use-gl=osmesa
  • 全屏截图,看看它是否只是画布。 整个屏幕都是黑色的。

版本

  • 铬:linux-515411
  • 傀儡师:0.13.0
  • 节点:8.2.1
  • Linux:CentOS 7

这是我需要在我的服务器上安装才能运行 chrome 的东西( 来源

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

有一个开放的错误会影响没有 X11 库的系统: crbug.com/swiftshader/79 它会阻止 Chrome OS 与 SwiftShader 一起运行,但同样的问题也会发生在不支持 X11 的无头 Linux 系统上。

幸运的是,安装 X11 并运行起来应该是可行的。 我不是 100% 确定哪些包提供了必要的库,但试试这些: xorg xserver-xorg xvfb libx11-dev libxext-dev libxext-dev:i386

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

所以我通过将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是真还是假。

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

您是否尝试过将preserveDrawingBuffer强制为true

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

以下是MDN关于此选项的说明:

preserveDrawingBuffer :如果值为真,缓冲区将不会被清除,并将保留它们的值,直到被作者清除或覆盖。

如果你想在服务器上运行它并且那里没有可用的 GPU,你需要使用一些东西来代替它。

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

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

我建议在这里检查接受的答案: 如何强制 chrome 使用 mesa 软件驱动程序用于 webgl我很确定它会解决您的问题

preserveDrawingBuffer设置为true为我解决了这个问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM