💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
5.2 KiB

  1. /*
  2. * Copyright (C) 2023 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ANTKEEPER_RENDER_MATERIAL_HPP
  20. #define ANTKEEPER_RENDER_MATERIAL_HPP
  21. #include <cstdint>
  22. #include <engine/gl/shader-template.hpp>
  23. #include <engine/render/material-blend-mode.hpp>
  24. #include <engine/render/material-variable.hpp>
  25. #include <engine/render/material-shadow-mode.hpp>
  26. #include <engine/utility/hash/fnv1a.hpp>
  27. #include <unordered_map>
  28. namespace render {
  29. /**
  30. * A material is associated with exactly one shader program and contains a set of material properties which can be uploaded to that shader program via shader inputs.
  31. */
  32. class material
  33. {
  34. public:
  35. /**
  36. * Constructs a material.
  37. */
  38. material() = default;
  39. /**
  40. * Constructs a copy of another material.
  41. *
  42. * @param other Material to copy.
  43. */
  44. material(const material& other);
  45. /**
  46. * Destroys a material.
  47. */
  48. ~material() = default;
  49. /**
  50. * Makes this material a copy of aother material.
  51. *
  52. * @param other Material to copy.
  53. * @return Reference to this material.
  54. */
  55. material& operator=(const material& other);
  56. /// @name Settings
  57. /// @{
  58. /**
  59. * Enables or disables back-face culling of the material surface.
  60. *
  61. * @param two_sided `true` to disable back-face culling, or `false` to enable it.
  62. */
  63. void set_two_sided(bool two_sided) noexcept;
  64. /**
  65. * Sets the material blend mode.
  66. *
  67. * @param mode Blend mode.
  68. */
  69. void set_blend_mode(material_blend_mode mode) noexcept;
  70. /**
  71. * Sets the material shadow mode.
  72. *
  73. * @param mode Shadow mode.
  74. */
  75. void set_shadow_mode(material_shadow_mode mode) noexcept;
  76. /**
  77. * Sets the material flags.
  78. *
  79. * @param flags Material flags.
  80. */
  81. void set_flags(std::uint32_t flags) noexcept;
  82. /// Returns `true` if the material surface is two-sided, and `false` otherwise.
  83. [[nodiscard]] inline bool is_two_sided() const noexcept
  84. {
  85. return two_sided;
  86. }
  87. /// Returns the material blend mode.
  88. [[nodiscard]] inline material_blend_mode get_blend_mode() const noexcept
  89. {
  90. return blend_mode;
  91. }
  92. /// Returns the material shadow mode.
  93. [[nodiscard]] inline material_shadow_mode get_shadow_mode() const noexcept
  94. {
  95. return shadow_mode;
  96. }
  97. /// Returns the material flags.
  98. [[nodiscard]] inline std::uint32_t get_flags() const noexcept
  99. {
  100. return flags;
  101. }
  102. /// @}
  103. /// @name Shading
  104. /// @{
  105. /**
  106. * Sets the material's shader template.
  107. *
  108. * @param shader_template Shader template with which to associate the material.
  109. */
  110. void set_shader_template(std::shared_ptr<gl::shader_template> shader_template);
  111. /**
  112. * Returns the shader template with which this material is associated.
  113. */
  114. [[nodiscard]] inline const std::shared_ptr<gl::shader_template>& get_shader_template() const noexcept
  115. {
  116. return shader_template;
  117. }
  118. /**
  119. * Sets the value of a material variable with the given name.
  120. *
  121. * @param key 32-bit FNV-1a hash value of the variable name.
  122. * @param value Shared pointer to the material variable value.
  123. */
  124. void set_variable(hash::fnv1a32_t key, std::shared_ptr<material_variable_base> value);
  125. /**
  126. * Returns a shared pointer to the material variable with the given name, or `nullptr` if not found.
  127. *
  128. * @param key 32-bit FNV-1a hash value of the variable name.
  129. *
  130. * @return Shared pointer to the material variable with the given name, or `nullptr` if not found.
  131. */
  132. [[nodiscard]] std::shared_ptr<material_variable_base> get_variable(hash::fnv1a32_t key) const;
  133. /**
  134. * Returns all material variables.
  135. *
  136. * @return Map of 32-bit FNV-1a hash values of variable names to variables.
  137. */
  138. [[nodiscard]] inline const std::unordered_map<hash::fnv1a32_t, std::shared_ptr<material_variable_base>>& get_variables() const noexcept
  139. {
  140. return variable_map;
  141. }
  142. /// @}
  143. /**
  144. * Returns a hash of the material state.
  145. *
  146. * The followings functions may change the material hash:
  147. *
  148. * * material::set_shader_template
  149. * * material::set_flags
  150. * * material::set_blend_mode
  151. * * material::set_two_sided
  152. * * material::set_shadow_mode
  153. */
  154. [[nodiscard]] inline std::size_t hash() const noexcept
  155. {
  156. return m_hash;
  157. }
  158. private:
  159. /**
  160. * Recalculates the material state hash.
  161. */
  162. void rehash() noexcept;
  163. bool two_sided{false};
  164. material_blend_mode blend_mode{material_blend_mode::opaque};
  165. material_shadow_mode shadow_mode{material_shadow_mode::opaque};
  166. std::uint32_t flags{0};
  167. std::shared_ptr<gl::shader_template> shader_template;
  168. std::unordered_map<hash::fnv1a32_t, std::shared_ptr<material_variable_base>> variable_map;
  169. std::size_t m_hash{0};
  170. };
  171. } // namespace render
  172. #endif // ANTKEEPER_RENDER_MATERIAL_HPP