|
"""Material properties, conforming to the glTF 2.0 standards as specified in |
|
https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-material |
|
and |
|
https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness |
|
|
|
Author: Matthew Matl |
|
""" |
|
import abc |
|
import numpy as np |
|
import six |
|
|
|
from .constants import TexFlags |
|
from .utils import format_color_vector, format_texture_source |
|
from .texture import Texture |
|
|
|
|
|
@six.add_metaclass(abc.ABCMeta) |
|
class Material(object): |
|
"""Base for standard glTF 2.0 materials. |
|
|
|
Parameters |
|
---------- |
|
name : str, optional |
|
The user-defined name of this object. |
|
normalTexture : (n,n,3) float or :class:`Texture`, optional |
|
A tangent space normal map. The texture contains RGB components in |
|
linear space. Each texel represents the XYZ components of a normal |
|
vector in tangent space. Red [0 to 255] maps to X [-1 to 1]. Green |
|
[0 to 255] maps to Y [-1 to 1]. Blue [128 to 255] maps to Z |
|
[1/255 to 1]. The normal vectors use OpenGL conventions where +X is |
|
right and +Y is up. +Z points toward the viewer. |
|
occlusionTexture : (n,n,1) float or :class:`Texture`, optional |
|
The occlusion map texture. The occlusion values are sampled from the R |
|
channel. Higher values indicate areas that should receive full indirect |
|
lighting and lower values indicate no indirect lighting. These values |
|
are linear. If other channels are present (GBA), they are ignored for |
|
occlusion calculations. |
|
emissiveTexture : (n,n,3) float or :class:`Texture`, optional |
|
The emissive map controls the color and intensity of the light being |
|
emitted by the material. This texture contains RGB components in sRGB |
|
color space. If a fourth component (A) is present, it is ignored. |
|
emissiveFactor : (3,) float, optional |
|
The RGB components of the emissive color of the material. These values |
|
are linear. If an emissiveTexture is specified, this value is |
|
multiplied with the texel values. |
|
alphaMode : str, optional |
|
The material's alpha rendering mode enumeration specifying the |
|
interpretation of the alpha value of the main factor and texture. |
|
Allowed Values: |
|
|
|
- `"OPAQUE"` The alpha value is ignored and the rendered output is |
|
fully opaque. |
|
- `"MASK"` The rendered output is either fully opaque or fully |
|
transparent depending on the alpha value and the specified alpha |
|
cutoff value. |
|
- `"BLEND"` The alpha value is used to composite the source and |
|
destination areas. The rendered output is combined with the |
|
background using the normal painting operation (i.e. the Porter |
|
and Duff over operator). |
|
|
|
alphaCutoff : float, optional |
|
Specifies the cutoff threshold when in MASK mode. If the alpha value is |
|
greater than or equal to this value then it is rendered as fully |
|
opaque, otherwise, it is rendered as fully transparent. |
|
A value greater than 1.0 will render the entire material as fully |
|
transparent. This value is ignored for other modes. |
|
doubleSided : bool, optional |
|
Specifies whether the material is double sided. When this value is |
|
false, back-face culling is enabled. When this value is true, |
|
back-face culling is disabled and double sided lighting is enabled. |
|
smooth : bool, optional |
|
If True, the material is rendered smoothly by using only one normal |
|
per vertex and face indexing. |
|
wireframe : bool, optional |
|
If True, the material is rendered in wireframe mode. |
|
""" |
|
|
|
def __init__(self, |
|
name=None, |
|
normalTexture=None, |
|
occlusionTexture=None, |
|
emissiveTexture=None, |
|
emissiveFactor=None, |
|
alphaMode=None, |
|
alphaCutoff=None, |
|
doubleSided=False, |
|
smooth=True, |
|
wireframe=False): |
|
|
|
|
|
if alphaMode is None: |
|
alphaMode = 'OPAQUE' |
|
|
|
if alphaCutoff is None: |
|
alphaCutoff = 0.5 |
|
|
|
if emissiveFactor is None: |
|
emissiveFactor = np.zeros(3).astype(np.float32) |
|
|
|
self.name = name |
|
self.normalTexture = normalTexture |
|
self.occlusionTexture = occlusionTexture |
|
self.emissiveTexture = emissiveTexture |
|
self.emissiveFactor = emissiveFactor |
|
self.alphaMode = alphaMode |
|
self.alphaCutoff = alphaCutoff |
|
self.doubleSided = doubleSided |
|
self.smooth = smooth |
|
self.wireframe = wireframe |
|
|
|
self._tex_flags = None |
|
|
|
@property |
|
def name(self): |
|
"""str : The user-defined name of this object. |
|
""" |
|
return self._name |
|
|
|
@name.setter |
|
def name(self, value): |
|
if value is not None: |
|
value = str(value) |
|
self._name = value |
|
|
|
@property |
|
def normalTexture(self): |
|
"""(n,n,3) float or :class:`Texture` : The tangent-space normal map. |
|
""" |
|
return self._normalTexture |
|
|
|
@normalTexture.setter |
|
def normalTexture(self, value): |
|
|
|
self._normalTexture = self._format_texture(value, 'RGB') |
|
self._tex_flags = None |
|
|
|
@property |
|
def occlusionTexture(self): |
|
"""(n,n,1) float or :class:`Texture` : The ambient occlusion map. |
|
""" |
|
return self._occlusionTexture |
|
|
|
@occlusionTexture.setter |
|
def occlusionTexture(self, value): |
|
self._occlusionTexture = self._format_texture(value, 'R') |
|
self._tex_flags = None |
|
|
|
@property |
|
def emissiveTexture(self): |
|
"""(n,n,3) float or :class:`Texture` : The emission map. |
|
""" |
|
return self._emissiveTexture |
|
|
|
@emissiveTexture.setter |
|
def emissiveTexture(self, value): |
|
self._emissiveTexture = self._format_texture(value, 'RGB') |
|
self._tex_flags = None |
|
|
|
@property |
|
def emissiveFactor(self): |
|
"""(3,) float : Base multiplier for emission colors. |
|
""" |
|
return self._emissiveFactor |
|
|
|
@emissiveFactor.setter |
|
def emissiveFactor(self, value): |
|
if value is None: |
|
value = np.zeros(3) |
|
self._emissiveFactor = format_color_vector(value, 3) |
|
|
|
@property |
|
def alphaMode(self): |
|
"""str : The mode for blending. |
|
""" |
|
return self._alphaMode |
|
|
|
@alphaMode.setter |
|
def alphaMode(self, value): |
|
if value not in set(['OPAQUE', 'MASK', 'BLEND']): |
|
raise ValueError('Invalid alpha mode {}'.format(value)) |
|
self._alphaMode = value |
|
|
|
@property |
|
def alphaCutoff(self): |
|
"""float : The cutoff threshold in MASK mode. |
|
""" |
|
return self._alphaCutoff |
|
|
|
@alphaCutoff.setter |
|
def alphaCutoff(self, value): |
|
if value < 0 or value > 1: |
|
raise ValueError('Alpha cutoff must be in range [0,1]') |
|
self._alphaCutoff = float(value) |
|
|
|
@property |
|
def doubleSided(self): |
|
"""bool : Whether the material is double-sided. |
|
""" |
|
return self._doubleSided |
|
|
|
@doubleSided.setter |
|
def doubleSided(self, value): |
|
if not isinstance(value, bool): |
|
raise TypeError('Double sided must be a boolean value') |
|
self._doubleSided = value |
|
|
|
@property |
|
def smooth(self): |
|
"""bool : Whether to render the mesh smoothly by |
|
interpolating vertex normals. |
|
""" |
|
return self._smooth |
|
|
|
@smooth.setter |
|
def smooth(self, value): |
|
if not isinstance(value, bool): |
|
raise TypeError('Double sided must be a boolean value') |
|
self._smooth = value |
|
|
|
@property |
|
def wireframe(self): |
|
"""bool : Whether to render the mesh in wireframe mode. |
|
""" |
|
return self._wireframe |
|
|
|
@wireframe.setter |
|
def wireframe(self, value): |
|
if not isinstance(value, bool): |
|
raise TypeError('Wireframe must be a boolean value') |
|
self._wireframe = value |
|
|
|
@property |
|
def is_transparent(self): |
|
"""bool : If True, the object is partially transparent. |
|
""" |
|
return self._compute_transparency() |
|
|
|
@property |
|
def tex_flags(self): |
|
"""int : Texture availability flags. |
|
""" |
|
if self._tex_flags is None: |
|
self._tex_flags = self._compute_tex_flags() |
|
return self._tex_flags |
|
|
|
@property |
|
def textures(self): |
|
"""list of :class:`Texture` : The textures associated with this |
|
material. |
|
""" |
|
return self._compute_textures() |
|
|
|
def _compute_transparency(self): |
|
return False |
|
|
|
def _compute_tex_flags(self): |
|
tex_flags = TexFlags.NONE |
|
if self.normalTexture is not None: |
|
tex_flags |= TexFlags.NORMAL |
|
if self.occlusionTexture is not None: |
|
tex_flags |= TexFlags.OCCLUSION |
|
if self.emissiveTexture is not None: |
|
tex_flags |= TexFlags.EMISSIVE |
|
return tex_flags |
|
|
|
def _compute_textures(self): |
|
all_textures = [ |
|
self.normalTexture, self.occlusionTexture, self.emissiveTexture |
|
] |
|
textures = set([t for t in all_textures if t is not None]) |
|
return textures |
|
|
|
def _format_texture(self, texture, target_channels='RGB'): |
|
"""Format a texture as a float32 np array. |
|
""" |
|
if isinstance(texture, Texture) or texture is None: |
|
return texture |
|
else: |
|
source = format_texture_source(texture, target_channels) |
|
return Texture(source=source, source_channels=target_channels) |
|
|
|
|
|
class MetallicRoughnessMaterial(Material): |
|
"""A material based on the metallic-roughness material model from |
|
Physically-Based Rendering (PBR) methodology. |
|
|
|
Parameters |
|
---------- |
|
name : str, optional |
|
The user-defined name of this object. |
|
normalTexture : (n,n,3) float or :class:`Texture`, optional |
|
A tangent space normal map. The texture contains RGB components in |
|
linear space. Each texel represents the XYZ components of a normal |
|
vector in tangent space. Red [0 to 255] maps to X [-1 to 1]. Green |
|
[0 to 255] maps to Y [-1 to 1]. Blue [128 to 255] maps to Z |
|
[1/255 to 1]. The normal vectors use OpenGL conventions where +X is |
|
right and +Y is up. +Z points toward the viewer. |
|
occlusionTexture : (n,n,1) float or :class:`Texture`, optional |
|
The occlusion map texture. The occlusion values are sampled from the R |
|
channel. Higher values indicate areas that should receive full indirect |
|
lighting and lower values indicate no indirect lighting. These values |
|
are linear. If other channels are present (GBA), they are ignored for |
|
occlusion calculations. |
|
emissiveTexture : (n,n,3) float or :class:`Texture`, optional |
|
The emissive map controls the color and intensity of the light being |
|
emitted by the material. This texture contains RGB components in sRGB |
|
color space. If a fourth component (A) is present, it is ignored. |
|
emissiveFactor : (3,) float, optional |
|
The RGB components of the emissive color of the material. These values |
|
are linear. If an emissiveTexture is specified, this value is |
|
multiplied with the texel values. |
|
alphaMode : str, optional |
|
The material's alpha rendering mode enumeration specifying the |
|
interpretation of the alpha value of the main factor and texture. |
|
Allowed Values: |
|
|
|
- `"OPAQUE"` The alpha value is ignored and the rendered output is |
|
fully opaque. |
|
- `"MASK"` The rendered output is either fully opaque or fully |
|
transparent depending on the alpha value and the specified alpha |
|
cutoff value. |
|
- `"BLEND"` The alpha value is used to composite the source and |
|
destination areas. The rendered output is combined with the |
|
background using the normal painting operation (i.e. the Porter |
|
and Duff over operator). |
|
|
|
alphaCutoff : float, optional |
|
Specifies the cutoff threshold when in MASK mode. If the alpha value is |
|
greater than or equal to this value then it is rendered as fully |
|
opaque, otherwise, it is rendered as fully transparent. |
|
A value greater than 1.0 will render the entire material as fully |
|
transparent. This value is ignored for other modes. |
|
doubleSided : bool, optional |
|
Specifies whether the material is double sided. When this value is |
|
false, back-face culling is enabled. When this value is true, |
|
back-face culling is disabled and double sided lighting is enabled. |
|
smooth : bool, optional |
|
If True, the material is rendered smoothly by using only one normal |
|
per vertex and face indexing. |
|
wireframe : bool, optional |
|
If True, the material is rendered in wireframe mode. |
|
baseColorFactor : (4,) float, optional |
|
The RGBA components of the base color of the material. The fourth |
|
component (A) is the alpha coverage of the material. The alphaMode |
|
property specifies how alpha is interpreted. These values are linear. |
|
If a baseColorTexture is specified, this value is multiplied with the |
|
texel values. |
|
baseColorTexture : (n,n,4) float or :class:`Texture`, optional |
|
The base color texture. This texture contains RGB(A) components in sRGB |
|
color space. The first three components (RGB) specify the base color of |
|
the material. If the fourth component (A) is present, it represents the |
|
alpha coverage of the material. Otherwise, an alpha of 1.0 is assumed. |
|
The alphaMode property specifies how alpha is interpreted. |
|
The stored texels must not be premultiplied. |
|
metallicFactor : float |
|
The metalness of the material. A value of 1.0 means the material is a |
|
metal. A value of 0.0 means the material is a dielectric. Values in |
|
between are for blending between metals and dielectrics such as dirty |
|
metallic surfaces. This value is linear. If a metallicRoughnessTexture |
|
is specified, this value is multiplied with the metallic texel values. |
|
roughnessFactor : float |
|
The roughness of the material. A value of 1.0 means the material is |
|
completely rough. A value of 0.0 means the material is completely |
|
smooth. This value is linear. If a metallicRoughnessTexture is |
|
specified, this value is multiplied with the roughness texel values. |
|
metallicRoughnessTexture : (n,n,2) float or :class:`Texture`, optional |
|
The metallic-roughness texture. The metalness values are sampled from |
|
the B channel. The roughness values are sampled from the G channel. |
|
These values are linear. If other channels are present (R or A), they |
|
are ignored for metallic-roughness calculations. |
|
""" |
|
|
|
def __init__(self, |
|
name=None, |
|
normalTexture=None, |
|
occlusionTexture=None, |
|
emissiveTexture=None, |
|
emissiveFactor=None, |
|
alphaMode=None, |
|
alphaCutoff=None, |
|
doubleSided=False, |
|
smooth=True, |
|
wireframe=False, |
|
baseColorFactor=None, |
|
baseColorTexture=None, |
|
metallicFactor=1.0, |
|
roughnessFactor=1.0, |
|
metallicRoughnessTexture=None): |
|
super(MetallicRoughnessMaterial, self).__init__( |
|
name=name, |
|
normalTexture=normalTexture, |
|
occlusionTexture=occlusionTexture, |
|
emissiveTexture=emissiveTexture, |
|
emissiveFactor=emissiveFactor, |
|
alphaMode=alphaMode, |
|
alphaCutoff=alphaCutoff, |
|
doubleSided=doubleSided, |
|
smooth=smooth, |
|
wireframe=wireframe |
|
) |
|
|
|
|
|
if baseColorFactor is None: |
|
baseColorFactor = np.ones(4).astype(np.float32) |
|
|
|
self.baseColorFactor = baseColorFactor |
|
self.baseColorTexture = baseColorTexture |
|
self.metallicFactor = metallicFactor |
|
self.roughnessFactor = roughnessFactor |
|
self.metallicRoughnessTexture = metallicRoughnessTexture |
|
|
|
@property |
|
def baseColorFactor(self): |
|
"""(4,) float or :class:`Texture` : The RGBA base color multiplier. |
|
""" |
|
return self._baseColorFactor |
|
|
|
@baseColorFactor.setter |
|
def baseColorFactor(self, value): |
|
if value is None: |
|
value = np.ones(4) |
|
self._baseColorFactor = format_color_vector(value, 4) |
|
|
|
@property |
|
def baseColorTexture(self): |
|
"""(n,n,4) float or :class:`Texture` : The diffuse texture. |
|
""" |
|
return self._baseColorTexture |
|
|
|
@baseColorTexture.setter |
|
def baseColorTexture(self, value): |
|
self._baseColorTexture = self._format_texture(value, 'RGBA') |
|
self._tex_flags = None |
|
|
|
@property |
|
def metallicFactor(self): |
|
"""float : The metalness of the material. |
|
""" |
|
return self._metallicFactor |
|
|
|
@metallicFactor.setter |
|
def metallicFactor(self, value): |
|
if value is None: |
|
value = 1.0 |
|
if value < 0 or value > 1: |
|
raise ValueError('Metallic factor must be in range [0,1]') |
|
self._metallicFactor = float(value) |
|
|
|
@property |
|
def roughnessFactor(self): |
|
"""float : The roughness of the material. |
|
""" |
|
return self.RoughnessFactor |
|
|
|
@roughnessFactor.setter |
|
def roughnessFactor(self, value): |
|
if value is None: |
|
value = 1.0 |
|
if value < 0 or value > 1: |
|
raise ValueError('Roughness factor must be in range [0,1]') |
|
self.RoughnessFactor = float(value) |
|
|
|
@property |
|
def metallicRoughnessTexture(self): |
|
"""(n,n,2) float or :class:`Texture` : The metallic-roughness texture. |
|
""" |
|
return self._metallicRoughnessTexture |
|
|
|
@metallicRoughnessTexture.setter |
|
def metallicRoughnessTexture(self, value): |
|
self._metallicRoughnessTexture = self._format_texture(value, 'GB') |
|
self._tex_flags = None |
|
|
|
def _compute_tex_flags(self): |
|
tex_flags = super(MetallicRoughnessMaterial, self)._compute_tex_flags() |
|
if self.baseColorTexture is not None: |
|
tex_flags |= TexFlags.BASE_COLOR |
|
if self.metallicRoughnessTexture is not None: |
|
tex_flags |= TexFlags.METALLIC_ROUGHNESS |
|
return tex_flags |
|
|
|
def _compute_transparency(self): |
|
if self.alphaMode == 'OPAQUE': |
|
return False |
|
cutoff = self.alphaCutoff |
|
if self.alphaMode == 'BLEND': |
|
cutoff = 1.0 |
|
if self.baseColorFactor[3] < cutoff: |
|
return True |
|
if (self.baseColorTexture is not None and |
|
self.baseColorTexture.is_transparent(cutoff)): |
|
return True |
|
return False |
|
|
|
def _compute_textures(self): |
|
textures = super(MetallicRoughnessMaterial, self)._compute_textures() |
|
all_textures = [self.baseColorTexture, self.metallicRoughnessTexture] |
|
all_textures = {t for t in all_textures if t is not None} |
|
textures |= all_textures |
|
return textures |
|
|
|
|
|
class SpecularGlossinessMaterial(Material): |
|
"""A material based on the specular-glossiness material model from |
|
Physically-Based Rendering (PBR) methodology. |
|
|
|
Parameters |
|
---------- |
|
name : str, optional |
|
The user-defined name of this object. |
|
normalTexture : (n,n,3) float or :class:`Texture`, optional |
|
A tangent space normal map. The texture contains RGB components in |
|
linear space. Each texel represents the XYZ components of a normal |
|
vector in tangent space. Red [0 to 255] maps to X [-1 to 1]. Green |
|
[0 to 255] maps to Y [-1 to 1]. Blue [128 to 255] maps to Z |
|
[1/255 to 1]. The normal vectors use OpenGL conventions where +X is |
|
right and +Y is up. +Z points toward the viewer. |
|
occlusionTexture : (n,n,1) float or :class:`Texture`, optional |
|
The occlusion map texture. The occlusion values are sampled from the R |
|
channel. Higher values indicate areas that should receive full indirect |
|
lighting and lower values indicate no indirect lighting. These values |
|
are linear. If other channels are present (GBA), they are ignored for |
|
occlusion calculations. |
|
emissiveTexture : (n,n,3) float or :class:`Texture`, optional |
|
The emissive map controls the color and intensity of the light being |
|
emitted by the material. This texture contains RGB components in sRGB |
|
color space. If a fourth component (A) is present, it is ignored. |
|
emissiveFactor : (3,) float, optional |
|
The RGB components of the emissive color of the material. These values |
|
are linear. If an emissiveTexture is specified, this value is |
|
multiplied with the texel values. |
|
alphaMode : str, optional |
|
The material's alpha rendering mode enumeration specifying the |
|
interpretation of the alpha value of the main factor and texture. |
|
Allowed Values: |
|
|
|
- `"OPAQUE"` The alpha value is ignored and the rendered output is |
|
fully opaque. |
|
- `"MASK"` The rendered output is either fully opaque or fully |
|
transparent depending on the alpha value and the specified alpha |
|
cutoff value. |
|
- `"BLEND"` The alpha value is used to composite the source and |
|
destination areas. The rendered output is combined with the |
|
background using the normal painting operation (i.e. the Porter |
|
and Duff over operator). |
|
|
|
alphaCutoff : float, optional |
|
Specifies the cutoff threshold when in MASK mode. If the alpha value is |
|
greater than or equal to this value then it is rendered as fully |
|
opaque, otherwise, it is rendered as fully transparent. |
|
A value greater than 1.0 will render the entire material as fully |
|
transparent. This value is ignored for other modes. |
|
doubleSided : bool, optional |
|
Specifies whether the material is double sided. When this value is |
|
false, back-face culling is enabled. When this value is true, |
|
back-face culling is disabled and double sided lighting is enabled. |
|
smooth : bool, optional |
|
If True, the material is rendered smoothly by using only one normal |
|
per vertex and face indexing. |
|
wireframe : bool, optional |
|
If True, the material is rendered in wireframe mode. |
|
diffuseFactor : (4,) float |
|
The RGBA components of the reflected diffuse color of the material. |
|
Metals have a diffuse value of [0.0, 0.0, 0.0]. The fourth component |
|
(A) is the opacity of the material. The values are linear. |
|
diffuseTexture : (n,n,4) float or :class:`Texture`, optional |
|
The diffuse texture. This texture contains RGB(A) components of the |
|
reflected diffuse color of the material in sRGB color space. If the |
|
fourth component (A) is present, it represents the alpha coverage of |
|
the material. Otherwise, an alpha of 1.0 is assumed. |
|
The alphaMode property specifies how alpha is interpreted. |
|
The stored texels must not be premultiplied. |
|
specularFactor : (3,) float |
|
The specular RGB color of the material. This value is linear. |
|
glossinessFactor : float |
|
The glossiness or smoothness of the material. A value of 1.0 means the |
|
material has full glossiness or is perfectly smooth. A value of 0.0 |
|
means the material has no glossiness or is perfectly rough. This value |
|
is linear. |
|
specularGlossinessTexture : (n,n,4) or :class:`Texture`, optional |
|
The specular-glossiness texture is a RGBA texture, containing the |
|
specular color (RGB) in sRGB space and the glossiness value (A) in |
|
linear space. |
|
""" |
|
|
|
def __init__(self, |
|
name=None, |
|
normalTexture=None, |
|
occlusionTexture=None, |
|
emissiveTexture=None, |
|
emissiveFactor=None, |
|
alphaMode=None, |
|
alphaCutoff=None, |
|
doubleSided=False, |
|
smooth=True, |
|
wireframe=False, |
|
diffuseFactor=None, |
|
diffuseTexture=None, |
|
specularFactor=None, |
|
glossinessFactor=1.0, |
|
specularGlossinessTexture=None): |
|
super(SpecularGlossinessMaterial, self).__init__( |
|
name=name, |
|
normalTexture=normalTexture, |
|
occlusionTexture=occlusionTexture, |
|
emissiveTexture=emissiveTexture, |
|
emissiveFactor=emissiveFactor, |
|
alphaMode=alphaMode, |
|
alphaCutoff=alphaCutoff, |
|
doubleSided=doubleSided, |
|
smooth=smooth, |
|
wireframe=wireframe |
|
) |
|
|
|
|
|
if diffuseFactor is None: |
|
diffuseFactor = np.ones(4).astype(np.float32) |
|
if specularFactor is None: |
|
specularFactor = np.ones(3).astype(np.float32) |
|
|
|
self.diffuseFactor = diffuseFactor |
|
self.diffuseTexture = diffuseTexture |
|
self.specularFactor = specularFactor |
|
self.glossinessFactor = glossinessFactor |
|
self.specularGlossinessTexture = specularGlossinessTexture |
|
|
|
@property |
|
def diffuseFactor(self): |
|
"""(4,) float : The diffuse base color. |
|
""" |
|
return self._diffuseFactor |
|
|
|
@diffuseFactor.setter |
|
def diffuseFactor(self, value): |
|
self._diffuseFactor = format_color_vector(value, 4) |
|
|
|
@property |
|
def diffuseTexture(self): |
|
"""(n,n,4) float or :class:`Texture` : The diffuse map. |
|
""" |
|
return self._diffuseTexture |
|
|
|
@diffuseTexture.setter |
|
def diffuseTexture(self, value): |
|
self._diffuseTexture = self._format_texture(value, 'RGBA') |
|
self._tex_flags = None |
|
|
|
@property |
|
def specularFactor(self): |
|
"""(3,) float : The specular color of the material. |
|
""" |
|
return self._specularFactor |
|
|
|
@specularFactor.setter |
|
def specularFactor(self, value): |
|
self._specularFactor = format_color_vector(value, 3) |
|
|
|
@property |
|
def glossinessFactor(self): |
|
"""float : The glossiness of the material. |
|
""" |
|
return self.glossinessFactor |
|
|
|
@glossinessFactor.setter |
|
def glossinessFactor(self, value): |
|
if value < 0 or value > 1: |
|
raise ValueError('glossiness factor must be in range [0,1]') |
|
self._glossinessFactor = float(value) |
|
|
|
@property |
|
def specularGlossinessTexture(self): |
|
"""(n,n,4) or :class:`Texture` : The specular-glossiness texture. |
|
""" |
|
return self._specularGlossinessTexture |
|
|
|
@specularGlossinessTexture.setter |
|
def specularGlossinessTexture(self, value): |
|
self._specularGlossinessTexture = self._format_texture(value, 'GB') |
|
self._tex_flags = None |
|
|
|
def _compute_tex_flags(self): |
|
flags = super(SpecularGlossinessMaterial, self)._compute_tex_flags() |
|
if self.diffuseTexture is not None: |
|
flags |= TexFlags.DIFFUSE |
|
if self.specularGlossinessTexture is not None: |
|
flags |= TexFlags.SPECULAR_GLOSSINESS |
|
return flags |
|
|
|
def _compute_transparency(self): |
|
if self.alphaMode == 'OPAQUE': |
|
return False |
|
cutoff = self.alphaCutoff |
|
if self.alphaMode == 'BLEND': |
|
cutoff = 1.0 |
|
if self.diffuseFactor[3] < cutoff: |
|
return True |
|
if (self.diffuseTexture is not None and |
|
self.diffuseTexture.is_transparent(cutoff)): |
|
return True |
|
return False |
|
|
|
def _compute_textures(self): |
|
textures = super(SpecularGlossinessMaterial, self)._compute_textures() |
|
all_textures = [self.diffuseTexture, self.specularGlossinessTexture] |
|
all_textures = {t for t in all_textures if t is not None} |
|
textures |= all_textures |
|
return textures |
|
|