💿🐜 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.

375 lines
8.4 KiB

  1. /*
  2. * Copyright (C) 2020 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_MATERIAL_PROPERTY_HPP
  20. #define ANTKEEPER_MATERIAL_PROPERTY_HPP
  21. #include "animation/tween.hpp"
  22. #include "rasterizer/shader-variable-type.hpp"
  23. #include "rasterizer/shader-input.hpp"
  24. #include <vmq/vmq.hpp>
  25. #include <cstdlib>
  26. using namespace vmq::types;
  27. class material;
  28. class shader_program;
  29. class texture_2d;
  30. class texture_cube;
  31. /**
  32. * Abstract base class for material properties.
  33. */
  34. class material_property_base
  35. {
  36. public:
  37. /**
  38. * Connects the material property to a shader input.
  39. *
  40. * @param input Shader input to which the material property should be connected.
  41. * @return `true` if the property was connected to the input successfully, `false` otherwise.
  42. */
  43. bool connect(const shader_input* input);
  44. /**
  45. * Disconnects the material property from its shader input.
  46. */
  47. void disconnect();
  48. /**
  49. * Sets state 0 = state 1.
  50. */
  51. virtual void update_tweens() = 0;
  52. /**
  53. * Uploads the material property to its shader program.
  54. *
  55. * @param a Interpolation factor. Should be on `[0.0, 1.0]`.
  56. * @return `true` if the property was uploaded successfully, `false` otherwise.
  57. */
  58. virtual bool upload(double a) const = 0;
  59. /**
  60. * Returns the type of data which the property contains.
  61. */
  62. virtual shader_variable_type get_data_type() const = 0;
  63. /**
  64. * Returns `true` if the material property is connected to a shader input, `false` otherwise.
  65. */
  66. bool is_connected() const;
  67. /**
  68. * Creates a copy of this material property.
  69. */
  70. virtual material_property_base* clone() const = 0;
  71. protected:
  72. material_property_base();
  73. const shader_input* input;
  74. };
  75. inline bool material_property_base::is_connected() const
  76. {
  77. return (input != nullptr);
  78. }
  79. /**
  80. * A property of a material which can be uploaded to a shader program via a shader input.
  81. *
  82. * @tparam T Property data type.
  83. */
  84. template <class T>
  85. class material_property: public material_property_base
  86. {
  87. public:
  88. /**
  89. * Creates a material property.
  90. *
  91. * @param element_count Number of elements in the property array.
  92. */
  93. material_property(std::size_t element_count);
  94. /**
  95. * Destroys a material property.
  96. */
  97. virtual ~material_property();
  98. material_property(const material_property<T>&) = delete;
  99. material_property<T>& operator=(const material_property<T>&) = delete;
  100. /// @copydoc material_property_base::update_tweens()
  101. virtual void update_tweens();
  102. /// @copydoc material_property_base::upload() const
  103. virtual bool upload(double a) const;
  104. /**
  105. * Sets the value of this property.
  106. *
  107. * @param value Value to set.
  108. */
  109. void set_value(const T& value);
  110. void set_val(const T& value);
  111. /**
  112. * Sets the value of a single element in this array property.
  113. *
  114. * @param index Index of an array element.
  115. * @param value Value to set.
  116. */
  117. void set_value(std::size_t index, const T& value);
  118. /**
  119. * Sets the values of a range of elements in this array property.
  120. *
  121. * @param index Index of the first array element to set.
  122. * @param values Pointer to an array of values to set.
  123. * @param count Number of elements to set.
  124. */
  125. void set_values(std::size_t index, const T* values, std::size_t count);
  126. /// @copydoc material_property_base::get_data_type() const
  127. virtual shader_variable_type get_data_type() const;
  128. /// @copydoc material_property_base::clone() const
  129. virtual material_property_base* clone() const;
  130. private:
  131. std::size_t element_count;
  132. tween<T>* values;
  133. };
  134. template <class T>
  135. material_property<T>::material_property(std::size_t element_count):
  136. element_count(element_count),
  137. values(nullptr)
  138. {
  139. values = new tween<T>[element_count];
  140. }
  141. template <class T>
  142. material_property<T>::~material_property()
  143. {
  144. delete[] values;
  145. }
  146. template <class T>
  147. void material_property<T>::update_tweens()
  148. {
  149. for (std::size_t i = 0; i < element_count; ++i)
  150. {
  151. values[i].update();
  152. }
  153. }
  154. template <class T>
  155. bool material_property<T>::upload(double a) const
  156. {
  157. if (!is_connected())
  158. {
  159. return false;
  160. }
  161. if (element_count > 1)
  162. {
  163. for (std::size_t i = 0; i < element_count; ++i)
  164. {
  165. if (!input->upload(i, values[i].interpolate(a)))
  166. return false;
  167. }
  168. return true;
  169. }
  170. else
  171. {
  172. return input->upload(values[0].interpolate(a));
  173. }
  174. }
  175. template <class T>
  176. void material_property<T>::set_value(const T& value)
  177. {
  178. values[0][1] = value;
  179. }
  180. template <class T>
  181. void material_property<T>::set_val(const T& value)
  182. {
  183. values[0][1] = value;
  184. }
  185. template <class T>
  186. void material_property<T>::set_value(std::size_t index, const T& value)
  187. {
  188. values[index][1] = value;
  189. }
  190. template <class T>
  191. void material_property<T>::set_values(std::size_t index, const T* values, std::size_t count)
  192. {
  193. for (std::size_t i = 0; i < count; ++i)
  194. {
  195. this->values[index + i][1] = values[i];
  196. }
  197. }
  198. template <>
  199. inline shader_variable_type material_property<bool>::get_data_type() const
  200. {
  201. return shader_variable_type::bool1;
  202. }
  203. template <>
  204. inline shader_variable_type material_property<bool2>::get_data_type() const
  205. {
  206. return shader_variable_type::bool2;
  207. }
  208. template <>
  209. inline shader_variable_type material_property<bool3>::get_data_type() const
  210. {
  211. return shader_variable_type::bool3;
  212. }
  213. template <>
  214. inline shader_variable_type material_property<bool4>::get_data_type() const
  215. {
  216. return shader_variable_type::bool4;
  217. }
  218. template <>
  219. inline shader_variable_type material_property<int>::get_data_type() const
  220. {
  221. return shader_variable_type::int1;
  222. }
  223. template <>
  224. inline shader_variable_type material_property<int2>::get_data_type() const
  225. {
  226. return shader_variable_type::int2;
  227. }
  228. template <>
  229. inline shader_variable_type material_property<int3>::get_data_type() const
  230. {
  231. return shader_variable_type::int3;
  232. }
  233. template <>
  234. inline shader_variable_type material_property<int4>::get_data_type() const
  235. {
  236. return shader_variable_type::int4;
  237. }
  238. template <>
  239. inline shader_variable_type material_property<unsigned int>::get_data_type() const
  240. {
  241. return shader_variable_type::uint1;
  242. }
  243. template <>
  244. inline shader_variable_type material_property<uint2>::get_data_type() const
  245. {
  246. return shader_variable_type::uint2;
  247. }
  248. template <>
  249. inline shader_variable_type material_property<uint3>::get_data_type() const
  250. {
  251. return shader_variable_type::uint3;
  252. }
  253. template <>
  254. inline shader_variable_type material_property<uint4>::get_data_type() const
  255. {
  256. return shader_variable_type::uint4;
  257. }
  258. template <>
  259. inline shader_variable_type material_property<float>::get_data_type() const
  260. {
  261. return shader_variable_type::float1;
  262. }
  263. template <>
  264. inline shader_variable_type material_property<float2>::get_data_type() const
  265. {
  266. return shader_variable_type::float2;
  267. }
  268. template <>
  269. inline shader_variable_type material_property<float3>::get_data_type() const
  270. {
  271. return shader_variable_type::float3;
  272. }
  273. template <>
  274. inline shader_variable_type material_property<float4>::get_data_type() const
  275. {
  276. return shader_variable_type::float4;
  277. }
  278. template <>
  279. inline shader_variable_type material_property<float2x2>::get_data_type() const
  280. {
  281. return shader_variable_type::float2x2;
  282. }
  283. template <>
  284. inline shader_variable_type material_property<float3x3>::get_data_type() const
  285. {
  286. return shader_variable_type::float3x3;
  287. }
  288. template <>
  289. inline shader_variable_type material_property<float4x4>::get_data_type() const
  290. {
  291. return shader_variable_type::float4x4;
  292. }
  293. template <>
  294. inline shader_variable_type material_property<const texture_2d*>::get_data_type() const
  295. {
  296. return shader_variable_type::texture_2d;
  297. }
  298. template <>
  299. inline shader_variable_type material_property<const texture_cube*>::get_data_type() const
  300. {
  301. return shader_variable_type::texture_cube;
  302. }
  303. template <class T>
  304. material_property_base* material_property<T>::clone() const
  305. {
  306. material_property<T>* property = new material_property<T>(element_count);
  307. for (std::size_t i = 0; i < element_count; ++i)
  308. {
  309. property->values[i][0] = values[i][0];
  310. property->values[i][1] = values[i][1];
  311. }
  312. property->input = input;
  313. return property;
  314. }
  315. #endif // ANTKEEPER_MATERIAL_PROPERTY_HPP