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/material.py
ADDED
|
@@ -0,0 +1,705 @@
|
|
|
1
|
+
"""Material properties, conforming to the glTF 2.0 standards as specified in
|
|
2
|
+
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-material
|
|
3
|
+
and
|
|
4
|
+
https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness
|
|
5
|
+
|
|
6
|
+
Author: Matthew Matl
|
|
7
|
+
"""
|
|
8
|
+
import abc
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from .constants import TexFlags
|
|
12
|
+
from .utils import format_color_vector, format_texture_source
|
|
13
|
+
from .texture import Texture
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Material(abc.ABC):
|
|
17
|
+
"""Base for standard glTF 2.0 materials.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
name : str, optional
|
|
22
|
+
The user-defined name of this object.
|
|
23
|
+
normalTexture : (n,n,3) float or :class:`Texture`, optional
|
|
24
|
+
A tangent space normal map. The texture contains RGB components in
|
|
25
|
+
linear space. Each texel represents the XYZ components of a normal
|
|
26
|
+
vector in tangent space. Red [0 to 255] maps to X [-1 to 1]. Green
|
|
27
|
+
[0 to 255] maps to Y [-1 to 1]. Blue [128 to 255] maps to Z
|
|
28
|
+
[1/255 to 1]. The normal vectors use OpenGL conventions where +X is
|
|
29
|
+
right and +Y is up. +Z points toward the viewer.
|
|
30
|
+
occlusionTexture : (n,n,1) float or :class:`Texture`, optional
|
|
31
|
+
The occlusion map texture. The occlusion values are sampled from the R
|
|
32
|
+
channel. Higher values indicate areas that should receive full indirect
|
|
33
|
+
lighting and lower values indicate no indirect lighting. These values
|
|
34
|
+
are linear. If other channels are present (GBA), they are ignored for
|
|
35
|
+
occlusion calculations.
|
|
36
|
+
emissiveTexture : (n,n,3) float or :class:`Texture`, optional
|
|
37
|
+
The emissive map controls the color and intensity of the light being
|
|
38
|
+
emitted by the material. This texture contains RGB components in sRGB
|
|
39
|
+
color space. If a fourth component (A) is present, it is ignored.
|
|
40
|
+
emissiveFactor : (3,) float, optional
|
|
41
|
+
The RGB components of the emissive color of the material. These values
|
|
42
|
+
are linear. If an emissiveTexture is specified, this value is
|
|
43
|
+
multiplied with the texel values.
|
|
44
|
+
alphaMode : str, optional
|
|
45
|
+
The material's alpha rendering mode enumeration specifying the
|
|
46
|
+
interpretation of the alpha value of the main factor and texture.
|
|
47
|
+
Allowed Values:
|
|
48
|
+
|
|
49
|
+
- `"OPAQUE"` The alpha value is ignored and the rendered output is
|
|
50
|
+
fully opaque.
|
|
51
|
+
- `"MASK"` The rendered output is either fully opaque or fully
|
|
52
|
+
transparent depending on the alpha value and the specified alpha
|
|
53
|
+
cutoff value.
|
|
54
|
+
- `"BLEND"` The alpha value is used to composite the source and
|
|
55
|
+
destination areas. The rendered output is combined with the
|
|
56
|
+
background using the normal painting operation (i.e. the Porter
|
|
57
|
+
and Duff over operator).
|
|
58
|
+
|
|
59
|
+
alphaCutoff : float, optional
|
|
60
|
+
Specifies the cutoff threshold when in MASK mode. If the alpha value is
|
|
61
|
+
greater than or equal to this value then it is rendered as fully
|
|
62
|
+
opaque, otherwise, it is rendered as fully transparent.
|
|
63
|
+
A value greater than 1.0 will render the entire material as fully
|
|
64
|
+
transparent. This value is ignored for other modes.
|
|
65
|
+
doubleSided : bool, optional
|
|
66
|
+
Specifies whether the material is double sided. When this value is
|
|
67
|
+
false, back-face culling is enabled. When this value is true,
|
|
68
|
+
back-face culling is disabled and double sided lighting is enabled.
|
|
69
|
+
smooth : bool, optional
|
|
70
|
+
If True, the material is rendered smoothly by using only one normal
|
|
71
|
+
per vertex and face indexing.
|
|
72
|
+
wireframe : bool, optional
|
|
73
|
+
If True, the material is rendered in wireframe mode.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def __init__(self,
|
|
77
|
+
name=None,
|
|
78
|
+
normalTexture=None,
|
|
79
|
+
occlusionTexture=None,
|
|
80
|
+
emissiveTexture=None,
|
|
81
|
+
emissiveFactor=None,
|
|
82
|
+
alphaMode=None,
|
|
83
|
+
alphaCutoff=None,
|
|
84
|
+
doubleSided=False,
|
|
85
|
+
smooth=True,
|
|
86
|
+
wireframe=False):
|
|
87
|
+
|
|
88
|
+
# Set defaults
|
|
89
|
+
if alphaMode is None:
|
|
90
|
+
alphaMode = 'OPAQUE'
|
|
91
|
+
|
|
92
|
+
if alphaCutoff is None:
|
|
93
|
+
alphaCutoff = 0.5
|
|
94
|
+
|
|
95
|
+
if emissiveFactor is None:
|
|
96
|
+
emissiveFactor = np.zeros(3).astype(np.float32)
|
|
97
|
+
|
|
98
|
+
self.name = name
|
|
99
|
+
self.normalTexture = normalTexture
|
|
100
|
+
self.occlusionTexture = occlusionTexture
|
|
101
|
+
self.emissiveTexture = emissiveTexture
|
|
102
|
+
self.emissiveFactor = emissiveFactor
|
|
103
|
+
self.alphaMode = alphaMode
|
|
104
|
+
self.alphaCutoff = alphaCutoff
|
|
105
|
+
self.doubleSided = doubleSided
|
|
106
|
+
self.smooth = smooth
|
|
107
|
+
self.wireframe = wireframe
|
|
108
|
+
|
|
109
|
+
self._tex_flags = None
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def name(self):
|
|
113
|
+
"""str : The user-defined name of this object.
|
|
114
|
+
"""
|
|
115
|
+
return self._name
|
|
116
|
+
|
|
117
|
+
@name.setter
|
|
118
|
+
def name(self, value):
|
|
119
|
+
if value is not None:
|
|
120
|
+
value = str(value)
|
|
121
|
+
self._name = value
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def normalTexture(self):
|
|
125
|
+
"""(n,n,3) float or :class:`Texture` : The tangent-space normal map.
|
|
126
|
+
"""
|
|
127
|
+
return self._normalTexture
|
|
128
|
+
|
|
129
|
+
@normalTexture.setter
|
|
130
|
+
def normalTexture(self, value):
|
|
131
|
+
# TODO TMP
|
|
132
|
+
self._normalTexture = self._format_texture(value, 'RGB')
|
|
133
|
+
self._tex_flags = None
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def occlusionTexture(self):
|
|
137
|
+
"""(n,n,1) float or :class:`Texture` : The ambient occlusion map.
|
|
138
|
+
"""
|
|
139
|
+
return self._occlusionTexture
|
|
140
|
+
|
|
141
|
+
@occlusionTexture.setter
|
|
142
|
+
def occlusionTexture(self, value):
|
|
143
|
+
self._occlusionTexture = self._format_texture(value, 'R')
|
|
144
|
+
self._tex_flags = None
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def emissiveTexture(self):
|
|
148
|
+
"""(n,n,3) float or :class:`Texture` : The emission map.
|
|
149
|
+
"""
|
|
150
|
+
return self._emissiveTexture
|
|
151
|
+
|
|
152
|
+
@emissiveTexture.setter
|
|
153
|
+
def emissiveTexture(self, value):
|
|
154
|
+
self._emissiveTexture = self._format_texture(value, 'RGB')
|
|
155
|
+
self._tex_flags = None
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def emissiveFactor(self):
|
|
159
|
+
"""(3,) float : Base multiplier for emission colors.
|
|
160
|
+
"""
|
|
161
|
+
return self._emissiveFactor
|
|
162
|
+
|
|
163
|
+
@emissiveFactor.setter
|
|
164
|
+
def emissiveFactor(self, value):
|
|
165
|
+
if value is None:
|
|
166
|
+
value = np.zeros(3)
|
|
167
|
+
self._emissiveFactor = format_color_vector(value, 3)
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def alphaMode(self):
|
|
171
|
+
"""str : The mode for blending.
|
|
172
|
+
"""
|
|
173
|
+
return self._alphaMode
|
|
174
|
+
|
|
175
|
+
@alphaMode.setter
|
|
176
|
+
def alphaMode(self, value):
|
|
177
|
+
if value not in set(['OPAQUE', 'MASK', 'BLEND']):
|
|
178
|
+
raise ValueError('Invalid alpha mode {}'.format(value))
|
|
179
|
+
self._alphaMode = value
|
|
180
|
+
|
|
181
|
+
@property
|
|
182
|
+
def alphaCutoff(self):
|
|
183
|
+
"""float : The cutoff threshold in MASK mode.
|
|
184
|
+
"""
|
|
185
|
+
return self._alphaCutoff
|
|
186
|
+
|
|
187
|
+
@alphaCutoff.setter
|
|
188
|
+
def alphaCutoff(self, value):
|
|
189
|
+
if value < 0 or value > 1:
|
|
190
|
+
raise ValueError('Alpha cutoff must be in range [0,1]')
|
|
191
|
+
self._alphaCutoff = float(value)
|
|
192
|
+
|
|
193
|
+
@property
|
|
194
|
+
def doubleSided(self):
|
|
195
|
+
"""bool : Whether the material is double-sided.
|
|
196
|
+
"""
|
|
197
|
+
return self._doubleSided
|
|
198
|
+
|
|
199
|
+
@doubleSided.setter
|
|
200
|
+
def doubleSided(self, value):
|
|
201
|
+
if not isinstance(value, bool):
|
|
202
|
+
raise TypeError('Double sided must be a boolean value')
|
|
203
|
+
self._doubleSided = value
|
|
204
|
+
|
|
205
|
+
@property
|
|
206
|
+
def smooth(self):
|
|
207
|
+
"""bool : Whether to render the mesh smoothly by
|
|
208
|
+
interpolating vertex normals.
|
|
209
|
+
"""
|
|
210
|
+
return self._smooth
|
|
211
|
+
|
|
212
|
+
@smooth.setter
|
|
213
|
+
def smooth(self, value):
|
|
214
|
+
if not isinstance(value, bool):
|
|
215
|
+
raise TypeError('Double sided must be a boolean value')
|
|
216
|
+
self._smooth = value
|
|
217
|
+
|
|
218
|
+
@property
|
|
219
|
+
def wireframe(self):
|
|
220
|
+
"""bool : Whether to render the mesh in wireframe mode.
|
|
221
|
+
"""
|
|
222
|
+
return self._wireframe
|
|
223
|
+
|
|
224
|
+
@wireframe.setter
|
|
225
|
+
def wireframe(self, value):
|
|
226
|
+
if not isinstance(value, bool):
|
|
227
|
+
raise TypeError('Wireframe must be a boolean value')
|
|
228
|
+
self._wireframe = value
|
|
229
|
+
|
|
230
|
+
@property
|
|
231
|
+
def is_transparent(self):
|
|
232
|
+
"""bool : If True, the object is partially transparent.
|
|
233
|
+
"""
|
|
234
|
+
return self._compute_transparency()
|
|
235
|
+
|
|
236
|
+
@property
|
|
237
|
+
def tex_flags(self):
|
|
238
|
+
"""int : Texture availability flags.
|
|
239
|
+
"""
|
|
240
|
+
if self._tex_flags is None:
|
|
241
|
+
self._tex_flags = self._compute_tex_flags()
|
|
242
|
+
return self._tex_flags
|
|
243
|
+
|
|
244
|
+
@property
|
|
245
|
+
def textures(self):
|
|
246
|
+
"""list of :class:`Texture` : The textures associated with this
|
|
247
|
+
material.
|
|
248
|
+
"""
|
|
249
|
+
return self._compute_textures()
|
|
250
|
+
|
|
251
|
+
def _compute_transparency(self):
|
|
252
|
+
return False
|
|
253
|
+
|
|
254
|
+
def _compute_tex_flags(self):
|
|
255
|
+
tex_flags = TexFlags.NONE
|
|
256
|
+
if self.normalTexture is not None:
|
|
257
|
+
tex_flags |= TexFlags.NORMAL
|
|
258
|
+
if self.occlusionTexture is not None:
|
|
259
|
+
tex_flags |= TexFlags.OCCLUSION
|
|
260
|
+
if self.emissiveTexture is not None:
|
|
261
|
+
tex_flags |= TexFlags.EMISSIVE
|
|
262
|
+
return tex_flags
|
|
263
|
+
|
|
264
|
+
def _compute_textures(self):
|
|
265
|
+
all_textures = [
|
|
266
|
+
self.normalTexture, self.occlusionTexture, self.emissiveTexture
|
|
267
|
+
]
|
|
268
|
+
textures = set([t for t in all_textures if t is not None])
|
|
269
|
+
return textures
|
|
270
|
+
|
|
271
|
+
def _format_texture(self, texture, target_channels='RGB'):
|
|
272
|
+
"""Format a texture as a float32 np array.
|
|
273
|
+
"""
|
|
274
|
+
if isinstance(texture, Texture) or texture is None:
|
|
275
|
+
return texture
|
|
276
|
+
else:
|
|
277
|
+
source = format_texture_source(texture, target_channels)
|
|
278
|
+
return Texture(source=source, source_channels=target_channels)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
class MetallicRoughnessMaterial(Material):
|
|
282
|
+
"""A material based on the metallic-roughness material model from
|
|
283
|
+
Physically-Based Rendering (PBR) methodology.
|
|
284
|
+
|
|
285
|
+
Parameters
|
|
286
|
+
----------
|
|
287
|
+
name : str, optional
|
|
288
|
+
The user-defined name of this object.
|
|
289
|
+
normalTexture : (n,n,3) float or :class:`Texture`, optional
|
|
290
|
+
A tangent space normal map. The texture contains RGB components in
|
|
291
|
+
linear space. Each texel represents the XYZ components of a normal
|
|
292
|
+
vector in tangent space. Red [0 to 255] maps to X [-1 to 1]. Green
|
|
293
|
+
[0 to 255] maps to Y [-1 to 1]. Blue [128 to 255] maps to Z
|
|
294
|
+
[1/255 to 1]. The normal vectors use OpenGL conventions where +X is
|
|
295
|
+
right and +Y is up. +Z points toward the viewer.
|
|
296
|
+
occlusionTexture : (n,n,1) float or :class:`Texture`, optional
|
|
297
|
+
The occlusion map texture. The occlusion values are sampled from the R
|
|
298
|
+
channel. Higher values indicate areas that should receive full indirect
|
|
299
|
+
lighting and lower values indicate no indirect lighting. These values
|
|
300
|
+
are linear. If other channels are present (GBA), they are ignored for
|
|
301
|
+
occlusion calculations.
|
|
302
|
+
emissiveTexture : (n,n,3) float or :class:`Texture`, optional
|
|
303
|
+
The emissive map controls the color and intensity of the light being
|
|
304
|
+
emitted by the material. This texture contains RGB components in sRGB
|
|
305
|
+
color space. If a fourth component (A) is present, it is ignored.
|
|
306
|
+
emissiveFactor : (3,) float, optional
|
|
307
|
+
The RGB components of the emissive color of the material. These values
|
|
308
|
+
are linear. If an emissiveTexture is specified, this value is
|
|
309
|
+
multiplied with the texel values.
|
|
310
|
+
alphaMode : str, optional
|
|
311
|
+
The material's alpha rendering mode enumeration specifying the
|
|
312
|
+
interpretation of the alpha value of the main factor and texture.
|
|
313
|
+
Allowed Values:
|
|
314
|
+
|
|
315
|
+
- `"OPAQUE"` The alpha value is ignored and the rendered output is
|
|
316
|
+
fully opaque.
|
|
317
|
+
- `"MASK"` The rendered output is either fully opaque or fully
|
|
318
|
+
transparent depending on the alpha value and the specified alpha
|
|
319
|
+
cutoff value.
|
|
320
|
+
- `"BLEND"` The alpha value is used to composite the source and
|
|
321
|
+
destination areas. The rendered output is combined with the
|
|
322
|
+
background using the normal painting operation (i.e. the Porter
|
|
323
|
+
and Duff over operator).
|
|
324
|
+
|
|
325
|
+
alphaCutoff : float, optional
|
|
326
|
+
Specifies the cutoff threshold when in MASK mode. If the alpha value is
|
|
327
|
+
greater than or equal to this value then it is rendered as fully
|
|
328
|
+
opaque, otherwise, it is rendered as fully transparent.
|
|
329
|
+
A value greater than 1.0 will render the entire material as fully
|
|
330
|
+
transparent. This value is ignored for other modes.
|
|
331
|
+
doubleSided : bool, optional
|
|
332
|
+
Specifies whether the material is double sided. When this value is
|
|
333
|
+
false, back-face culling is enabled. When this value is true,
|
|
334
|
+
back-face culling is disabled and double sided lighting is enabled.
|
|
335
|
+
smooth : bool, optional
|
|
336
|
+
If True, the material is rendered smoothly by using only one normal
|
|
337
|
+
per vertex and face indexing.
|
|
338
|
+
wireframe : bool, optional
|
|
339
|
+
If True, the material is rendered in wireframe mode.
|
|
340
|
+
baseColorFactor : (4,) float, optional
|
|
341
|
+
The RGBA components of the base color of the material. The fourth
|
|
342
|
+
component (A) is the alpha coverage of the material. The alphaMode
|
|
343
|
+
property specifies how alpha is interpreted. These values are linear.
|
|
344
|
+
If a baseColorTexture is specified, this value is multiplied with the
|
|
345
|
+
texel values.
|
|
346
|
+
baseColorTexture : (n,n,4) float or :class:`Texture`, optional
|
|
347
|
+
The base color texture. This texture contains RGB(A) components in sRGB
|
|
348
|
+
color space. The first three components (RGB) specify the base color of
|
|
349
|
+
the material. If the fourth component (A) is present, it represents the
|
|
350
|
+
alpha coverage of the material. Otherwise, an alpha of 1.0 is assumed.
|
|
351
|
+
The alphaMode property specifies how alpha is interpreted.
|
|
352
|
+
The stored texels must not be premultiplied.
|
|
353
|
+
metallicFactor : float
|
|
354
|
+
The metalness of the material. A value of 1.0 means the material is a
|
|
355
|
+
metal. A value of 0.0 means the material is a dielectric. Values in
|
|
356
|
+
between are for blending between metals and dielectrics such as dirty
|
|
357
|
+
metallic surfaces. This value is linear. If a metallicRoughnessTexture
|
|
358
|
+
is specified, this value is multiplied with the metallic texel values.
|
|
359
|
+
roughnessFactor : float
|
|
360
|
+
The roughness of the material. A value of 1.0 means the material is
|
|
361
|
+
completely rough. A value of 0.0 means the material is completely
|
|
362
|
+
smooth. This value is linear. If a metallicRoughnessTexture is
|
|
363
|
+
specified, this value is multiplied with the roughness texel values.
|
|
364
|
+
metallicRoughnessTexture : (n,n,2) float or :class:`Texture`, optional
|
|
365
|
+
The metallic-roughness texture. The metalness values are sampled from
|
|
366
|
+
the B channel. The roughness values are sampled from the G channel.
|
|
367
|
+
These values are linear. If other channels are present (R or A), they
|
|
368
|
+
are ignored for metallic-roughness calculations.
|
|
369
|
+
"""
|
|
370
|
+
|
|
371
|
+
def __init__(self,
|
|
372
|
+
name=None,
|
|
373
|
+
normalTexture=None,
|
|
374
|
+
occlusionTexture=None,
|
|
375
|
+
emissiveTexture=None,
|
|
376
|
+
emissiveFactor=None,
|
|
377
|
+
alphaMode=None,
|
|
378
|
+
alphaCutoff=None,
|
|
379
|
+
doubleSided=False,
|
|
380
|
+
smooth=True,
|
|
381
|
+
wireframe=False,
|
|
382
|
+
baseColorFactor=None,
|
|
383
|
+
baseColorTexture=None,
|
|
384
|
+
metallicFactor=1.0,
|
|
385
|
+
roughnessFactor=1.0,
|
|
386
|
+
metallicRoughnessTexture=None):
|
|
387
|
+
super(MetallicRoughnessMaterial, self).__init__(
|
|
388
|
+
name=name,
|
|
389
|
+
normalTexture=normalTexture,
|
|
390
|
+
occlusionTexture=occlusionTexture,
|
|
391
|
+
emissiveTexture=emissiveTexture,
|
|
392
|
+
emissiveFactor=emissiveFactor,
|
|
393
|
+
alphaMode=alphaMode,
|
|
394
|
+
alphaCutoff=alphaCutoff,
|
|
395
|
+
doubleSided=doubleSided,
|
|
396
|
+
smooth=smooth,
|
|
397
|
+
wireframe=wireframe
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
# Set defaults
|
|
401
|
+
if baseColorFactor is None:
|
|
402
|
+
baseColorFactor = np.ones(4).astype(np.float32)
|
|
403
|
+
|
|
404
|
+
self.baseColorFactor = baseColorFactor
|
|
405
|
+
self.baseColorTexture = baseColorTexture
|
|
406
|
+
self.metallicFactor = metallicFactor
|
|
407
|
+
self.roughnessFactor = roughnessFactor
|
|
408
|
+
self.metallicRoughnessTexture = metallicRoughnessTexture
|
|
409
|
+
|
|
410
|
+
@property
|
|
411
|
+
def baseColorFactor(self):
|
|
412
|
+
"""(4,) float or :class:`Texture` : The RGBA base color multiplier.
|
|
413
|
+
"""
|
|
414
|
+
return self._baseColorFactor
|
|
415
|
+
|
|
416
|
+
@baseColorFactor.setter
|
|
417
|
+
def baseColorFactor(self, value):
|
|
418
|
+
if value is None:
|
|
419
|
+
value = np.ones(4)
|
|
420
|
+
self._baseColorFactor = format_color_vector(value, 4)
|
|
421
|
+
|
|
422
|
+
@property
|
|
423
|
+
def baseColorTexture(self):
|
|
424
|
+
"""(n,n,4) float or :class:`Texture` : The diffuse texture.
|
|
425
|
+
"""
|
|
426
|
+
return self._baseColorTexture
|
|
427
|
+
|
|
428
|
+
@baseColorTexture.setter
|
|
429
|
+
def baseColorTexture(self, value):
|
|
430
|
+
self._baseColorTexture = self._format_texture(value, 'RGBA')
|
|
431
|
+
self._tex_flags = None
|
|
432
|
+
|
|
433
|
+
@property
|
|
434
|
+
def metallicFactor(self):
|
|
435
|
+
"""float : The metalness of the material.
|
|
436
|
+
"""
|
|
437
|
+
return self._metallicFactor
|
|
438
|
+
|
|
439
|
+
@metallicFactor.setter
|
|
440
|
+
def metallicFactor(self, value):
|
|
441
|
+
if value is None:
|
|
442
|
+
value = 1.0
|
|
443
|
+
if value < 0 or value > 1:
|
|
444
|
+
raise ValueError('Metallic factor must be in range [0,1]')
|
|
445
|
+
self._metallicFactor = float(value)
|
|
446
|
+
|
|
447
|
+
@property
|
|
448
|
+
def roughnessFactor(self):
|
|
449
|
+
"""float : The roughness of the material.
|
|
450
|
+
"""
|
|
451
|
+
return self.RoughnessFactor
|
|
452
|
+
|
|
453
|
+
@roughnessFactor.setter
|
|
454
|
+
def roughnessFactor(self, value):
|
|
455
|
+
if value is None:
|
|
456
|
+
value = 1.0
|
|
457
|
+
if value < 0 or value > 1:
|
|
458
|
+
raise ValueError('Roughness factor must be in range [0,1]')
|
|
459
|
+
self.RoughnessFactor = float(value)
|
|
460
|
+
|
|
461
|
+
@property
|
|
462
|
+
def metallicRoughnessTexture(self):
|
|
463
|
+
"""(n,n,2) float or :class:`Texture` : The metallic-roughness texture.
|
|
464
|
+
"""
|
|
465
|
+
return self._metallicRoughnessTexture
|
|
466
|
+
|
|
467
|
+
@metallicRoughnessTexture.setter
|
|
468
|
+
def metallicRoughnessTexture(self, value):
|
|
469
|
+
self._metallicRoughnessTexture = self._format_texture(value, 'GB')
|
|
470
|
+
self._tex_flags = None
|
|
471
|
+
|
|
472
|
+
def _compute_tex_flags(self):
|
|
473
|
+
tex_flags = super(MetallicRoughnessMaterial, self)._compute_tex_flags()
|
|
474
|
+
if self.baseColorTexture is not None:
|
|
475
|
+
tex_flags |= TexFlags.BASE_COLOR
|
|
476
|
+
if self.metallicRoughnessTexture is not None:
|
|
477
|
+
tex_flags |= TexFlags.METALLIC_ROUGHNESS
|
|
478
|
+
return tex_flags
|
|
479
|
+
|
|
480
|
+
def _compute_transparency(self):
|
|
481
|
+
if self.alphaMode == 'OPAQUE':
|
|
482
|
+
return False
|
|
483
|
+
cutoff = self.alphaCutoff
|
|
484
|
+
if self.alphaMode == 'BLEND':
|
|
485
|
+
cutoff = 1.0
|
|
486
|
+
if self.baseColorFactor[3] < cutoff:
|
|
487
|
+
return True
|
|
488
|
+
if (self.baseColorTexture is not None and
|
|
489
|
+
self.baseColorTexture.is_transparent(cutoff)):
|
|
490
|
+
return True
|
|
491
|
+
return False
|
|
492
|
+
|
|
493
|
+
def _compute_textures(self):
|
|
494
|
+
textures = super(MetallicRoughnessMaterial, self)._compute_textures()
|
|
495
|
+
all_textures = [self.baseColorTexture, self.metallicRoughnessTexture]
|
|
496
|
+
all_textures = {t for t in all_textures if t is not None}
|
|
497
|
+
textures |= all_textures
|
|
498
|
+
return textures
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
class SpecularGlossinessMaterial(Material):
|
|
502
|
+
"""A material based on the specular-glossiness material model from
|
|
503
|
+
Physically-Based Rendering (PBR) methodology.
|
|
504
|
+
|
|
505
|
+
Parameters
|
|
506
|
+
----------
|
|
507
|
+
name : str, optional
|
|
508
|
+
The user-defined name of this object.
|
|
509
|
+
normalTexture : (n,n,3) float or :class:`Texture`, optional
|
|
510
|
+
A tangent space normal map. The texture contains RGB components in
|
|
511
|
+
linear space. Each texel represents the XYZ components of a normal
|
|
512
|
+
vector in tangent space. Red [0 to 255] maps to X [-1 to 1]. Green
|
|
513
|
+
[0 to 255] maps to Y [-1 to 1]. Blue [128 to 255] maps to Z
|
|
514
|
+
[1/255 to 1]. The normal vectors use OpenGL conventions where +X is
|
|
515
|
+
right and +Y is up. +Z points toward the viewer.
|
|
516
|
+
occlusionTexture : (n,n,1) float or :class:`Texture`, optional
|
|
517
|
+
The occlusion map texture. The occlusion values are sampled from the R
|
|
518
|
+
channel. Higher values indicate areas that should receive full indirect
|
|
519
|
+
lighting and lower values indicate no indirect lighting. These values
|
|
520
|
+
are linear. If other channels are present (GBA), they are ignored for
|
|
521
|
+
occlusion calculations.
|
|
522
|
+
emissiveTexture : (n,n,3) float or :class:`Texture`, optional
|
|
523
|
+
The emissive map controls the color and intensity of the light being
|
|
524
|
+
emitted by the material. This texture contains RGB components in sRGB
|
|
525
|
+
color space. If a fourth component (A) is present, it is ignored.
|
|
526
|
+
emissiveFactor : (3,) float, optional
|
|
527
|
+
The RGB components of the emissive color of the material. These values
|
|
528
|
+
are linear. If an emissiveTexture is specified, this value is
|
|
529
|
+
multiplied with the texel values.
|
|
530
|
+
alphaMode : str, optional
|
|
531
|
+
The material's alpha rendering mode enumeration specifying the
|
|
532
|
+
interpretation of the alpha value of the main factor and texture.
|
|
533
|
+
Allowed Values:
|
|
534
|
+
|
|
535
|
+
- `"OPAQUE"` The alpha value is ignored and the rendered output is
|
|
536
|
+
fully opaque.
|
|
537
|
+
- `"MASK"` The rendered output is either fully opaque or fully
|
|
538
|
+
transparent depending on the alpha value and the specified alpha
|
|
539
|
+
cutoff value.
|
|
540
|
+
- `"BLEND"` The alpha value is used to composite the source and
|
|
541
|
+
destination areas. The rendered output is combined with the
|
|
542
|
+
background using the normal painting operation (i.e. the Porter
|
|
543
|
+
and Duff over operator).
|
|
544
|
+
|
|
545
|
+
alphaCutoff : float, optional
|
|
546
|
+
Specifies the cutoff threshold when in MASK mode. If the alpha value is
|
|
547
|
+
greater than or equal to this value then it is rendered as fully
|
|
548
|
+
opaque, otherwise, it is rendered as fully transparent.
|
|
549
|
+
A value greater than 1.0 will render the entire material as fully
|
|
550
|
+
transparent. This value is ignored for other modes.
|
|
551
|
+
doubleSided : bool, optional
|
|
552
|
+
Specifies whether the material is double sided. When this value is
|
|
553
|
+
false, back-face culling is enabled. When this value is true,
|
|
554
|
+
back-face culling is disabled and double sided lighting is enabled.
|
|
555
|
+
smooth : bool, optional
|
|
556
|
+
If True, the material is rendered smoothly by using only one normal
|
|
557
|
+
per vertex and face indexing.
|
|
558
|
+
wireframe : bool, optional
|
|
559
|
+
If True, the material is rendered in wireframe mode.
|
|
560
|
+
diffuseFactor : (4,) float
|
|
561
|
+
The RGBA components of the reflected diffuse color of the material.
|
|
562
|
+
Metals have a diffuse value of [0.0, 0.0, 0.0]. The fourth component
|
|
563
|
+
(A) is the opacity of the material. The values are linear.
|
|
564
|
+
diffuseTexture : (n,n,4) float or :class:`Texture`, optional
|
|
565
|
+
The diffuse texture. This texture contains RGB(A) components of the
|
|
566
|
+
reflected diffuse color of the material in sRGB color space. If the
|
|
567
|
+
fourth component (A) is present, it represents the alpha coverage of
|
|
568
|
+
the material. Otherwise, an alpha of 1.0 is assumed.
|
|
569
|
+
The alphaMode property specifies how alpha is interpreted.
|
|
570
|
+
The stored texels must not be premultiplied.
|
|
571
|
+
specularFactor : (3,) float
|
|
572
|
+
The specular RGB color of the material. This value is linear.
|
|
573
|
+
glossinessFactor : float
|
|
574
|
+
The glossiness or smoothness of the material. A value of 1.0 means the
|
|
575
|
+
material has full glossiness or is perfectly smooth. A value of 0.0
|
|
576
|
+
means the material has no glossiness or is perfectly rough. This value
|
|
577
|
+
is linear.
|
|
578
|
+
specularGlossinessTexture : (n,n,4) or :class:`Texture`, optional
|
|
579
|
+
The specular-glossiness texture is a RGBA texture, containing the
|
|
580
|
+
specular color (RGB) in sRGB space and the glossiness value (A) in
|
|
581
|
+
linear space.
|
|
582
|
+
"""
|
|
583
|
+
|
|
584
|
+
def __init__(self,
|
|
585
|
+
name=None,
|
|
586
|
+
normalTexture=None,
|
|
587
|
+
occlusionTexture=None,
|
|
588
|
+
emissiveTexture=None,
|
|
589
|
+
emissiveFactor=None,
|
|
590
|
+
alphaMode=None,
|
|
591
|
+
alphaCutoff=None,
|
|
592
|
+
doubleSided=False,
|
|
593
|
+
smooth=True,
|
|
594
|
+
wireframe=False,
|
|
595
|
+
diffuseFactor=None,
|
|
596
|
+
diffuseTexture=None,
|
|
597
|
+
specularFactor=None,
|
|
598
|
+
glossinessFactor=1.0,
|
|
599
|
+
specularGlossinessTexture=None):
|
|
600
|
+
super(SpecularGlossinessMaterial, self).__init__(
|
|
601
|
+
name=name,
|
|
602
|
+
normalTexture=normalTexture,
|
|
603
|
+
occlusionTexture=occlusionTexture,
|
|
604
|
+
emissiveTexture=emissiveTexture,
|
|
605
|
+
emissiveFactor=emissiveFactor,
|
|
606
|
+
alphaMode=alphaMode,
|
|
607
|
+
alphaCutoff=alphaCutoff,
|
|
608
|
+
doubleSided=doubleSided,
|
|
609
|
+
smooth=smooth,
|
|
610
|
+
wireframe=wireframe
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
# Set defaults
|
|
614
|
+
if diffuseFactor is None:
|
|
615
|
+
diffuseFactor = np.ones(4).astype(np.float32)
|
|
616
|
+
if specularFactor is None:
|
|
617
|
+
specularFactor = np.ones(3).astype(np.float32)
|
|
618
|
+
|
|
619
|
+
self.diffuseFactor = diffuseFactor
|
|
620
|
+
self.diffuseTexture = diffuseTexture
|
|
621
|
+
self.specularFactor = specularFactor
|
|
622
|
+
self.glossinessFactor = glossinessFactor
|
|
623
|
+
self.specularGlossinessTexture = specularGlossinessTexture
|
|
624
|
+
|
|
625
|
+
@property
|
|
626
|
+
def diffuseFactor(self):
|
|
627
|
+
"""(4,) float : The diffuse base color.
|
|
628
|
+
"""
|
|
629
|
+
return self._diffuseFactor
|
|
630
|
+
|
|
631
|
+
@diffuseFactor.setter
|
|
632
|
+
def diffuseFactor(self, value):
|
|
633
|
+
self._diffuseFactor = format_color_vector(value, 4)
|
|
634
|
+
|
|
635
|
+
@property
|
|
636
|
+
def diffuseTexture(self):
|
|
637
|
+
"""(n,n,4) float or :class:`Texture` : The diffuse map.
|
|
638
|
+
"""
|
|
639
|
+
return self._diffuseTexture
|
|
640
|
+
|
|
641
|
+
@diffuseTexture.setter
|
|
642
|
+
def diffuseTexture(self, value):
|
|
643
|
+
self._diffuseTexture = self._format_texture(value, 'RGBA')
|
|
644
|
+
self._tex_flags = None
|
|
645
|
+
|
|
646
|
+
@property
|
|
647
|
+
def specularFactor(self):
|
|
648
|
+
"""(3,) float : The specular color of the material.
|
|
649
|
+
"""
|
|
650
|
+
return self._specularFactor
|
|
651
|
+
|
|
652
|
+
@specularFactor.setter
|
|
653
|
+
def specularFactor(self, value):
|
|
654
|
+
self._specularFactor = format_color_vector(value, 3)
|
|
655
|
+
|
|
656
|
+
@property
|
|
657
|
+
def glossinessFactor(self):
|
|
658
|
+
"""float : The glossiness of the material.
|
|
659
|
+
"""
|
|
660
|
+
return self.glossinessFactor
|
|
661
|
+
|
|
662
|
+
@glossinessFactor.setter
|
|
663
|
+
def glossinessFactor(self, value):
|
|
664
|
+
if value < 0 or value > 1:
|
|
665
|
+
raise ValueError('glossiness factor must be in range [0,1]')
|
|
666
|
+
self._glossinessFactor = float(value)
|
|
667
|
+
|
|
668
|
+
@property
|
|
669
|
+
def specularGlossinessTexture(self):
|
|
670
|
+
"""(n,n,4) or :class:`Texture` : The specular-glossiness texture.
|
|
671
|
+
"""
|
|
672
|
+
return self._specularGlossinessTexture
|
|
673
|
+
|
|
674
|
+
@specularGlossinessTexture.setter
|
|
675
|
+
def specularGlossinessTexture(self, value):
|
|
676
|
+
self._specularGlossinessTexture = self._format_texture(value, 'GB')
|
|
677
|
+
self._tex_flags = None
|
|
678
|
+
|
|
679
|
+
def _compute_tex_flags(self):
|
|
680
|
+
flags = super(SpecularGlossinessMaterial, self)._compute_tex_flags()
|
|
681
|
+
if self.diffuseTexture is not None:
|
|
682
|
+
flags |= TexFlags.DIFFUSE
|
|
683
|
+
if self.specularGlossinessTexture is not None:
|
|
684
|
+
flags |= TexFlags.SPECULAR_GLOSSINESS
|
|
685
|
+
return flags
|
|
686
|
+
|
|
687
|
+
def _compute_transparency(self):
|
|
688
|
+
if self.alphaMode == 'OPAQUE':
|
|
689
|
+
return False
|
|
690
|
+
cutoff = self.alphaCutoff
|
|
691
|
+
if self.alphaMode == 'BLEND':
|
|
692
|
+
cutoff = 1.0
|
|
693
|
+
if self.diffuseFactor[3] < cutoff:
|
|
694
|
+
return True
|
|
695
|
+
if (self.diffuseTexture is not None and
|
|
696
|
+
self.diffuseTexture.is_transparent(cutoff)):
|
|
697
|
+
return True
|
|
698
|
+
return False
|
|
699
|
+
|
|
700
|
+
def _compute_textures(self):
|
|
701
|
+
textures = super(SpecularGlossinessMaterial, self)._compute_textures()
|
|
702
|
+
all_textures = [self.diffuseTexture, self.specularGlossinessTexture]
|
|
703
|
+
all_textures = {t for t in all_textures if t is not None}
|
|
704
|
+
textures |= all_textures
|
|
705
|
+
return textures
|