pyrender 配置问题汇总

本文总结一下 pyrender 的配置以及在 Ubuntu Linux 中遇到的问题。

安装

参考:

首先建立虚拟环境,然后建议安装一个稍微老的版本:

pip install pyrender==0.1.39

问题稍少一些。

问题及配置

NOTE:下面这两个问题都是在 Ubuntu/Linux 中遇到的,在 Mac OS 中没有遇到过。

配置 pyrender OSMesa 环境

如果在 Linux 中使用 pyrender 的 OffscreenRender 功能时,你很可能会遇到如下问题:

ValueError: Failed to initialize Pyglet window with an OpenGL >= 3+ context. If you're logged in via SSH, ensure that you're running your script with vglrun (i.e. VirtualGL). The internal error message was "Cannot connect to "None""

问题的原因是 pyrender 的 OffscreenRender 功能和 Pyglet 出现冲突,而在 Server 端我们还必须要使用它的 OffscreenRender 的功能。

问题的解决方法就是配置 pyrender 官网提到 OSMesa 环境。

1. 配置 pyrender 的 OSMesa 环境

具体参见官网链接一步一步走:Getting Pyrender Working with OSMesa。它一共有两个步骤。

(1) Installing OSMesa

这个建议采用官网给出的 Building From Source 方法。其中几个细节:

  • 可以用 mesa-18.3.3 版本不变;
  • PREFIX 安装路径建议换一个自定义的路径,不过记得使用绝对路径,例如/home/username/dev/mesa_install
  • 记得最后按要求更新 ~/.bashrc;

(2) Installing a Compatible Fork of PyOpenGL

这里给出的 repo 链接没法用,正确的其实是 https://github.com/mmatl/pyopengl。clone 后,注意在该路径的外部使用 pip install ./pyopengl

不过,似乎这一步做不做并不影响 pyrender OSMesa 的使用。不太确定。

2. 修改 pyrender 代码

在你的 pyrender python 代码的最开头加上:

import os
os.environ["PYOPENGL_PLATFORM"] = "osmesa"

这样 pyrender 的 OffscreenRender 功能应该就可以正常运行了。经测试应该没有问题。

解决 render textured mesh 时的问题

参考:

上面一个问题解决后,应该可以渲染 untextured mesh。但是,如果你要渲染 textured mesh,还是可能会遇到一个问题,类似这样:

...
  File "/usr/local/lib/python2.7/dist-packages/OpenGL/error.py", line 232, in glCheckError
    baseOperation = baseOperation,
OpenGL.error.GLError: GLError(
	err = 1282,
	description = 'invalid operation',
	baseOperation = glRenderbufferStorageMultisample,
	cArguments = (GL_RENDERBUFFER, 4, GL_RGBA, 400, 400)
)

解决方法是这样:

(1) 找到 pyrender 安装路径下的 pyrender/renderer.py 文件(可以用 pip show pyrender 找到一个包的安装路径)。大概在 Line 10911096 行附近有这样一段代码:

glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA, self.viewport_width, self.viewport_height)

glBindRenderbuffer(GL_RENDERBUFFER, self._main_db_ms)

glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT24, self.viewport_width, self.viewport_height)

将其改成这样:

# 其实就是把上面的 4 替换成 num_samples,其余不变
num_samples = min(glGetIntegerv(GL_MAX_SAMPLES), 4) # No more than GL_MAX_SAMPLES

glRenderbufferStorageMultisample(GL_RENDERBUFFER, num_samples, GL_RGBA, self.viewport_width, self.viewport_height)

glBindRenderbuffer(GL_RENDERBUFFER, self._main_db_ms) # 这行不变

glRenderbufferStorageMultisample(GL_RENDERBUFFER, num_samples, GL_DEPTH_COMPONENT24, self.viewport_width, self.viewport_height)

(2) 上面改完后,你应该不会有错误了,但是可能会得到空白图片结果(汗死)。此时检查 offscreen.py 代码后,可以发现,RenderFlags.OFFSCREEN 已经自动加上了,因此,在 OffscreenRender 模式下,无需再加一遍,再加一遍反倒是会错。

if self._platform.supports_framebuffers():
    flags |= RenderFlags.OFFSCREEN
    ...
else:
   # If your platform doesn't support framebuffers, it cannot render with `RenderFlags.OFFSCREEN`.
    ...

因此,你的代码中,显示定义的 flags 此时不能包含 RenderFlags.OFFSCREEN。类似这样:

    r = OffscreenRenderer(viewport_width=width, viewport_height=height)
    flags = RenderFlags.SHADOWS_DIRECTIONAL # 不能包含 RenderFlags.OFFSCREEN
    color, depth = r.render(scene, flags)

此后,你应该就既没有错误,也能得到彩色图片结果了。

Search

    Table of Contents