|
"""Wrapper for offscreen rendering. |
|
|
|
Author: Matthew Matl |
|
""" |
|
import os |
|
|
|
from .renderer import Renderer |
|
from .constants import RenderFlags |
|
|
|
|
|
class OffscreenRenderer(object): |
|
"""A wrapper for offscreen rendering. |
|
|
|
Parameters |
|
---------- |
|
viewport_width : int |
|
The width of the main viewport, in pixels. |
|
viewport_height : int |
|
The height of the main viewport, in pixels. |
|
point_size : float |
|
The size of screen-space points in pixels. |
|
""" |
|
|
|
def __init__(self, viewport_width, viewport_height, point_size=1.0): |
|
self.viewport_width = viewport_width |
|
self.viewport_height = viewport_height |
|
self.point_size = point_size |
|
|
|
self._platform = None |
|
self._renderer = None |
|
self._create() |
|
|
|
@property |
|
def viewport_width(self): |
|
"""int : The width of the main viewport, in pixels. |
|
""" |
|
return self._viewport_width |
|
|
|
@viewport_width.setter |
|
def viewport_width(self, value): |
|
self._viewport_width = int(value) |
|
|
|
@property |
|
def viewport_height(self): |
|
"""int : The height of the main viewport, in pixels. |
|
""" |
|
return self._viewport_height |
|
|
|
@viewport_height.setter |
|
def viewport_height(self, value): |
|
self._viewport_height = int(value) |
|
|
|
@property |
|
def point_size(self): |
|
"""float : The pixel size of points in point clouds. |
|
""" |
|
return self._point_size |
|
|
|
@point_size.setter |
|
def point_size(self, value): |
|
self._point_size = float(value) |
|
|
|
def render(self, scene, flags=RenderFlags.NONE, seg_node_map=None): |
|
"""Render a scene with the given set of flags. |
|
|
|
Parameters |
|
---------- |
|
scene : :class:`Scene` |
|
A scene to render. |
|
flags : int |
|
A bitwise or of one or more flags from :class:`.RenderFlags`. |
|
seg_node_map : dict |
|
A map from :class:`.Node` objects to (3,) colors for each. |
|
If specified along with flags set to :attr:`.RenderFlags.SEG`, |
|
the color image will be a segmentation image. |
|
|
|
Returns |
|
------- |
|
color_im : (h, w, 3) uint8 or (h, w, 4) uint8 |
|
The color buffer in RGB format, or in RGBA format if |
|
:attr:`.RenderFlags.RGBA` is set. |
|
Not returned if flags includes :attr:`.RenderFlags.DEPTH_ONLY`. |
|
depth_im : (h, w) float32 |
|
The depth buffer in linear units. |
|
""" |
|
self._platform.make_current() |
|
|
|
|
|
if (self._platform.viewport_height != self.viewport_height or |
|
self._platform.viewport_width != self.viewport_width): |
|
if not self._platform.supports_framebuffers(): |
|
self.delete() |
|
self._create() |
|
|
|
self._platform.make_current() |
|
self._renderer.viewport_width = self.viewport_width |
|
self._renderer.viewport_height = self.viewport_height |
|
self._renderer.point_size = self.point_size |
|
|
|
if self._platform.supports_framebuffers(): |
|
flags |= RenderFlags.OFFSCREEN |
|
retval = self._renderer.render(scene, flags, seg_node_map) |
|
else: |
|
self._renderer.render(scene, flags, seg_node_map) |
|
depth = self._renderer.read_depth_buf() |
|
if flags & RenderFlags.DEPTH_ONLY: |
|
retval = depth |
|
else: |
|
color = self._renderer.read_color_buf() |
|
retval = color, depth |
|
|
|
|
|
self._platform.make_uncurrent() |
|
return retval |
|
|
|
def delete(self): |
|
"""Free all OpenGL resources. |
|
""" |
|
self._platform.make_current() |
|
self._renderer.delete() |
|
self._platform.delete_context() |
|
del self._renderer |
|
del self._platform |
|
self._renderer = None |
|
self._platform = None |
|
import gc |
|
gc.collect() |
|
|
|
def _create(self): |
|
if 'PYOPENGL_PLATFORM' not in os.environ: |
|
from pyrender.platforms.pyglet_platform import PygletPlatform |
|
self._platform = PygletPlatform(self.viewport_width, |
|
self.viewport_height) |
|
elif os.environ['PYOPENGL_PLATFORM'] == 'egl': |
|
from pyrender.platforms import egl |
|
device_id = int(os.environ.get('EGL_DEVICE_ID', '0')) |
|
egl_device = egl.get_device_by_index(device_id) |
|
self._platform = egl.EGLPlatform(self.viewport_width, |
|
self.viewport_height, |
|
device=egl_device) |
|
elif os.environ['PYOPENGL_PLATFORM'] == 'osmesa': |
|
from pyrender.platforms.osmesa import OSMesaPlatform |
|
self._platform = OSMesaPlatform(self.viewport_width, |
|
self.viewport_height) |
|
else: |
|
raise ValueError('Unsupported PyOpenGL platform: {}'.format( |
|
os.environ['PYOPENGL_PLATFORM'] |
|
)) |
|
self._platform.init_context() |
|
self._platform.make_current() |
|
self._renderer = Renderer(self.viewport_width, self.viewport_height) |
|
|
|
def __del__(self): |
|
try: |
|
self.delete() |
|
except Exception: |
|
pass |
|
|
|
|
|
__all__ = ['OffscreenRenderer'] |
|
|