12 #ifndef hifi_model_Material_h
13 #define hifi_model_Material_h
18 #include <unordered_map>
21 #include <ColorUtils.h>
23 #include <gpu/Resource.h>
24 #include <gpu/Texture.h>
25 #include <gpu/TextureTable.h>
27 #include "MaterialMappingMode.h"
34 typedef std::shared_ptr< TextureMap > TextureMapPointer;
48 OPACITY_TRANSLUCENT_MAP_BIT,
50 OPACITY_CUTOFF_VAL_BIT,
73 typedef std::bitset<NUM_FLAGS> Flags;
90 OPACITY_MAP_OPAQUE = 0,
94 static std::string getOpacityMapModeName(OpacityMapMode mode);
96 static bool getOpacityMapModeFromName(
const std::string& modeName, OpacityMapMode& mode);
105 static std::string getCullFaceModeName(CullFaceMode mode);
106 static bool getCullFaceModeFromName(
const std::string& modeName, CullFaceMode& mode);
111 MaterialKey() : _flags(0) {}
112 MaterialKey(
const Flags& flags) : _flags(flags) {}
119 MaterialKey build()
const {
return MaterialKey(_flags); }
121 Builder& withEmissive() { _flags.set(EMISSIVE_VAL_BIT);
return (*
this); }
122 Builder& withUnlit() { _flags.set(UNLIT_VAL_BIT);
return (*
this); }
124 Builder& withAlbedo() { _flags.set(ALBEDO_VAL_BIT);
return (*
this); }
125 Builder& withMetallic() { _flags.set(METALLIC_VAL_BIT);
return (*
this); }
126 Builder& withGlossy() { _flags.set(GLOSSY_VAL_BIT);
return (*
this); }
128 Builder& withTranslucentFactor() { _flags.set(OPACITY_VAL_BIT);
return (*
this); }
129 Builder& withTranslucentMap() { _flags.set(OPACITY_TRANSLUCENT_MAP_BIT);
return (*
this); }
130 Builder& withMaskMap() { _flags.set(OPACITY_MASK_MAP_BIT);
return (*
this); }
131 Builder& withOpacityMapMode(OpacityMapMode mode) {
133 case OPACITY_MAP_OPAQUE:
134 _flags.reset(OPACITY_TRANSLUCENT_MAP_BIT);
135 _flags.reset(OPACITY_MASK_MAP_BIT);
137 case OPACITY_MAP_MASK:
138 _flags.reset(OPACITY_TRANSLUCENT_MAP_BIT);
139 _flags.set(OPACITY_MASK_MAP_BIT);
141 case OPACITY_MAP_BLEND:
142 _flags.set(OPACITY_TRANSLUCENT_MAP_BIT);
143 _flags.reset(OPACITY_MASK_MAP_BIT);
146 _flags.set(OPACITY_MAP_MODE_BIT);
149 Builder& withOpacityCutoff() { _flags.set(OPACITY_CUTOFF_VAL_BIT);
return (*
this); }
151 Builder& withScattering() { _flags.set(SCATTERING_VAL_BIT);
return (*
this); }
153 Builder& withEmissiveMap() { _flags.set(EMISSIVE_MAP_BIT);
return (*
this); }
154 Builder& withAlbedoMap() { _flags.set(ALBEDO_MAP_BIT);
return (*
this); }
155 Builder& withMetallicMap() { _flags.set(METALLIC_MAP_BIT);
return (*
this); }
156 Builder& withRoughnessMap() { _flags.set(ROUGHNESS_MAP_BIT);
return (*
this); }
158 Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT);
return (*
this); }
159 Builder& withOcclusionMap() { _flags.set(OCCLUSION_MAP_BIT);
return (*
this); }
160 Builder& withLightMap() { _flags.set(LIGHT_MAP_BIT);
return (*
this); }
161 Builder& withScatteringMap() { _flags.set(SCATTERING_MAP_BIT);
return (*
this); }
164 static MaterialKey opaqueAlbedo() {
return Builder().withAlbedo().build(); }
167 void setEmissive(
bool value) { _flags.set(EMISSIVE_VAL_BIT, value); }
168 bool isEmissive()
const {
return _flags[EMISSIVE_VAL_BIT]; }
170 void setUnlit(
bool value) { _flags.set(UNLIT_VAL_BIT, value); }
171 bool isUnlit()
const {
return _flags[UNLIT_VAL_BIT]; }
173 void setEmissiveMap(
bool value) { _flags.set(EMISSIVE_MAP_BIT, value); }
174 bool isEmissiveMap()
const {
return _flags[EMISSIVE_MAP_BIT]; }
176 void setAlbedo(
bool value) { _flags.set(ALBEDO_VAL_BIT, value); }
177 bool isAlbedo()
const {
return _flags[ALBEDO_VAL_BIT]; }
179 void setAlbedoMap(
bool value) { _flags.set(ALBEDO_MAP_BIT, value); }
180 bool isAlbedoMap()
const {
return _flags[ALBEDO_MAP_BIT]; }
182 void setMetallic(
bool value) { _flags.set(METALLIC_VAL_BIT, value); }
183 bool isMetallic()
const {
return _flags[METALLIC_VAL_BIT]; }
185 void setMetallicMap(
bool value) { _flags.set(METALLIC_MAP_BIT, value); }
186 bool isMetallicMap()
const {
return _flags[METALLIC_MAP_BIT]; }
188 void setGlossy(
bool value) { _flags.set(GLOSSY_VAL_BIT, value); }
189 bool isGlossy()
const {
return _flags[GLOSSY_VAL_BIT]; }
190 bool isRough()
const {
return !_flags[GLOSSY_VAL_BIT]; }
192 void setRoughnessMap(
bool value) { _flags.set(ROUGHNESS_MAP_BIT, value); }
193 bool isRoughnessMap()
const {
return _flags[ROUGHNESS_MAP_BIT]; }
195 void setTranslucentFactor(
bool value) { _flags.set(OPACITY_VAL_BIT, value); }
196 bool isTranslucentFactor()
const {
return _flags[OPACITY_VAL_BIT]; }
198 void setTranslucentMap(
bool value) { _flags.set(OPACITY_TRANSLUCENT_MAP_BIT, value); }
199 bool isTranslucentMap()
const {
return _flags[OPACITY_TRANSLUCENT_MAP_BIT]; }
201 void setOpacityMaskMap(
bool value) { _flags.set(OPACITY_MASK_MAP_BIT, value); }
202 bool isOpacityMaskMap()
const {
return _flags[OPACITY_MASK_MAP_BIT]; }
204 void setOpacityCutoff(
bool value) { _flags.set(OPACITY_CUTOFF_VAL_BIT, value); }
205 bool isOpacityCutoff()
const {
return _flags[OPACITY_CUTOFF_VAL_BIT]; }
207 void setNormalMap(
bool value) { _flags.set(NORMAL_MAP_BIT, value); }
208 bool isNormalMap()
const {
return _flags[NORMAL_MAP_BIT]; }
210 void setOcclusionMap(
bool value) { _flags.set(OCCLUSION_MAP_BIT, value); }
211 bool isOcclusionMap()
const {
return _flags[OCCLUSION_MAP_BIT]; }
213 void setLightMap(
bool value) { _flags.set(LIGHT_MAP_BIT, value); }
214 bool isLightMap()
const {
return _flags[LIGHT_MAP_BIT]; }
216 void setScattering(
bool value) { _flags.set(SCATTERING_VAL_BIT, value); }
217 bool isScattering()
const {
return _flags[SCATTERING_VAL_BIT]; }
219 void setScatteringMap(
bool value) { _flags.set(SCATTERING_MAP_BIT, value); }
220 bool isScatteringMap()
const {
return _flags[SCATTERING_MAP_BIT]; }
222 void setMapChannel(MapChannel channel,
bool value) { _flags.set(
static_cast<size_t>(EMISSIVE_MAP_BIT) +
static_cast<size_t>(channel), value); }
223 bool isMapChannel(MapChannel channel)
const {
return _flags[
static_cast<size_t>(EMISSIVE_MAP_BIT) +
static_cast<size_t>(channel)]; }
227 void setOpacityMapMode(OpacityMapMode mode) {
229 case OPACITY_MAP_OPAQUE:
230 _flags.reset(OPACITY_TRANSLUCENT_MAP_BIT);
231 _flags.reset(OPACITY_MASK_MAP_BIT);
233 case OPACITY_MAP_MASK:
234 _flags.reset(OPACITY_TRANSLUCENT_MAP_BIT);
235 _flags.set(OPACITY_MASK_MAP_BIT);
237 case OPACITY_MAP_BLEND:
238 _flags.set(OPACITY_TRANSLUCENT_MAP_BIT);
239 _flags.reset(OPACITY_MASK_MAP_BIT);
242 _flags.set(OPACITY_MAP_MODE_BIT);
244 bool isOpacityMapMode()
const {
return _flags[OPACITY_MAP_MODE_BIT]; }
245 OpacityMapMode getOpacityMapMode()
const {
return (isOpacityMaskMap() ? OPACITY_MAP_MASK : (isTranslucentMap() ? OPACITY_MAP_BLEND : OPACITY_MAP_OPAQUE)); }
247 bool isTranslucent()
const {
return isTranslucentFactor() || isTranslucentMap(); }
248 bool isOpaque()
const {
return !isTranslucent(); }
249 bool isSurfaceOpaque()
const {
return isOpaque() && !isOpacityMaskMap(); }
250 bool isTexelOpaque()
const {
return isOpaque() && isOpacityMaskMap(); }
253 class MaterialFilter {
255 MaterialKey::Flags _value{ 0 };
256 MaterialKey::Flags _mask{ 0 };
259 MaterialFilter(
const MaterialKey::Flags& value = MaterialKey::Flags(0),
const MaterialKey::Flags& mask = MaterialKey::Flags(0)) : _value(value), _mask(mask) {}
262 MaterialKey::Flags _value{ 0 };
263 MaterialKey::Flags _mask{ 0 };
267 MaterialFilter build()
const {
return MaterialFilter(_value, _mask); }
269 Builder& withoutEmissive() { _value.reset(MaterialKey::EMISSIVE_VAL_BIT); _mask.set(MaterialKey::EMISSIVE_VAL_BIT);
return (*
this); }
270 Builder& withEmissive() { _value.set(MaterialKey::EMISSIVE_VAL_BIT); _mask.set(MaterialKey::EMISSIVE_VAL_BIT);
return (*
this); }
272 Builder& withoutEmissiveMap() { _value.reset(MaterialKey::EMISSIVE_MAP_BIT); _mask.set(MaterialKey::EMISSIVE_MAP_BIT);
return (*
this); }
273 Builder& withEmissiveMap() { _value.set(MaterialKey::EMISSIVE_MAP_BIT); _mask.set(MaterialKey::EMISSIVE_MAP_BIT);
return (*
this); }
275 Builder& withoutUnlit() { _value.reset(MaterialKey::UNLIT_VAL_BIT); _mask.set(MaterialKey::UNLIT_VAL_BIT);
return (*
this); }
276 Builder& withUnlit() { _value.set(MaterialKey::UNLIT_VAL_BIT); _mask.set(MaterialKey::UNLIT_VAL_BIT);
return (*
this); }
278 Builder& withoutAlbedo() { _value.reset(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT);
return (*
this); }
279 Builder& withAlbedo() { _value.set(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT);
return (*
this); }
281 Builder& withoutAlbedoMap() { _value.reset(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT);
return (*
this); }
282 Builder& withAlbedoMap() { _value.set(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT);
return (*
this); }
284 Builder& withoutMetallic() { _value.reset(MaterialKey::METALLIC_VAL_BIT); _mask.set(MaterialKey::METALLIC_VAL_BIT);
return (*
this); }
285 Builder& withMetallic() { _value.set(MaterialKey::METALLIC_VAL_BIT); _mask.set(MaterialKey::METALLIC_VAL_BIT);
return (*
this); }
287 Builder& withoutMetallicMap() { _value.reset(MaterialKey::METALLIC_MAP_BIT); _mask.set(MaterialKey::METALLIC_MAP_BIT);
return (*
this); }
288 Builder& withMetallicMap() { _value.set(MaterialKey::METALLIC_MAP_BIT); _mask.set(MaterialKey::METALLIC_MAP_BIT);
return (*
this); }
290 Builder& withoutGlossy() { _value.reset(MaterialKey::GLOSSY_VAL_BIT); _mask.set(MaterialKey::GLOSSY_VAL_BIT);
return (*
this); }
291 Builder& withGlossy() { _value.set(MaterialKey::GLOSSY_VAL_BIT); _mask.set(MaterialKey::GLOSSY_VAL_BIT);
return (*
this); }
293 Builder& withoutRoughnessMap() { _value.reset(MaterialKey::ROUGHNESS_MAP_BIT); _mask.set(MaterialKey::ROUGHNESS_MAP_BIT);
return (*
this); }
294 Builder& withRoughnessMap() { _value.set(MaterialKey::ROUGHNESS_MAP_BIT); _mask.set(MaterialKey::ROUGHNESS_MAP_BIT);
return (*
this); }
296 Builder& withoutTranslucentFactor() { _value.reset(MaterialKey::OPACITY_VAL_BIT); _mask.set(MaterialKey::OPACITY_VAL_BIT);
return (*
this); }
297 Builder& withTranslucentFactor() { _value.set(MaterialKey::OPACITY_VAL_BIT); _mask.set(MaterialKey::OPACITY_VAL_BIT);
return (*
this); }
299 Builder& withoutTranslucentMap() { _value.reset(MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT); _mask.set(MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT);
return (*
this); }
300 Builder& withTranslucentMap() { _value.set(MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT); _mask.set(MaterialKey::OPACITY_TRANSLUCENT_MAP_BIT);
return (*
this); }
302 Builder& withoutMaskMap() { _value.reset(MaterialKey::OPACITY_MASK_MAP_BIT); _mask.set(MaterialKey::OPACITY_MASK_MAP_BIT);
return (*
this); }
303 Builder& withMaskMap() { _value.set(MaterialKey::OPACITY_MASK_MAP_BIT); _mask.set(MaterialKey::OPACITY_MASK_MAP_BIT);
return (*
this); }
305 Builder& withoutOpacityMapMode() { _value.reset(MaterialKey::OPACITY_MAP_MODE_BIT); _mask.set(MaterialKey::OPACITY_MAP_MODE_BIT);
return (*
this); }
306 Builder& withOpacityMapMode() { _value.set(MaterialKey::OPACITY_MAP_MODE_BIT); _mask.set(MaterialKey::OPACITY_MAP_MODE_BIT);
return (*
this); }
308 Builder& withoutOpacityCutoff() { _value.reset(MaterialKey::OPACITY_CUTOFF_VAL_BIT); _mask.set(MaterialKey::OPACITY_CUTOFF_VAL_BIT);
return (*
this); }
309 Builder& withOpacityCutoff() { _value.set(MaterialKey::OPACITY_CUTOFF_VAL_BIT); _mask.set(MaterialKey::OPACITY_CUTOFF_VAL_BIT);
return (*
this); }
311 Builder& withoutNormalMap() { _value.reset(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT);
return (*
this); }
312 Builder& withNormalMap() { _value.set(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT);
return (*
this); }
314 Builder& withoutOcclusionMap() { _value.reset(MaterialKey::OCCLUSION_MAP_BIT); _mask.set(MaterialKey::OCCLUSION_MAP_BIT);
return (*
this); }
315 Builder& withOcclusionMap() { _value.set(MaterialKey::OCCLUSION_MAP_BIT); _mask.set(MaterialKey::OCCLUSION_MAP_BIT);
return (*
this); }
317 Builder& withoutLightMap() { _value.reset(MaterialKey::LIGHT_MAP_BIT); _mask.set(MaterialKey::LIGHT_MAP_BIT);
return (*
this); }
318 Builder& withLightMap() { _value.set(MaterialKey::LIGHT_MAP_BIT); _mask.set(MaterialKey::LIGHT_MAP_BIT);
return (*
this); }
320 Builder& withoutScattering() { _value.reset(MaterialKey::SCATTERING_VAL_BIT); _mask.set(MaterialKey::SCATTERING_VAL_BIT);
return (*
this); }
321 Builder& withScattering() { _value.set(MaterialKey::SCATTERING_VAL_BIT); _mask.set(MaterialKey::SCATTERING_VAL_BIT);
return (*
this); }
323 Builder& withoutScatteringMap() { _value.reset(MaterialKey::SCATTERING_MAP_BIT); _mask.set(MaterialKey::SCATTERING_MAP_BIT);
return (*
this); }
324 Builder& withScatteringMap() { _value.set(MaterialKey::SCATTERING_MAP_BIT); _mask.set(MaterialKey::SCATTERING_MAP_BIT);
return (*
this); }
328 static MaterialFilter opaqueAlbedo() {
return Builder().withAlbedo().withoutTranslucentFactor().build(); }
332 bool test(
const MaterialKey& key)
const {
return (key._flags & _mask) == (_value & _mask); }
336 bool operator() (
const MaterialFilter& left,
const MaterialFilter& right)
const {
337 if (left._value.to_ulong() == right._value.to_ulong()) {
338 return left._mask.to_ulong() < right._mask.to_ulong();
340 return left._value.to_ulong() < right._value.to_ulong();
348 typedef MaterialKey::MapChannel MapChannel;
349 typedef std::unordered_map<MapChannel, TextureMapPointer> TextureMaps;
350 typedef std::unordered_map<MapChannel, Sampler> SamplerMap;
351 typedef std::unordered_map<MapChannel, int> TexCoordSetMap;
354 Material(
const Material& material);
355 virtual ~Material() =
default;
356 Material& operator= (
const Material& material);
358 virtual MaterialKey getKey()
const {
return _key; }
360 static const float DEFAULT_EMISSIVE;
361 void setEmissive(
const glm::vec3& emissive,
bool isSRGB =
true);
362 virtual glm::vec3 getEmissive(
bool SRGB =
true)
const {
return (SRGB ? ColorUtils::tosRGBVec3(_emissive) : _emissive); }
364 static const float DEFAULT_OPACITY;
365 void setOpacity(
float opacity);
366 virtual float getOpacity()
const {
return _opacity; }
368 static const MaterialKey::OpacityMapMode DEFAULT_OPACITY_MAP_MODE;
369 void setOpacityMapMode(MaterialKey::OpacityMapMode opacityMapMode);
370 virtual MaterialKey::OpacityMapMode getOpacityMapMode()
const;
372 static const float DEFAULT_OPACITY_CUTOFF;
373 void setOpacityCutoff(
float opacityCutoff);
374 virtual float getOpacityCutoff()
const {
return _opacityCutoff; }
376 static const MaterialKey::CullFaceMode DEFAULT_CULL_FACE_MODE;
377 void setCullFaceMode(MaterialKey::CullFaceMode cullFaceMode) { _cullFaceMode = cullFaceMode; }
378 virtual MaterialKey::CullFaceMode getCullFaceMode()
const {
return _cullFaceMode; }
380 void setUnlit(
bool value);
381 virtual bool isUnlit()
const {
return _key.isUnlit(); }
383 static const float DEFAULT_ALBEDO;
384 void setAlbedo(
const glm::vec3& albedo,
bool isSRGB =
true);
385 virtual glm::vec3 getAlbedo(
bool SRGB =
true)
const {
return (SRGB ? ColorUtils::tosRGBVec3(_albedo) : _albedo); }
387 static const float DEFAULT_METALLIC;
388 void setMetallic(
float metallic);
389 virtual float getMetallic()
const {
return _metallic; }
391 static const float DEFAULT_ROUGHNESS;
392 void setRoughness(
float roughness);
393 virtual float getRoughness()
const {
return _roughness; }
395 static const float DEFAULT_SCATTERING;
396 void setScattering(
float scattering);
397 virtual float getScattering()
const {
return _scattering; }
400 static const int NUM_TEXCOORD_TRANSFORMS { 2 };
401 void setTextureMap(MapChannel channel,
const TextureMapPointer& textureMap);
402 virtual TextureMaps getTextureMaps()
const {
return _textureMaps; }
403 const TextureMapPointer getTextureMap(MapChannel channel)
const;
405 void setSampler(MapChannel channel,
const Sampler& sampler);
406 void applySampler(MapChannel channel);
408 void setTexCoordSet(MapChannel channel,
int texCoordSet);
409 int getTexCoordSet(MapChannel channel);
414 virtual bool resetOpacityMap()
const;
417 static float shininessToRoughness(
float shininess) {
return 1.0f - shininess / 100.0f; }
419 void setTextureTransforms(
const Transform& transform, MaterialMappingMode mode,
bool repeat);
421 const std::string& getName()
const {
return _name; }
422 void setName(
const std::string& name) { _name = name; }
424 const std::string& getModel()
const {
return _model; }
425 void setModel(
const std::string& model) { _model = model; }
427 virtual glm::mat4 getTexCoordTransform(uint i)
const {
return _texcoordTransforms[i]; }
428 void setTexCoordTransform(uint i,
const glm::mat4& mat4) { _texcoordTransforms[i] = mat4; }
429 virtual glm::vec2 getLightmapParams()
const {
return _lightmapParams; }
430 virtual glm::vec2 getMaterialParams()
const {
return _materialParams; }
432 virtual uint8_t getLayers()
const {
return _layers; }
433 void setLayers(uint8_t layers) { _layers = std::min(3, std::max(1, (
int)layers)); }
435 virtual bool getDefaultFallthrough()
const {
return _defaultFallthrough; }
436 void setDefaultFallthrough(
bool defaultFallthrough) { _defaultFallthrough = defaultFallthrough; }
439 TEXCOORDTRANSFORM0 = MaterialKey::NUM_FLAGS,
451 std::unordered_map<uint, bool> getPropertyFallthroughs() {
return _propertyFallthroughs; }
452 bool getPropertyFallthrough(uint property) {
return _propertyFallthroughs[property]; }
453 void setPropertyDoesFallthrough(uint property) { _propertyFallthroughs[property] =
true; }
455 virtual bool isProcedural()
const {
return false; }
456 virtual bool isEnabled()
const {
return true; }
457 virtual bool isReady()
const {
return true; }
458 virtual QString getProceduralString()
const {
return QString(); }
460 virtual bool isReference()
const {
return false; }
462 virtual bool isMToon()
const {
return false; }
463 static const glm::vec3 DEFAULT_SHADE;
464 virtual glm::vec3 getShade(
bool SRGB =
true)
const {
return glm::vec3(0.0f); }
465 static const float DEFAULT_SHADING_SHIFT;
466 virtual float getShadingShift()
const {
return 0.0f; }
467 static const float DEFAULT_SHADING_TOONY;
468 virtual float getShadingToony()
const {
return 0.0f; }
469 static const glm::vec3 DEFAULT_MATCAP;
470 virtual glm::vec3 getMatcap(
bool SRGB =
true)
const {
return glm::vec3(0.0f); }
471 static const glm::vec3 DEFAULT_PARAMETRIC_RIM;
472 virtual glm::vec3 getParametricRim(
bool SRGB =
true)
const {
return glm::vec3(0.0f); }
473 static const float DEFAULT_PARAMETRIC_RIM_FRESNEL_POWER;
474 virtual float getParametricRimFresnelPower()
const {
return 0.0f; }
475 static const float DEFAULT_PARAMETRIC_RIM_LIFT;
476 virtual float getParametricRimLift()
const {
return 0.0f; }
477 static const float DEFAULT_RIM_LIGHTING_MIX;
478 virtual float getRimLightingMix()
const {
return 0.0f; }
479 static const float DEFAULT_UV_ANIMATION_SCROLL_SPEED;
480 virtual float getUVAnimationScrollXSpeed()
const {
return 0.0f; }
481 virtual float getUVAnimationScrollYSpeed()
const {
return 0.0f; }
482 virtual float getUVAnimationRotationSpeed()
const {
return 0.0f; }
484 static const glm::vec3 DEFAULT_OUTLINE;
485 virtual uint8_t getOutlineWidthMode() {
return 0; }
486 virtual float getOutlineWidth() {
return 0.0f; }
487 virtual glm::vec3 getOutline(
bool SRGB =
true)
const {
return glm::vec3(0.0f); }
489 static const std::string HIFI_PBR;
490 static const std::string HIFI_SHADER_SIMPLE;
491 static const std::string VRM_MTOON;
494 std::string _name {
"" };
495 mutable MaterialKey _key { 0 };
496 std::string _model { HIFI_PBR };
497 uint8_t _layers { 1 };
501 glm::vec3 _emissive { DEFAULT_EMISSIVE };
502 float _opacity { DEFAULT_OPACITY };
503 glm::vec3 _albedo { DEFAULT_ALBEDO };
504 float _roughness { DEFAULT_ROUGHNESS };
505 float _metallic { DEFAULT_METALLIC };
506 float _scattering { DEFAULT_SCATTERING };
507 float _opacityCutoff { DEFAULT_OPACITY_CUTOFF };
508 std::array<glm::mat4, NUM_TEXCOORD_TRANSFORMS> _texcoordTransforms;
509 glm::vec2 _lightmapParams { 0.0, 1.0 };
510 glm::vec2 _materialParams { 0.0, 1.0 };
511 MaterialKey::CullFaceMode _cullFaceMode { DEFAULT_CULL_FACE_MODE };
512 TextureMaps _textureMaps;
513 SamplerMap _samplers;
514 TexCoordSetMap _texCoordSets;
516 bool _defaultFallthrough {
false };
517 std::unordered_map<uint, bool> _propertyFallthroughs { NUM_TOTAL_FLAGS };
519 mutable std::recursive_mutex _textureMapsMutex;
521 typedef std::shared_ptr<Material> MaterialPointer;
523 class MaterialLayer {
525 MaterialLayer(MaterialPointer material, quint16 priority) : material(material), priority(priority) {}
527 MaterialPointer material {
nullptr };
528 quint16 priority { 0 };
531 class MaterialLayerCompare {
533 bool operator() (MaterialLayer left, MaterialLayer right) {
534 return left.priority < right.priority;
537 typedef std::priority_queue<MaterialLayer, std::vector<MaterialLayer>, MaterialLayerCompare> MaterialLayerQueue;
539 class MultiMaterial :
public MaterialLayerQueue {
543 void push(
const MaterialLayer& value) {
544 MaterialLayerQueue::push(value);
545 _hasCalculatedTextureInfo =
false;
549 bool remove(
const MaterialPointer& value) {
551 while (it != c.end()) {
552 if (it->material == value) {
559 std::make_heap(c.begin(), c.end(), comp);
560 _hasCalculatedTextureInfo =
false;
571 glm::vec3 _emissive { Material::DEFAULT_EMISSIVE };
572 float _opacity { Material::DEFAULT_OPACITY };
574 glm::vec3 _albedo { Material::DEFAULT_ALBEDO };
575 float _roughness { Material::DEFAULT_ROUGHNESS };
577 float _metallic { Material::DEFAULT_METALLIC };
578 float _scattering { Material::DEFAULT_SCATTERING };
579 float _opacityCutoff { Material::DEFAULT_OPACITY_CUTOFF };
583 glm::mat4 _texcoordTransforms[Material::NUM_TEXCOORD_TRANSFORMS];
587 glm::vec2 _materialParams { 0.0, 1.0 };
589 glm::vec2 _lightmapParams { 0.0, 1.0 };
591 glm::vec3 spare { 0.0f };
592 uint32_t _texCoordSets { 0 };
595 for (
auto& transform : _texcoordTransforms) {
596 transform = glm::mat4();
600 void setTexCoordSet(
int channel,
int texCoordSet) {
602 const int MAX_TEX_COORD_SET = 1;
603 _texCoordSets |= std::min(texCoordSet, MAX_TEX_COORD_SET) << (2 * channel);
609 glm::vec3 _emissive { Material::DEFAULT_EMISSIVE };
610 float _opacity { Material::DEFAULT_OPACITY };
612 glm::vec3 _albedo { Material::DEFAULT_ALBEDO };
613 float _opacityCutoff { Material::DEFAULT_OPACITY_CUTOFF };
615 glm::vec3 _shade { Material::DEFAULT_SHADE };
616 float _shadingShift { Material::DEFAULT_SHADING_SHIFT };
618 glm::vec3 _matcap { Material::DEFAULT_MATCAP };
619 float _shadingToony { Material::DEFAULT_SHADING_TOONY };
621 glm::vec3 _parametricRim { Material::DEFAULT_PARAMETRIC_RIM };
622 float _parametricRimFresnelPower { Material::DEFAULT_PARAMETRIC_RIM_FRESNEL_POWER };
624 float _parametricRimLift { Material::DEFAULT_PARAMETRIC_RIM_LIFT };
625 float _rimLightingMix { Material::DEFAULT_RIM_LIGHTING_MIX };
626 glm::vec2 _uvAnimationScrollSpeed { Material::DEFAULT_UV_ANIMATION_SCROLL_SPEED };
628 float _uvAnimationScrollRotationSpeed { Material::DEFAULT_UV_ANIMATION_SCROLL_SPEED };
629 float _time { 0.0f };
631 float _spare { 0.0f };
634 glm::mat4 _texcoordTransforms[Material::NUM_TEXCOORD_TRANSFORMS];
638 glm::vec2 _materialParams { 0.0, 1.0 };
640 uint32_t _texCoordSets { 0 };
642 float spare { 0.0f };
645 for (
auto& transform : _texcoordTransforms) {
646 transform = glm::mat4();
650 void setTexCoordSet(
int channel,
int texCoordSet) {
652 const int MAX_TEX_COORD_SET = 1;
653 _texCoordSets |= std::min(texCoordSet, MAX_TEX_COORD_SET) << (2 * channel);
657 void setMaterialKey(
const graphics::MaterialKey& materialKey) { _materialKey = materialKey; }
658 graphics::MaterialKey getMaterialKey()
const {
return _materialKey; }
659 gpu::BufferView& getSchemaBuffer() {
return _schemaBuffer; }
660 glm::vec4 getTopColor()
const;
661 bool isInvisible()
const;
662 const std::array<gpu::TextureTablePointer, 3>& getTextureTables()
const {
return _textureTables; }
664 void setCullFaceMode(graphics::MaterialKey::CullFaceMode cullFaceMode) { _cullFaceMode = cullFaceMode; }
665 graphics::MaterialKey::CullFaceMode getCullFaceMode()
const {
return _cullFaceMode; }
667 uint8_t getLayers()
const {
return _layers; }
669 void setNeedsUpdate(
bool needsUpdate) { _needsUpdate = needsUpdate; }
670 void setTexturesLoading(
bool value) { _texturesLoading = value; }
671 void setInitialized() { _initialized =
true; }
673 bool shouldUpdate()
const {
return !_initialized || _needsUpdate || _texturesLoading || anyReferenceMaterialsOrTexturesChanged(); }
675 int getTextureCount()
const { calculateMaterialInfo();
return _textureCount; }
676 size_t getTextureSize()
const { calculateMaterialInfo();
return _textureSize; }
677 bool hasTextureInfo()
const {
return _hasCalculatedTextureInfo; }
679 void resetReferenceTexturesAndMaterials();
680 void addReferenceTexture(
const std::function<gpu::TexturePointer()>& textureOperator);
681 void addReferenceMaterial(
const std::function<graphics::MaterialPointer()>& materialOperator);
683 void setisMToonAndLayers(
bool isMToon, uint8_t layers);
684 bool isMToon()
const {
return _isMToon; }
686 bool hasOutline()
const {
return _outlineWidthMode != 0 && _outlineWidth > 0.0f; }
687 uint8_t getOutlineWidthMode()
const {
return _outlineWidthMode; }
688 float getOutlineWidth()
const {
return _outlineWidth; }
689 glm::vec3 getOutline()
const {
return _outline; }
690 void resetOutline() { _outlineWidthMode = 0; _outlineWidth = 0.0f; _outline = glm::vec3(0.0f); }
691 void setOutlineWidthMode(uint8_t mode) { _outlineWidthMode = mode; }
692 void setOutlineWidth(
float width) { _outlineWidth = width; }
693 void setOutline(
const glm::vec3& outline) { _outline = outline; }
695 void setSplatMap(
const gpu::TexturePointer& splatMap) { _splatMap = splatMap; }
696 const gpu::TexturePointer& getSplatMap()
const {
return _splatMap; }
697 bool isSplatMap()
const {
return (
bool)_splatMap; }
699 void addSamplerFunc(std::function<
void(
void)> samplerFunc) { _samplerFuncs.push_back(samplerFunc); }
700 void resetSamplers() { _samplerFuncs.clear(); }
701 void applySamplers()
const;
704 graphics::MaterialKey _materialKey;
705 gpu::BufferView _schemaBuffer;
706 std::array<gpu::TextureTablePointer, 3> _textureTables;
707 graphics::MaterialKey::CullFaceMode _cullFaceMode { graphics::Material::DEFAULT_CULL_FACE_MODE };
708 gpu::TexturePointer _splatMap {
nullptr };
709 bool _needsUpdate {
false };
710 bool _texturesLoading {
false };
711 bool _initialized {
false };
712 uint8_t _layers { 1 };
714 mutable size_t _textureSize { 0 };
715 mutable int _textureCount { 0 };
716 mutable bool _hasCalculatedTextureInfo {
false };
717 void calculateMaterialInfo()
const;
719 bool anyReferenceMaterialsOrTexturesChanged()
const;
721 std::vector<std::pair<std::function<gpu::TexturePointer()>, gpu::TexturePointer>> _referenceTextures;
722 std::vector<std::pair<std::function<graphics::MaterialPointer()>, graphics::MaterialPointer>> _referenceMaterials;
724 bool _isMToon {
false };
725 uint8_t _outlineWidthMode { 0 };
726 float _outlineWidth { 0.0f };
727 glm::vec3 _outline { graphics::Material::DEFAULT_OUTLINE };
729 std::vector<std::function<void(
void)>> _samplerFuncs;