在没有 GPU 的情况下以无头 chrome 渲染 WebGL 图像
Posted
技术标签:
【中文标题】在没有 GPU 的情况下以无头 chrome 渲染 WebGL 图像【英文标题】:Rendering WebGL image in headless chrome without a GPU 【发布时间】:2018-06-09 05:53:54 【问题描述】:我正在尝试在没有 GPU 的 Linux 服务器上导出使用 WebGL 渲染的图像。为此,我使用的是无头 Chrome,但导出的图像是黑色的(example exported image、taking a screenshot of page shows its just canvas that is black)。我希望有人帮助我弄清楚为什么会发生这种情况。
要导出图像,我将图像渲染到画布中,通过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 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 傀儡师:0.13.0 节点: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
【问题讨论】:
你能提供更多关于你的硬件配置的细节吗? AFAIK,WebGL 确实需要 GPU。许多(大多数?)最近的计算机确实包含英特尔“集成图形”形式的 GPU,如果您不过度推动它们,这对于 3D 渲染来说绰绰有余,但是没有 GPU 访问权限的 VM 将是一个问题。 .. 我们的服务器没有 GPU。有很多文档表明它是可能的:“SwiftShader 是基于 CPU 的高性能 OpenGL ES 实现”(github.com/google/swiftshader)blog.chromium.org/2016/06/…。添加 Swiftshader bugs.chromium.org/p/chromium/issues/detail?id=630728 的 Chromium 问题。 Chromium 文档讨论 GPU 不可用时的软件合成器chromium.org/developers/design-documents/… 你真的安装了 Swiftshader 吗?在您的帖子中没有看到任何关于此的内容?另外,你有办法捕获 Chrome 的控制台吗? 将 --disable-gpu 传递给我的 chrome 选项允许我呈现一个 html 画布饼图。非常感谢您的提示! 我运行的服务(无浏览器)似乎没有 WebGL 的问题(除了速度慢,但这完全取决于您分配的资源)。你可以看一个例子here。 【参考方案1】:我通过添加解决了这个问题
'--use-gl=angle'
到无头镀铬设置。
我还删除了'--disable-gpu'
,因为我认为这是修复一些错误的临时解决方法,不再需要。
您可以在 Chrome 源代码中找到与“角度”here 不同的选项(在 Chrome 源代码中找到这个是我最不希望看到的!)
【讨论】:
【参考方案2】:将preserveDrawingBuffer
设置为true
为我解决了这个问题
【讨论】:
【参考方案3】:有一个未解决的错误会影响没有 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。
【讨论】:
首先,感谢您的帮助!我安装了 deps 并检查了它们是否可以动态加载,但问题仍然存在(gist.github.com/jhollingworth/24c57fe654d5f9b591d577281c7992c4)。我在带有 GPU 日志记录的 chromium 调试版本中运行了一个简单的 WebGL 示例 (gist.github.com/jhollingworth/f9bae6a65be1f61eadc4c538c5ed983c):gist.github.com/jhollingworth/0b1843dc4417fd282d238cb6ef46628b。GL_RENDERER = Google SwiftShader
和 GL_VERSION = OpenGL ES 3.0 SwiftShader 3.3.0.2
。我假设这意味着 Swiftshader 已加载?对我可以尝试的其他事情有什么想法吗?
我想知道的一件事是,每次调用toDataUrl()
的时间从 30 毫秒到 500 毫秒不等,具体取决于场景的复杂性(例如,加载图像然后转换它比gl.clearColor
花费的时间要长得多)。对我来说,这意味着正在执行 OpenGL 命令(gl.getError
每次都返回 NONE
),但无论出于何种原因,WebGL 都没有真正绘制到画布中。我不知道你对此有什么想法?
这方面有更新吗?我面临同样的问题:***.com/questions/61239552/…
只是为了更新:这个例子似乎在 MacOS 下运行良好。同时,我可以通过禁用抗锯齿来解决 unity3D webgl 问题。【参考方案4】:
所以我通过将premultipliedAlpha
设置为false 部分解决了这个问题。当它为真(默认)时,toDataURL
将返回一个空图像。如果为 false,则返回渲染图像。
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" ></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
是真还是假,我都可以看到渲染的图像。
【讨论】:
我还发现了 Headless Chrome 中 Swiftshader 的一个问题,可能与此 bugs.chromium.org/p/swiftshader/issues/detail?id=92 如何在 headless chrome 中将图像(上面的 dataURL)保存到 png 中?【参考方案5】:如果你想在服务器上运行它并且那里没有可用的 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 渲染。
我建议在这里查看接受的答案:how to force chrome to use mesa software driver for webgl 我很确定它会解决您的问题
【讨论】:
Chrome 已经为 CPU 提供了一个 OpenGL ES 实现,称为 SwiftShader,当没有 GPU 或被列入黑名单时,它用作 WebGL 的后备。它在许多情况下都能正常工作,但显然 James 发现了一个影响特定无头设置的错误。【参考方案6】:我不知道这是否可以帮助您,但是您可以在创建 WebGL 上下文时设置一些选项。根据浏览器的实现,你可以有不同的默认值。
您是否尝试强制 preserveDrawingBuffer 为 true ?
var gl = canvas.getContext( "webgl",
preserveDrawingBuffer: true
);
MDN 对此选项的评价如下:
preserveDrawingBuffer:如果值为 true,则缓冲区不会被清除,并且会保留其值,直到被作者清除或覆盖。
【讨论】:
感谢您的想法,但遗憾的是没有帮助以上是关于在没有 GPU 的情况下以无头 chrome 渲染 WebGL 图像的主要内容,如果未能解决你的问题,请参考以下文章
Chrome 浏览器无头问题:没有这样的元素:无法在 chrome://downloads/ 找到元素 [重复]