pyrender-maintained 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyrender/__init__.py +24 -0
- pyrender/camera.py +435 -0
- pyrender/constants.py +149 -0
- pyrender/font.py +272 -0
- pyrender/light.py +382 -0
- pyrender/material.py +705 -0
- pyrender/mesh.py +328 -0
- pyrender/node.py +263 -0
- pyrender/offscreen.py +160 -0
- pyrender/platforms/__init__.py +6 -0
- pyrender/platforms/base.py +73 -0
- pyrender/platforms/egl.py +219 -0
- pyrender/platforms/osmesa.py +59 -0
- pyrender/platforms/pyglet_platform.py +90 -0
- pyrender/primitive.py +489 -0
- pyrender/renderer.py +1328 -0
- pyrender/sampler.py +102 -0
- pyrender/scene.py +585 -0
- pyrender/shader_program.py +283 -0
- pyrender/texture.py +259 -0
- pyrender/trackball.py +216 -0
- pyrender/utils.py +115 -0
- pyrender/version.py +1 -0
- pyrender/viewer.py +1157 -0
- pyrender_maintained-1.0.0.dist-info/METADATA +55 -0
- pyrender_maintained-1.0.0.dist-info/RECORD +29 -0
- pyrender_maintained-1.0.0.dist-info/WHEEL +5 -0
- pyrender_maintained-1.0.0.dist-info/licenses/LICENSE +21 -0
- pyrender_maintained-1.0.0.dist-info/top_level.txt +1 -0
pyrender/offscreen.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Wrapper for offscreen rendering.
|
|
2
|
+
|
|
3
|
+
Author: Matthew Matl
|
|
4
|
+
"""
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
from .renderer import Renderer
|
|
8
|
+
from .constants import RenderFlags
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class OffscreenRenderer(object):
|
|
12
|
+
"""A wrapper for offscreen rendering.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
viewport_width : int
|
|
17
|
+
The width of the main viewport, in pixels.
|
|
18
|
+
viewport_height : int
|
|
19
|
+
The height of the main viewport, in pixels.
|
|
20
|
+
point_size : float
|
|
21
|
+
The size of screen-space points in pixels.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, viewport_width, viewport_height, point_size=1.0):
|
|
25
|
+
self.viewport_width = viewport_width
|
|
26
|
+
self.viewport_height = viewport_height
|
|
27
|
+
self.point_size = point_size
|
|
28
|
+
|
|
29
|
+
self._platform = None
|
|
30
|
+
self._renderer = None
|
|
31
|
+
self._create()
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def viewport_width(self):
|
|
35
|
+
"""int : The width of the main viewport, in pixels.
|
|
36
|
+
"""
|
|
37
|
+
return self._viewport_width
|
|
38
|
+
|
|
39
|
+
@viewport_width.setter
|
|
40
|
+
def viewport_width(self, value):
|
|
41
|
+
self._viewport_width = int(value)
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def viewport_height(self):
|
|
45
|
+
"""int : The height of the main viewport, in pixels.
|
|
46
|
+
"""
|
|
47
|
+
return self._viewport_height
|
|
48
|
+
|
|
49
|
+
@viewport_height.setter
|
|
50
|
+
def viewport_height(self, value):
|
|
51
|
+
self._viewport_height = int(value)
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def point_size(self):
|
|
55
|
+
"""float : The pixel size of points in point clouds.
|
|
56
|
+
"""
|
|
57
|
+
return self._point_size
|
|
58
|
+
|
|
59
|
+
@point_size.setter
|
|
60
|
+
def point_size(self, value):
|
|
61
|
+
self._point_size = float(value)
|
|
62
|
+
|
|
63
|
+
def render(self, scene, flags=RenderFlags.NONE, seg_node_map=None):
|
|
64
|
+
"""Render a scene with the given set of flags.
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
scene : :class:`Scene`
|
|
69
|
+
A scene to render.
|
|
70
|
+
flags : int
|
|
71
|
+
A bitwise or of one or more flags from :class:`.RenderFlags`.
|
|
72
|
+
seg_node_map : dict
|
|
73
|
+
A map from :class:`.Node` objects to (3,) colors for each.
|
|
74
|
+
If specified along with flags set to :attr:`.RenderFlags.SEG`,
|
|
75
|
+
the color image will be a segmentation image.
|
|
76
|
+
|
|
77
|
+
Returns
|
|
78
|
+
-------
|
|
79
|
+
color_im : (h, w, 3) uint8 or (h, w, 4) uint8
|
|
80
|
+
The color buffer in RGB format, or in RGBA format if
|
|
81
|
+
:attr:`.RenderFlags.RGBA` is set.
|
|
82
|
+
Not returned if flags includes :attr:`.RenderFlags.DEPTH_ONLY`.
|
|
83
|
+
depth_im : (h, w) float32
|
|
84
|
+
The depth buffer in linear units.
|
|
85
|
+
"""
|
|
86
|
+
self._platform.make_current()
|
|
87
|
+
# If platform does not support dynamically-resizing framebuffers,
|
|
88
|
+
# destroy it and restart it
|
|
89
|
+
if (self._platform.viewport_height != self.viewport_height or
|
|
90
|
+
self._platform.viewport_width != self.viewport_width):
|
|
91
|
+
if not self._platform.supports_framebuffers():
|
|
92
|
+
self.delete()
|
|
93
|
+
self._create()
|
|
94
|
+
|
|
95
|
+
self._platform.make_current()
|
|
96
|
+
self._renderer.viewport_width = self.viewport_width
|
|
97
|
+
self._renderer.viewport_height = self.viewport_height
|
|
98
|
+
self._renderer.point_size = self.point_size
|
|
99
|
+
|
|
100
|
+
if self._platform.supports_framebuffers():
|
|
101
|
+
flags |= RenderFlags.OFFSCREEN
|
|
102
|
+
retval = self._renderer.render(scene, flags, seg_node_map)
|
|
103
|
+
else:
|
|
104
|
+
self._renderer.render(scene, flags, seg_node_map)
|
|
105
|
+
depth = self._renderer.read_depth_buf()
|
|
106
|
+
if flags & RenderFlags.DEPTH_ONLY:
|
|
107
|
+
retval = depth
|
|
108
|
+
else:
|
|
109
|
+
color = self._renderer.read_color_buf()
|
|
110
|
+
retval = color, depth
|
|
111
|
+
|
|
112
|
+
# Make the platform not current
|
|
113
|
+
self._platform.make_uncurrent()
|
|
114
|
+
return retval
|
|
115
|
+
|
|
116
|
+
def delete(self):
|
|
117
|
+
"""Free all OpenGL resources.
|
|
118
|
+
"""
|
|
119
|
+
self._platform.make_current()
|
|
120
|
+
self._renderer.delete()
|
|
121
|
+
self._platform.delete_context()
|
|
122
|
+
del self._renderer
|
|
123
|
+
del self._platform
|
|
124
|
+
self._renderer = None
|
|
125
|
+
self._platform = None
|
|
126
|
+
import gc
|
|
127
|
+
gc.collect()
|
|
128
|
+
|
|
129
|
+
def _create(self):
|
|
130
|
+
if 'PYOPENGL_PLATFORM' not in os.environ:
|
|
131
|
+
from pyrender.platforms.pyglet_platform import PygletPlatform
|
|
132
|
+
self._platform = PygletPlatform(self.viewport_width,
|
|
133
|
+
self.viewport_height)
|
|
134
|
+
elif os.environ['PYOPENGL_PLATFORM'] == 'egl':
|
|
135
|
+
from pyrender.platforms import egl
|
|
136
|
+
device_id = int(os.environ.get('EGL_DEVICE_ID', '0'))
|
|
137
|
+
egl_device = egl.get_device_by_index(device_id)
|
|
138
|
+
self._platform = egl.EGLPlatform(self.viewport_width,
|
|
139
|
+
self.viewport_height,
|
|
140
|
+
device=egl_device)
|
|
141
|
+
elif os.environ['PYOPENGL_PLATFORM'] == 'osmesa':
|
|
142
|
+
from pyrender.platforms.osmesa import OSMesaPlatform
|
|
143
|
+
self._platform = OSMesaPlatform(self.viewport_width,
|
|
144
|
+
self.viewport_height)
|
|
145
|
+
else:
|
|
146
|
+
raise ValueError('Unsupported PyOpenGL platform: {}'.format(
|
|
147
|
+
os.environ['PYOPENGL_PLATFORM']
|
|
148
|
+
))
|
|
149
|
+
self._platform.init_context()
|
|
150
|
+
self._platform.make_current()
|
|
151
|
+
self._renderer = Renderer(self.viewport_width, self.viewport_height)
|
|
152
|
+
|
|
153
|
+
def __del__(self):
|
|
154
|
+
try:
|
|
155
|
+
self.delete()
|
|
156
|
+
except Exception:
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
__all__ = ['OffscreenRenderer']
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Platform(abc.ABC):
|
|
5
|
+
"""Base class for all OpenGL platforms.
|
|
6
|
+
|
|
7
|
+
Parameters
|
|
8
|
+
----------
|
|
9
|
+
viewport_width : int
|
|
10
|
+
The width of the main viewport, in pixels.
|
|
11
|
+
viewport_height : int
|
|
12
|
+
The height of the main viewport, in pixels
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, viewport_width, viewport_height):
|
|
16
|
+
self.viewport_width = viewport_width
|
|
17
|
+
self.viewport_height = viewport_height
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def viewport_width(self):
|
|
21
|
+
"""int : The width of the main viewport, in pixels.
|
|
22
|
+
"""
|
|
23
|
+
return self._viewport_width
|
|
24
|
+
|
|
25
|
+
@viewport_width.setter
|
|
26
|
+
def viewport_width(self, value):
|
|
27
|
+
self._viewport_width = value
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def viewport_height(self):
|
|
31
|
+
"""int : The height of the main viewport, in pixels.
|
|
32
|
+
"""
|
|
33
|
+
return self._viewport_height
|
|
34
|
+
|
|
35
|
+
@viewport_height.setter
|
|
36
|
+
def viewport_height(self, value):
|
|
37
|
+
self._viewport_height = value
|
|
38
|
+
|
|
39
|
+
@abc.abstractmethod
|
|
40
|
+
def init_context(self):
|
|
41
|
+
"""Create an OpenGL context.
|
|
42
|
+
"""
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
@abc.abstractmethod
|
|
46
|
+
def make_current(self):
|
|
47
|
+
"""Make the OpenGL context current.
|
|
48
|
+
"""
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
@abc.abstractmethod
|
|
52
|
+
def make_uncurrent(self):
|
|
53
|
+
"""Make the OpenGL context uncurrent.
|
|
54
|
+
"""
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
@abc.abstractmethod
|
|
58
|
+
def delete_context(self):
|
|
59
|
+
"""Delete the OpenGL context.
|
|
60
|
+
"""
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
@abc.abstractmethod
|
|
64
|
+
def supports_framebuffers(self):
|
|
65
|
+
"""Returns True if the method supports framebuffer rendering.
|
|
66
|
+
"""
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
def __del__(self):
|
|
70
|
+
try:
|
|
71
|
+
self.delete_context()
|
|
72
|
+
except Exception:
|
|
73
|
+
pass
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import ctypes
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
import OpenGL.platform
|
|
5
|
+
|
|
6
|
+
from .base import Platform
|
|
7
|
+
|
|
8
|
+
EGL_PLATFORM_DEVICE_EXT = 0x313F
|
|
9
|
+
EGL_DRM_DEVICE_FILE_EXT = 0x3233
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _ensure_egl_loaded():
|
|
13
|
+
plugin = OpenGL.platform.PlatformPlugin.by_name('egl')
|
|
14
|
+
if plugin is None:
|
|
15
|
+
raise RuntimeError("EGL platform plugin is not available.")
|
|
16
|
+
|
|
17
|
+
plugin_class = plugin.load()
|
|
18
|
+
plugin.loaded = True
|
|
19
|
+
# create instance of this platform implementation
|
|
20
|
+
plugin = plugin_class()
|
|
21
|
+
|
|
22
|
+
plugin.install(vars(OpenGL.platform))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
_ensure_egl_loaded()
|
|
26
|
+
from OpenGL import EGL as egl
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _get_egl_func(func_name, res_type, *arg_types):
|
|
30
|
+
address = egl.eglGetProcAddress(func_name)
|
|
31
|
+
if address is None:
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
proto = ctypes.CFUNCTYPE(res_type)
|
|
35
|
+
proto.argtypes = arg_types
|
|
36
|
+
func = proto(address)
|
|
37
|
+
return func
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _get_egl_struct(struct_name):
|
|
41
|
+
from OpenGL._opaque import opaque_pointer_cls
|
|
42
|
+
return opaque_pointer_cls(struct_name)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# These are not defined in PyOpenGL by default.
|
|
46
|
+
_EGLDeviceEXT = _get_egl_struct('EGLDeviceEXT')
|
|
47
|
+
_eglGetPlatformDisplayEXT = _get_egl_func('eglGetPlatformDisplayEXT', egl.EGLDisplay)
|
|
48
|
+
_eglQueryDevicesEXT = _get_egl_func('eglQueryDevicesEXT', egl.EGLBoolean)
|
|
49
|
+
_eglQueryDeviceStringEXT = _get_egl_func('eglQueryDeviceStringEXT', ctypes.c_char_p)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def query_devices():
|
|
53
|
+
if _eglQueryDevicesEXT is None:
|
|
54
|
+
raise RuntimeError("EGL query extension is not loaded or is not supported.")
|
|
55
|
+
|
|
56
|
+
num_devices = egl.EGLint()
|
|
57
|
+
success = _eglQueryDevicesEXT(0, None, ctypes.pointer(num_devices))
|
|
58
|
+
if not success or num_devices.value < 1:
|
|
59
|
+
return []
|
|
60
|
+
|
|
61
|
+
devices = (_EGLDeviceEXT * num_devices.value)() # array of size num_devices
|
|
62
|
+
success = _eglQueryDevicesEXT(num_devices.value, devices, ctypes.pointer(num_devices))
|
|
63
|
+
if not success or num_devices.value < 1:
|
|
64
|
+
return []
|
|
65
|
+
|
|
66
|
+
return [EGLDevice(devices[i]) for i in range(num_devices.value)]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def get_default_device():
|
|
70
|
+
# Fall back to not using query extension.
|
|
71
|
+
if _eglQueryDevicesEXT is None:
|
|
72
|
+
return EGLDevice(None)
|
|
73
|
+
|
|
74
|
+
return query_devices()[0]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_device_by_index(device_id):
|
|
78
|
+
if _eglQueryDevicesEXT is None and device_id == 0:
|
|
79
|
+
return get_default_device()
|
|
80
|
+
|
|
81
|
+
devices = query_devices()
|
|
82
|
+
if device_id >= len(devices):
|
|
83
|
+
raise ValueError('Invalid device ID ({})'.format(device_id, len(devices)))
|
|
84
|
+
return devices[device_id]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class EGLDevice:
|
|
88
|
+
|
|
89
|
+
def __init__(self, display=None):
|
|
90
|
+
self._display = display
|
|
91
|
+
|
|
92
|
+
def get_display(self):
|
|
93
|
+
if self._display is None:
|
|
94
|
+
return egl.eglGetDisplay(egl.EGL_DEFAULT_DISPLAY)
|
|
95
|
+
|
|
96
|
+
return _eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, self._display, None)
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def name(self):
|
|
100
|
+
if self._display is None:
|
|
101
|
+
return 'default'
|
|
102
|
+
|
|
103
|
+
name = _eglQueryDeviceStringEXT(self._display, EGL_DRM_DEVICE_FILE_EXT)
|
|
104
|
+
if name is None:
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
return name.decode('ascii')
|
|
108
|
+
|
|
109
|
+
def __repr__(self):
|
|
110
|
+
return "<EGLDevice(name={})>".format(self.name)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class EGLPlatform(Platform):
|
|
114
|
+
"""Renders using EGL.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
def __init__(self, viewport_width, viewport_height, device: EGLDevice = None):
|
|
118
|
+
super(EGLPlatform, self).__init__(viewport_width, viewport_height)
|
|
119
|
+
if device is None:
|
|
120
|
+
device = get_default_device()
|
|
121
|
+
|
|
122
|
+
self._egl_device = device
|
|
123
|
+
self._egl_display = None
|
|
124
|
+
self._egl_context = None
|
|
125
|
+
|
|
126
|
+
def init_context(self):
|
|
127
|
+
_ensure_egl_loaded()
|
|
128
|
+
|
|
129
|
+
from OpenGL.EGL import (
|
|
130
|
+
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_BLUE_SIZE,
|
|
131
|
+
EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_DEPTH_SIZE,
|
|
132
|
+
EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
|
|
133
|
+
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_CONFORMANT,
|
|
134
|
+
EGL_NONE, EGL_DEFAULT_DISPLAY, EGL_NO_CONTEXT,
|
|
135
|
+
EGL_OPENGL_API, EGL_CONTEXT_MAJOR_VERSION,
|
|
136
|
+
EGL_CONTEXT_MINOR_VERSION,
|
|
137
|
+
EGL_CONTEXT_OPENGL_PROFILE_MASK,
|
|
138
|
+
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
|
139
|
+
eglGetDisplay, eglInitialize, eglChooseConfig,
|
|
140
|
+
eglBindAPI, eglCreateContext, EGLConfig
|
|
141
|
+
)
|
|
142
|
+
from OpenGL import arrays
|
|
143
|
+
|
|
144
|
+
config_attributes = arrays.GLintArray.asArray([
|
|
145
|
+
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
|
|
146
|
+
EGL_BLUE_SIZE, 8,
|
|
147
|
+
EGL_RED_SIZE, 8,
|
|
148
|
+
EGL_GREEN_SIZE, 8,
|
|
149
|
+
EGL_DEPTH_SIZE, 24,
|
|
150
|
+
EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
|
|
151
|
+
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
|
152
|
+
EGL_CONFORMANT, EGL_OPENGL_BIT,
|
|
153
|
+
EGL_NONE
|
|
154
|
+
])
|
|
155
|
+
context_attributes = arrays.GLintArray.asArray([
|
|
156
|
+
EGL_CONTEXT_MAJOR_VERSION, 4,
|
|
157
|
+
EGL_CONTEXT_MINOR_VERSION, 1,
|
|
158
|
+
EGL_CONTEXT_OPENGL_PROFILE_MASK,
|
|
159
|
+
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
|
160
|
+
EGL_NONE
|
|
161
|
+
])
|
|
162
|
+
major, minor = ctypes.c_long(), ctypes.c_long()
|
|
163
|
+
num_configs = ctypes.c_long()
|
|
164
|
+
configs = (EGLConfig * 1)()
|
|
165
|
+
|
|
166
|
+
# Cache DISPLAY if necessary and get an off-screen EGL display
|
|
167
|
+
orig_dpy = None
|
|
168
|
+
if 'DISPLAY' in os.environ:
|
|
169
|
+
orig_dpy = os.environ['DISPLAY']
|
|
170
|
+
del os.environ['DISPLAY']
|
|
171
|
+
|
|
172
|
+
self._egl_display = self._egl_device.get_display()
|
|
173
|
+
if orig_dpy is not None:
|
|
174
|
+
os.environ['DISPLAY'] = orig_dpy
|
|
175
|
+
|
|
176
|
+
# Initialize EGL
|
|
177
|
+
assert eglInitialize(self._egl_display, major, minor)
|
|
178
|
+
assert eglChooseConfig(
|
|
179
|
+
self._egl_display, config_attributes, configs, 1, num_configs
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Bind EGL to the OpenGL API
|
|
183
|
+
assert eglBindAPI(EGL_OPENGL_API)
|
|
184
|
+
|
|
185
|
+
# Create an EGL context
|
|
186
|
+
self._egl_context = eglCreateContext(
|
|
187
|
+
self._egl_display, configs[0],
|
|
188
|
+
EGL_NO_CONTEXT, context_attributes
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Make it current
|
|
192
|
+
self.make_current()
|
|
193
|
+
|
|
194
|
+
def make_current(self):
|
|
195
|
+
from OpenGL.EGL import eglMakeCurrent, EGL_NO_SURFACE
|
|
196
|
+
assert eglMakeCurrent(
|
|
197
|
+
self._egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
|
198
|
+
self._egl_context
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
def make_uncurrent(self):
|
|
202
|
+
"""Make the OpenGL context uncurrent.
|
|
203
|
+
"""
|
|
204
|
+
pass
|
|
205
|
+
|
|
206
|
+
def delete_context(self):
|
|
207
|
+
from OpenGL.EGL import eglDestroyContext, eglTerminate
|
|
208
|
+
if self._egl_display is not None:
|
|
209
|
+
if self._egl_context is not None:
|
|
210
|
+
eglDestroyContext(self._egl_display, self._egl_context)
|
|
211
|
+
self._egl_context = None
|
|
212
|
+
eglTerminate(self._egl_display)
|
|
213
|
+
self._egl_display = None
|
|
214
|
+
|
|
215
|
+
def supports_framebuffers(self):
|
|
216
|
+
return True
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
__all__ = ['EGLPlatform']
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from .base import Platform
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
__all__ = ['OSMesaPlatform']
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OSMesaPlatform(Platform):
|
|
8
|
+
"""Renders into a software buffer using OSMesa. Requires special versions
|
|
9
|
+
of OSMesa to be installed, plus PyOpenGL upgrade.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, viewport_width, viewport_height):
|
|
13
|
+
super(OSMesaPlatform, self).__init__(viewport_width, viewport_height)
|
|
14
|
+
self._context = None
|
|
15
|
+
self._buffer = None
|
|
16
|
+
|
|
17
|
+
def init_context(self):
|
|
18
|
+
from OpenGL import arrays
|
|
19
|
+
from OpenGL.osmesa import (
|
|
20
|
+
OSMesaCreateContextAttribs, OSMESA_FORMAT,
|
|
21
|
+
OSMESA_RGBA, OSMESA_PROFILE, OSMESA_CORE_PROFILE,
|
|
22
|
+
OSMESA_CONTEXT_MAJOR_VERSION, OSMESA_CONTEXT_MINOR_VERSION,
|
|
23
|
+
OSMESA_DEPTH_BITS
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
attrs = arrays.GLintArray.asArray([
|
|
27
|
+
OSMESA_FORMAT, OSMESA_RGBA,
|
|
28
|
+
OSMESA_DEPTH_BITS, 24,
|
|
29
|
+
OSMESA_PROFILE, OSMESA_CORE_PROFILE,
|
|
30
|
+
OSMESA_CONTEXT_MAJOR_VERSION, 3,
|
|
31
|
+
OSMESA_CONTEXT_MINOR_VERSION, 3,
|
|
32
|
+
0
|
|
33
|
+
])
|
|
34
|
+
self._context = OSMesaCreateContextAttribs(attrs, None)
|
|
35
|
+
self._buffer = arrays.GLubyteArray.zeros(
|
|
36
|
+
(self.viewport_height, self.viewport_width, 4)
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def make_current(self):
|
|
40
|
+
from OpenGL import GL as gl
|
|
41
|
+
from OpenGL.osmesa import OSMesaMakeCurrent
|
|
42
|
+
assert(OSMesaMakeCurrent(
|
|
43
|
+
self._context, self._buffer, gl.GL_UNSIGNED_BYTE,
|
|
44
|
+
self.viewport_width, self.viewport_height
|
|
45
|
+
))
|
|
46
|
+
|
|
47
|
+
def make_uncurrent(self):
|
|
48
|
+
"""Make the OpenGL context uncurrent.
|
|
49
|
+
"""
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
def delete_context(self):
|
|
53
|
+
from OpenGL.osmesa import OSMesaDestroyContext
|
|
54
|
+
OSMesaDestroyContext(self._context)
|
|
55
|
+
self._context = None
|
|
56
|
+
self._buffer = None
|
|
57
|
+
|
|
58
|
+
def supports_framebuffers(self):
|
|
59
|
+
return False
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from pyrender.constants import (TARGET_OPEN_GL_MAJOR, TARGET_OPEN_GL_MINOR,
|
|
2
|
+
MIN_OPEN_GL_MAJOR, MIN_OPEN_GL_MINOR)
|
|
3
|
+
from .base import Platform
|
|
4
|
+
|
|
5
|
+
import OpenGL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
__all__ = ['PygletPlatform']
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PygletPlatform(Platform):
|
|
12
|
+
"""Renders on-screen using a 1x1 hidden Pyglet window for getting
|
|
13
|
+
an OpenGL context.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, viewport_width, viewport_height):
|
|
17
|
+
super(PygletPlatform, self).__init__(viewport_width, viewport_height)
|
|
18
|
+
self._window = None
|
|
19
|
+
|
|
20
|
+
def init_context(self):
|
|
21
|
+
import pyglet
|
|
22
|
+
pyglet.options['shadow_window'] = False
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
pyglet.lib.x11.xlib.XInitThreads()
|
|
26
|
+
except Exception:
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
self._window = None
|
|
30
|
+
confs = [pyglet.gl.Config(sample_buffers=1, samples=4,
|
|
31
|
+
depth_size=24,
|
|
32
|
+
double_buffer=True,
|
|
33
|
+
major_version=TARGET_OPEN_GL_MAJOR,
|
|
34
|
+
minor_version=TARGET_OPEN_GL_MINOR),
|
|
35
|
+
pyglet.gl.Config(depth_size=24,
|
|
36
|
+
double_buffer=True,
|
|
37
|
+
major_version=TARGET_OPEN_GL_MAJOR,
|
|
38
|
+
minor_version=TARGET_OPEN_GL_MINOR),
|
|
39
|
+
pyglet.gl.Config(sample_buffers=1, samples=4,
|
|
40
|
+
depth_size=24,
|
|
41
|
+
double_buffer=True,
|
|
42
|
+
major_version=MIN_OPEN_GL_MAJOR,
|
|
43
|
+
minor_version=MIN_OPEN_GL_MINOR),
|
|
44
|
+
pyglet.gl.Config(depth_size=24,
|
|
45
|
+
double_buffer=True,
|
|
46
|
+
major_version=MIN_OPEN_GL_MAJOR,
|
|
47
|
+
minor_version=MIN_OPEN_GL_MINOR)]
|
|
48
|
+
for conf in confs:
|
|
49
|
+
try:
|
|
50
|
+
self._window = pyglet.window.Window(config=conf, visible=False,
|
|
51
|
+
resizable=False,
|
|
52
|
+
width=1, height=1)
|
|
53
|
+
break
|
|
54
|
+
except pyglet.window.NoSuchConfigException as e:
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
if not self._window:
|
|
58
|
+
raise ValueError(
|
|
59
|
+
'Failed to initialize Pyglet window with an OpenGL >= 3+ '
|
|
60
|
+
'context. If you\'re logged in via SSH, ensure that you\'re '
|
|
61
|
+
'running your script with vglrun (i.e. VirtualGL). The '
|
|
62
|
+
'internal error message was "{}"'.format(e)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def make_current(self):
|
|
66
|
+
if self._window:
|
|
67
|
+
self._window.switch_to()
|
|
68
|
+
|
|
69
|
+
def make_uncurrent(self):
|
|
70
|
+
try:
|
|
71
|
+
import pyglet
|
|
72
|
+
pyglet.gl.xlib.glx.glXMakeContextCurrent(self._window.context.x_display, 0, 0, None)
|
|
73
|
+
except Exception:
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
def delete_context(self):
|
|
77
|
+
if self._window is not None:
|
|
78
|
+
self.make_current()
|
|
79
|
+
cid = OpenGL.contextdata.getContext()
|
|
80
|
+
try:
|
|
81
|
+
self._window.context.destroy()
|
|
82
|
+
self._window.close()
|
|
83
|
+
except Exception:
|
|
84
|
+
pass
|
|
85
|
+
self._window = None
|
|
86
|
+
OpenGL.contextdata.cleanupContext(cid)
|
|
87
|
+
del cid
|
|
88
|
+
|
|
89
|
+
def supports_framebuffers(self):
|
|
90
|
+
return True
|