28 #include <type_traits>
40 two_sided = other.two_sided;
41 blend_mode = other.blend_mode;
42 shadow_mode = other.shadow_mode;
44 shader_template = other.shader_template;
47 for (
const auto& [key, value]: other.variable_map)
51 variable_map.emplace(key, value->clone());
55 m_hash = other.m_hash;
62 this->two_sided = two_sided;
90 this->shader_template = shader_template;
97 variable_map[key] = std::move(value);
102 if (
auto i = variable_map.find(key); i != variable_map.end())
110 void material::rehash() noexcept
115 m_hash = shader_template->hash();
118 m_hash =
hash_combine(m_hash, std::hash<bool>{}(two_sided));
119 m_hash =
hash_combine(m_hash, std::hash<material_blend_mode>{}(blend_mode));
120 m_hash =
hash_combine(m_hash, std::hash<material_shadow_mode>{}(shadow_mode));
121 m_hash =
hash_combine(m_hash, std::hash<std::uint32_t>{}(flags));
126 template <
typename T>
131 *value =
element.value().get<T>();
144 auto variable = std::make_shared<render::matvar_texture_1d>(
json.size());
159 auto variable = std::make_shared<render::matvar_texture_1d>(
json.size());
176 auto variable = std::make_shared<render::matvar_texture_2d>(
json.size());
191 auto variable = std::make_shared<render::matvar_texture_2d>(
json.size());
208 auto variable = std::make_shared<render::matvar_texture_3d>(
json.size());
223 auto variable = std::make_shared<render::matvar_texture_3d>(
json.size());
240 auto variable = std::make_shared<render::matvar_texture_cube>(
json.size());
255 auto variable = std::make_shared<render::matvar_texture_cube>(
json.size());
266 template <
typename T>
273 auto variable = std::make_shared<render::material_variable<T>>(
json.size());
279 variable->set(i,
element.get<T>());
292 template <
typename T>
296 if (
json.is_array() &&
json.begin().value().is_array())
299 auto variable = std::make_shared<render::material_variable<T>>(
json.size());
303 for (
const auto& vector_element:
json)
308 for (
const auto& value_element: vector_element)
309 value[
j++] = value_element.get<
typename T::element_type>();
311 variable->set(i, value);
323 for (
const auto& value_element:
json)
324 value[
i++] = value_element.get<
typename T::element_type>();
332 template <
typename T>
336 if (
json.is_array() &&
json.begin().value().is_array())
338 if (
json.begin().value().begin().value().is_array())
341 auto variable = std::make_shared<render::material_variable<T>>(
json.size());
345 for (
const auto& matrix_element:
json)
350 for (
const auto& column_element: matrix_element)
353 for (
const auto& row_element: column_element)
355 value[
j][
k] = row_element.get<
typename T::element_type>();
363 variable->set(i, value);
377 for (
const auto& column_element:
json)
380 for (
const auto& row_element: column_element)
382 value[
i][
j] = row_element.get<
typename T::element_type>();
401 auto material = std::make_unique<render::material>();
407 bool two_sided =
false;
408 read_value(&two_sided, *
json,
"two_sided");
412 std::string blend_mode;
413 read_value(&blend_mode, *
json,
"blend_mode");
414 if (blend_mode ==
"opaque")
418 else if (blend_mode ==
"masked")
422 else if (blend_mode ==
"translucent")
428 std::string shadow_mode;
429 read_value(&shadow_mode, *
json,
"shadow_mode");
430 if (shadow_mode ==
"opaque")
434 else if (shadow_mode ==
"none")
440 std::uint32_t flags = 0;
443 std::string depth_mode;
444 read_value(&depth_mode, *
json,
"depth_mode");
445 if (depth_mode ==
"in_front")
449 std::string decal_mode;
450 read_value(&decal_mode, *
json,
"decal_mode");
451 if (decal_mode ==
"decal")
453 else if (decal_mode ==
"surface")
460 std::string shader_template_filename;
461 if (read_value(&shader_template_filename, *
json,
"shader_template"))
468 if (
auto variables_element =
json->find(
"variables"); variables_element !=
json->end())
470 for (
const auto& variable_element: variables_element.value())
474 if (!read_value(&name, variable_element,
"name"))
482 if (!read_value(&
type, variable_element,
"type"))
489 auto value_element = variable_element.find(
"value");
490 if (value_element == variable_element.end())
499 if (
type ==
"texture_1d")
501 load_texture_1d_property(
resource_manager, *material, key, value_element.value());
503 else if (
type ==
"texture_2d")
505 load_texture_2d_property(
resource_manager, *material, key, value_element.value());
507 else if (
type ==
"texture_3d")
509 load_texture_3d_property(
resource_manager, *material, key, value_element.value());
511 else if (
type ==
"texture_cube")
513 load_texture_cube_property(
resource_manager, *material, key, value_element.value());
516 else if (
type[
type.size() - 2] ==
'x' &&
517 std::isdigit(
type[
type.size() - 3]) &&
518 std::isdigit(
type.back()))
520 std::size_t columns = std::stoul(
type.substr(
type.size() - 3, 1));
521 std::size_t rows = std::stoul(
type.substr(
type.size() - 1, 1));
523 if (
type.find(
"float") != std::string::npos)
525 if (columns == 2 && rows == 2)
526 load_matrix_property<math::fmat2>(*material, key, columns, rows, value_element.value());
527 else if (columns == 3 && rows == 3)
528 load_matrix_property<math::fmat3>(*material, key, columns, rows, value_element.value());
529 else if (columns == 4 && rows == 4)
530 load_matrix_property<math::fmat4>(*material, key, columns, rows, value_element.value());
534 else if (std::isdigit(
type.back()))
536 std::size_t size = std::stoul(
type.substr(
type.size() - 1, 1));
538 if (
type.find(
"float") != std::string::npos)
541 load_vector_property<math::fvec2>(*material, key, size, value_element.value());
543 load_vector_property<math::fvec3>(*material, key, size, value_element.value());
545 load_vector_property<math::fvec4>(*material, key, size, value_element.value());
547 else if (
type.find(
"uint") != std::string::npos)
550 load_vector_property<math::uvec2>(*material, key, size, value_element.value());
552 load_vector_property<math::uvec3>(*material, key, size, value_element.value());
554 load_vector_property<math::uvec4>(*material, key, size, value_element.value());
556 else if (
type.find(
"int") != std::string::npos)
559 load_vector_property<math::ivec2>(*material, key, size, value_element.value());
561 load_vector_property<math::ivec3>(*material, key, size, value_element.value());
563 load_vector_property<math::ivec4>(*material, key, size, value_element.value());
565 else if (
type.find(
"bool") != std::string::npos)
568 load_vector_property<math::bvec2>(*material, key, size, value_element.value());
570 load_vector_property<math::bvec3>(*material, key, size, value_element.value());
572 load_vector_property<math::bvec4>(*material, key, size, value_element.value());
578 if (
type.find(
"float") != std::string::npos)
579 load_scalar_property<float>(*material, key, value_element.value());
580 else if (
type.find(
"uint") != std::string::npos)
581 load_scalar_property<unsigned int>(*material, key, value_element.value());
582 else if (
type.find(
"int") != std::string::npos)
583 load_scalar_property<int>(*material, key, value_element.value());
584 else if (
type.find(
"bool") != std::string::npos)
585 load_scalar_property<bool>(*material, key, value_element.value());
Template used to for generating one or more shader variants from a single source.
A material is associated with exactly one shader program and contains a set of material properties wh...
void set_variable(hash::fnv1a32_t key, std::shared_ptr< material_variable_base > value)
Sets the value of a material variable with the given name.
material()=default
Constructs a material.
void set_two_sided(bool two_sided) noexcept
Enables or disables back-face culling of the material surface.
std::shared_ptr< material_variable_base > get_variable(hash::fnv1a32_t key) const
Returns a shared pointer to the material variable with the given name, or nullptr if not found.
material & operator=(const material &other)
Makes this material a copy of aother material.
void set_flags(std::uint32_t flags) noexcept
Sets the material flags.
void set_blend_mode(material_blend_mode mode) noexcept
Sets the material blend mode.
void set_shadow_mode(material_shadow_mode mode) noexcept
Sets the material shadow mode.
void set_shader_template(std::shared_ptr< gl::shader_template > shader_template)
Sets the material's shader template.
static std::unique_ptr< T > load(::resource_manager &resource_manager, deserialize_context &ctx)
Loads a resource.
Manages the loading, caching, and saving of resources.
std::shared_ptr< T > load(const std::filesystem::path &path)
Loads and caches a resource.
constexpr std::uint32_t hash_combine(std::uint32_t x, std::uint32_t y) noexcept
Combines two hash values.
nlohmann::json json
JSON data.
#define MATERIAL_FLAG_DECAL
#define MATERIAL_FLAG_DECAL_SURFACE
#define MATERIAL_FLAG_X_RAY
material_blend_mode
Material blend modes.
@ opaque
Material is fully opaque.
@ masked
Material has binary masked opacity.
@ translucent
Material is translucent.
material_shadow_mode
Material shadow casting modes.
@ none
Material does not cast shadows.
@ opaque
Material casts fully opaque shadows.
Provides access to a deserialization state.
32-bit FNV-1a hash value.