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

666 lines
23 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. #include <engine/gl/opengl/gl-shader-variables.hpp>
  20. #include <engine/gl/texture-1d.hpp>
  21. #include <engine/gl/texture-2d.hpp>
  22. #include <engine/gl/texture-3d.hpp>
  23. #include <engine/gl/texture-cube.hpp>
  24. #include <numeric>
  25. namespace gl {
  26. gl_shader_bool::gl_shader_bool(std::size_t size, GLint gl_uniform_location):
  27. shader_variable(size),
  28. gl_uniform_location{gl_uniform_location},
  29. ivalues(size)
  30. {}
  31. void gl_shader_bool::update(bool value) const noexcept
  32. {
  33. glUniform1i(gl_uniform_location, static_cast<GLint>(value));
  34. }
  35. void gl_shader_bool::update(bool value, std::size_t index) const
  36. {
  37. glUniform1i(gl_uniform_location + static_cast<GLint>(index), static_cast<GLint>(value));
  38. }
  39. void gl_shader_bool::update(std::span<const bool> values, std::size_t index) const
  40. {
  41. for (std::size_t i = 0; i < values.size(); ++i)
  42. {
  43. ivalues[i] = static_cast<GLint>(values[i]);
  44. }
  45. glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), ivalues.data());
  46. }
  47. gl_shader_bvec2::gl_shader_bvec2(std::size_t size, GLint gl_uniform_location):
  48. shader_variable(size),
  49. gl_uniform_location{gl_uniform_location},
  50. ivalues(size * 2)
  51. {}
  52. void gl_shader_bvec2::update(const math::bvec2& value) const noexcept
  53. {
  54. glUniform2i(gl_uniform_location, static_cast<GLint>(value[0]), static_cast<GLint>(value[1]));
  55. }
  56. void gl_shader_bvec2::update(const math::bvec2& value, std::size_t index) const
  57. {
  58. glUniform2i(gl_uniform_location + static_cast<GLint>(index), static_cast<GLint>(value[0]), static_cast<GLint>(value[1]));
  59. }
  60. void gl_shader_bvec2::update(std::span<const math::bvec2> values, std::size_t index) const
  61. {
  62. GLint* ivalue = ivalues.data();
  63. for (const auto& value: values)
  64. {
  65. *(++ivalue) = static_cast<GLint>(value[0]);
  66. *(++ivalue) = static_cast<GLint>(value[1]);
  67. }
  68. glUniform2iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), ivalues.data());
  69. }
  70. gl_shader_bvec3::gl_shader_bvec3(std::size_t size, GLint gl_uniform_location):
  71. shader_variable(size),
  72. gl_uniform_location{gl_uniform_location},
  73. ivalues(size * 3)
  74. {}
  75. void gl_shader_bvec3::update(const math::bvec3& value) const noexcept
  76. {
  77. glUniform3i(gl_uniform_location, static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2]));
  78. }
  79. void gl_shader_bvec3::update(const math::bvec3& value, std::size_t index) const
  80. {
  81. glUniform3i(gl_uniform_location + static_cast<GLint>(index), static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2]));
  82. }
  83. void gl_shader_bvec3::update(std::span<const math::bvec3> values, std::size_t index) const
  84. {
  85. GLint* ivalue = ivalues.data();
  86. for (const auto& value: values)
  87. {
  88. *(++ivalue) = static_cast<GLint>(value[0]);
  89. *(++ivalue) = static_cast<GLint>(value[1]);
  90. *(++ivalue) = static_cast<GLint>(value[2]);
  91. }
  92. glUniform3iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), ivalues.data());
  93. }
  94. gl_shader_bvec4::gl_shader_bvec4(std::size_t size, GLint gl_uniform_location):
  95. shader_variable(size),
  96. gl_uniform_location{gl_uniform_location},
  97. ivalues(size * 4)
  98. {}
  99. void gl_shader_bvec4::update(const math::bvec4& value) const noexcept
  100. {
  101. glUniform4i(gl_uniform_location, static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2]), static_cast<GLint>(value[3]));
  102. }
  103. void gl_shader_bvec4::update(const math::bvec4& value, std::size_t index) const
  104. {
  105. glUniform4i(gl_uniform_location + static_cast<GLint>(index), static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2]), static_cast<GLint>(value[3]));
  106. }
  107. void gl_shader_bvec4::update(std::span<const math::bvec4> values, std::size_t index) const
  108. {
  109. GLint* ivalue = ivalues.data();
  110. for (const auto& value: values)
  111. {
  112. *(++ivalue) = static_cast<GLint>(value[0]);
  113. *(++ivalue) = static_cast<GLint>(value[1]);
  114. *(++ivalue) = static_cast<GLint>(value[2]);
  115. *(++ivalue) = static_cast<GLint>(value[3]);
  116. }
  117. glUniform4iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), ivalues.data());
  118. }
  119. gl_shader_int::gl_shader_int(std::size_t size, GLint gl_uniform_location):
  120. shader_variable(size),
  121. gl_uniform_location{gl_uniform_location}
  122. {}
  123. void gl_shader_int::update(int value) const noexcept
  124. {
  125. glUniform1i(gl_uniform_location, value);
  126. }
  127. void gl_shader_int::update(int value, std::size_t index) const
  128. {
  129. glUniform1i(gl_uniform_location + static_cast<GLint>(index), value);
  130. }
  131. void gl_shader_int::update(std::span<const int> values, std::size_t index) const
  132. {
  133. glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data());
  134. }
  135. gl_shader_ivec2::gl_shader_ivec2(std::size_t size, GLint gl_uniform_location):
  136. shader_variable(size),
  137. gl_uniform_location{gl_uniform_location}
  138. {}
  139. void gl_shader_ivec2::update(const math::ivec2& value) const noexcept
  140. {
  141. glUniform2iv(gl_uniform_location, 1, value.data());
  142. }
  143. void gl_shader_ivec2::update(const math::ivec2& value, std::size_t index) const
  144. {
  145. glUniform2iv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
  146. }
  147. void gl_shader_ivec2::update(std::span<const math::ivec2> values, std::size_t index) const
  148. {
  149. glUniform2iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
  150. }
  151. gl_shader_ivec3::gl_shader_ivec3(std::size_t size, GLint gl_uniform_location):
  152. shader_variable(size),
  153. gl_uniform_location{gl_uniform_location}
  154. {}
  155. void gl_shader_ivec3::update(const math::ivec3& value) const noexcept
  156. {
  157. glUniform3iv(gl_uniform_location, 1, value.data());
  158. }
  159. void gl_shader_ivec3::update(const math::ivec3& value, std::size_t index) const
  160. {
  161. glUniform3iv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
  162. }
  163. void gl_shader_ivec3::update(std::span<const math::ivec3> values, std::size_t index) const
  164. {
  165. glUniform3iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
  166. }
  167. gl_shader_ivec4::gl_shader_ivec4(std::size_t size, GLint gl_uniform_location):
  168. shader_variable(size),
  169. gl_uniform_location{gl_uniform_location}
  170. {}
  171. void gl_shader_ivec4::update(const math::ivec4& value) const noexcept
  172. {
  173. glUniform4iv(gl_uniform_location, 1, value.data());
  174. }
  175. void gl_shader_ivec4::update(const math::ivec4& value, std::size_t index) const
  176. {
  177. glUniform4iv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
  178. }
  179. void gl_shader_ivec4::update(std::span<const math::ivec4> values, std::size_t index) const
  180. {
  181. glUniform4iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
  182. }
  183. gl_shader_uint::gl_shader_uint(std::size_t size, GLint gl_uniform_location):
  184. shader_variable(size),
  185. gl_uniform_location{gl_uniform_location}
  186. {}
  187. void gl_shader_uint::update(unsigned int value) const noexcept
  188. {
  189. glUniform1ui(gl_uniform_location, value);
  190. }
  191. void gl_shader_uint::update(unsigned int value, std::size_t index) const
  192. {
  193. glUniform1ui(gl_uniform_location + static_cast<GLint>(index), value);
  194. }
  195. void gl_shader_uint::update(std::span<const unsigned int> values, std::size_t index) const
  196. {
  197. glUniform1uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data());
  198. }
  199. gl_shader_uvec2::gl_shader_uvec2(std::size_t size, GLint gl_uniform_location):
  200. shader_variable(size),
  201. gl_uniform_location{gl_uniform_location}
  202. {}
  203. void gl_shader_uvec2::update(const math::uvec2& value) const noexcept
  204. {
  205. glUniform2uiv(gl_uniform_location, 1, value.data());
  206. }
  207. void gl_shader_uvec2::update(const math::uvec2& value, std::size_t index) const
  208. {
  209. glUniform2uiv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
  210. }
  211. void gl_shader_uvec2::update(std::span<const math::uvec2> values, std::size_t index) const
  212. {
  213. glUniform2uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
  214. }
  215. gl_shader_uvec3::gl_shader_uvec3(std::size_t size, GLint gl_uniform_location):
  216. shader_variable(size),
  217. gl_uniform_location{gl_uniform_location}
  218. {}
  219. void gl_shader_uvec3::update(const math::uvec3& value) const noexcept
  220. {
  221. glUniform3uiv(gl_uniform_location, 1, value.data());
  222. }
  223. void gl_shader_uvec3::update(const math::uvec3& value, std::size_t index) const
  224. {
  225. glUniform3uiv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
  226. }
  227. void gl_shader_uvec3::update(std::span<const math::uvec3> values, std::size_t index) const
  228. {
  229. glUniform3uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
  230. }
  231. gl_shader_uvec4::gl_shader_uvec4(std::size_t size, GLint gl_uniform_location):
  232. shader_variable(size),
  233. gl_uniform_location{gl_uniform_location}
  234. {}
  235. void gl_shader_uvec4::update(const math::uvec4& value) const noexcept
  236. {
  237. glUniform4uiv(gl_uniform_location, 1, value.data());
  238. }
  239. void gl_shader_uvec4::update(const math::uvec4& value, std::size_t index) const
  240. {
  241. glUniform4uiv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
  242. }
  243. void gl_shader_uvec4::update(std::span<const math::uvec4> values, std::size_t index) const
  244. {
  245. glUniform4uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
  246. }
  247. gl_shader_float::gl_shader_float(std::size_t size, GLint gl_uniform_location):
  248. shader_variable(size),
  249. gl_uniform_location{gl_uniform_location}
  250. {}
  251. void gl_shader_float::update(float value) const noexcept
  252. {
  253. glUniform1f(gl_uniform_location, value);
  254. }
  255. void gl_shader_float::update(float value, std::size_t index) const
  256. {
  257. glUniform1f(gl_uniform_location + static_cast<GLint>(index), value);
  258. }
  259. void gl_shader_float::update(std::span<const float> values, std::size_t index) const
  260. {
  261. glUniform1fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data());
  262. }
  263. gl_shader_fvec2::gl_shader_fvec2(std::size_t size, GLint gl_uniform_location):
  264. shader_variable(size),
  265. gl_uniform_location{gl_uniform_location}
  266. {}
  267. void gl_shader_fvec2::update(const math::fvec2& value) const noexcept
  268. {
  269. glUniform2fv(gl_uniform_location, 1, value.data());
  270. }
  271. void gl_shader_fvec2::update(const math::fvec2& value, std::size_t index) const
  272. {
  273. glUniform2fv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
  274. }
  275. void gl_shader_fvec2::update(std::span<const math::fvec2> values, std::size_t index) const
  276. {
  277. glUniform2fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
  278. }
  279. gl_shader_fvec3::gl_shader_fvec3(std::size_t size, GLint gl_uniform_location):
  280. shader_variable(size),
  281. gl_uniform_location{gl_uniform_location}
  282. {}
  283. void gl_shader_fvec3::update(const math::fvec3& value) const noexcept
  284. {
  285. glUniform3fv(gl_uniform_location, 1, value.data());
  286. }
  287. void gl_shader_fvec3::update(const math::fvec3& value, std::size_t index) const
  288. {
  289. glUniform3fv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
  290. }
  291. void gl_shader_fvec3::update(std::span<const math::fvec3> values, std::size_t index) const
  292. {
  293. glUniform3fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
  294. }
  295. gl_shader_fvec4::gl_shader_fvec4(std::size_t size, GLint gl_uniform_location):
  296. shader_variable(size),
  297. gl_uniform_location{gl_uniform_location}
  298. {}
  299. void gl_shader_fvec4::update(const math::fvec4& value) const noexcept
  300. {
  301. glUniform4fv(gl_uniform_location, 1, value.data());
  302. }
  303. void gl_shader_fvec4::update(const math::fvec4& value, std::size_t index) const
  304. {
  305. glUniform4fv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
  306. }
  307. void gl_shader_fvec4::update(std::span<const math::fvec4> values, std::size_t index) const
  308. {
  309. glUniform4fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
  310. }
  311. gl_shader_fmat2::gl_shader_fmat2(std::size_t size, GLint gl_uniform_location):
  312. shader_variable(size),
  313. gl_uniform_location{gl_uniform_location}
  314. {}
  315. void gl_shader_fmat2::update(const math::fmat2& value) const noexcept
  316. {
  317. glUniformMatrix2fv(gl_uniform_location, 1, GL_FALSE, value.data());
  318. }
  319. void gl_shader_fmat2::update(const math::fmat2& value, std::size_t index) const
  320. {
  321. glUniformMatrix2fv(gl_uniform_location + static_cast<GLint>(index) * 2, 1, GL_FALSE, value.data());
  322. }
  323. void gl_shader_fmat2::update(std::span<const math::fmat2> values, std::size_t index) const
  324. {
  325. glUniformMatrix2fv(gl_uniform_location + static_cast<GLint>(index) * 2, static_cast<GLsizei>(values.size()), GL_FALSE, values.data()->data());
  326. }
  327. gl_shader_fmat3::gl_shader_fmat3(std::size_t size, GLint gl_uniform_location):
  328. shader_variable(size),
  329. gl_uniform_location{gl_uniform_location}
  330. {}
  331. void gl_shader_fmat3::update(const math::fmat3& value) const noexcept
  332. {
  333. glUniformMatrix3fv(gl_uniform_location, 1, GL_FALSE, value.data());
  334. }
  335. void gl_shader_fmat3::update(const math::fmat3& value, std::size_t index) const
  336. {
  337. glUniformMatrix3fv(gl_uniform_location + static_cast<GLint>(index) * 3, 1, GL_FALSE, value.data());
  338. }
  339. void gl_shader_fmat3::update(std::span<const math::fmat3> values, std::size_t index) const
  340. {
  341. glUniformMatrix3fv(gl_uniform_location + static_cast<GLint>(index) * 3, static_cast<GLsizei>(values.size()), GL_FALSE, values.data()->data());
  342. }
  343. gl_shader_fmat4::gl_shader_fmat4(std::size_t size, GLint gl_uniform_location):
  344. shader_variable(size),
  345. gl_uniform_location{gl_uniform_location}
  346. {}
  347. void gl_shader_fmat4::update(const math::fmat4& value) const noexcept
  348. {
  349. glUniformMatrix4fv(gl_uniform_location, 1, GL_FALSE, value.data());
  350. }
  351. void gl_shader_fmat4::update(const math::fmat4& value, std::size_t index) const
  352. {
  353. glUniformMatrix4fv(gl_uniform_location + static_cast<GLint>(index) * 4, 1, GL_FALSE, value.data());
  354. }
  355. void gl_shader_fmat4::update(std::span<const math::fmat4> values, std::size_t index) const
  356. {
  357. glUniformMatrix4fv(gl_uniform_location + static_cast<GLint>(index) * 4, static_cast<GLsizei>(values.size()), GL_FALSE, values.data()->data());
  358. }
  359. gl_shader_texture_1d::gl_shader_texture_1d(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_unit_index):
  360. shader_variable(size),
  361. gl_uniform_location{gl_uniform_location},
  362. gl_texture_unit_indices(size)
  363. {
  364. std::iota(gl_texture_unit_indices.begin(), gl_texture_unit_indices.end(), gl_first_texture_unit_index);
  365. }
  366. void gl_shader_texture_1d::update(const texture_1d& value) const noexcept
  367. {
  368. // Bind texture to texture unit
  369. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices.front()));
  370. glBindTexture(GL_TEXTURE_1D, value.m_gl_texture_id);
  371. // Pass texture unit index to shader
  372. glUniform1i(gl_uniform_location, gl_texture_unit_indices.front());
  373. }
  374. void gl_shader_texture_1d::update(const texture_1d& value, std::size_t index) const
  375. {
  376. const GLint gl_texture_index = gl_texture_unit_indices[index];
  377. // Bind texture to texture unit
  378. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_index));
  379. glBindTexture(GL_TEXTURE_1D, value.m_gl_texture_id);
  380. // Pass texture unit index to shader
  381. glUniform1i(gl_uniform_location + static_cast<GLint>(index), gl_texture_index);
  382. }
  383. void gl_shader_texture_1d::update(std::span<const texture_1d* const> values, std::size_t index) const
  384. {
  385. // Bind textures
  386. for (std::size_t i = 0; i < values.size(); ++i)
  387. {
  388. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i]));
  389. glBindTexture(GL_TEXTURE_1D, values[i]->m_gl_texture_id);
  390. }
  391. // Pass texture unit indices to shader
  392. glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]);
  393. }
  394. void gl_shader_texture_1d::update(std::span<const std::shared_ptr<texture_1d>> values, std::size_t index) const
  395. {
  396. // Bind textures
  397. for (std::size_t i = 0; i < values.size(); ++i)
  398. {
  399. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i]));
  400. glBindTexture(GL_TEXTURE_1D, values[i]->m_gl_texture_id);
  401. }
  402. // Pass texture unit indices to shader
  403. glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]);
  404. }
  405. gl_shader_texture_2d::gl_shader_texture_2d(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_unit_index):
  406. shader_variable(size),
  407. gl_uniform_location{gl_uniform_location},
  408. gl_texture_unit_indices(size)
  409. {
  410. std::iota(gl_texture_unit_indices.begin(), gl_texture_unit_indices.end(), gl_first_texture_unit_index);
  411. }
  412. void gl_shader_texture_2d::update(const texture_2d& value) const noexcept
  413. {
  414. // Bind texture to texture unit
  415. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices.front()));
  416. glBindTexture(GL_TEXTURE_2D, value.m_gl_texture_id);
  417. // Pass texture unit index to shader
  418. glUniform1i(gl_uniform_location, gl_texture_unit_indices.front());
  419. }
  420. void gl_shader_texture_2d::update(const texture_2d& value, std::size_t index) const
  421. {
  422. const GLint gl_texture_index = gl_texture_unit_indices[index];
  423. // Bind texture to texture unit
  424. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_index));
  425. glBindTexture(GL_TEXTURE_2D, value.m_gl_texture_id);
  426. // Pass texture unit index to shader
  427. glUniform1i(gl_uniform_location + static_cast<GLint>(index), gl_texture_index);
  428. }
  429. void gl_shader_texture_2d::update(std::span<const texture_2d* const> values, std::size_t index) const
  430. {
  431. // Bind textures
  432. for (std::size_t i = 0; i < values.size(); ++i)
  433. {
  434. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i]));
  435. glBindTexture(GL_TEXTURE_2D, values[i]->m_gl_texture_id);
  436. }
  437. // Pass texture unit indices to shader
  438. glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]);
  439. }
  440. void gl_shader_texture_2d::update(std::span<const std::shared_ptr<texture_2d>> values, std::size_t index) const
  441. {
  442. // Bind textures
  443. for (std::size_t i = 0; i < values.size(); ++i)
  444. {
  445. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i]));
  446. glBindTexture(GL_TEXTURE_2D, values[i]->m_gl_texture_id);
  447. }
  448. // Pass texture unit indices to shader
  449. glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]);
  450. }
  451. gl_shader_texture_3d::gl_shader_texture_3d(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_unit_index):
  452. shader_variable(size),
  453. gl_uniform_location{gl_uniform_location},
  454. gl_texture_unit_indices(size)
  455. {
  456. std::iota(gl_texture_unit_indices.begin(), gl_texture_unit_indices.end(), gl_first_texture_unit_index);
  457. }
  458. void gl_shader_texture_3d::update(const texture_3d& value) const noexcept
  459. {
  460. // Bind texture to texture unit
  461. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices.front()));
  462. glBindTexture(GL_TEXTURE_3D, value.m_gl_texture_id);
  463. // Pass texture unit index to shader
  464. glUniform1i(gl_uniform_location, gl_texture_unit_indices.front());
  465. }
  466. void gl_shader_texture_3d::update(const texture_3d& value, std::size_t index) const
  467. {
  468. const GLint gl_texture_index = gl_texture_unit_indices[index];
  469. // Bind texture to texture unit
  470. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_index));
  471. glBindTexture(GL_TEXTURE_3D, value.m_gl_texture_id);
  472. // Pass texture unit index to shader
  473. glUniform1i(gl_uniform_location + static_cast<GLint>(index), gl_texture_index);
  474. }
  475. void gl_shader_texture_3d::update(std::span<const texture_3d* const> values, std::size_t index) const
  476. {
  477. // Bind textures
  478. for (std::size_t i = 0; i < values.size(); ++i)
  479. {
  480. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i]));
  481. glBindTexture(GL_TEXTURE_3D, values[i]->m_gl_texture_id);
  482. }
  483. // Pass texture unit indices to shader
  484. glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]);
  485. }
  486. void gl_shader_texture_3d::update(std::span<const std::shared_ptr<texture_3d>> values, std::size_t index) const
  487. {
  488. // Bind textures
  489. for (std::size_t i = 0; i < values.size(); ++i)
  490. {
  491. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i]));
  492. glBindTexture(GL_TEXTURE_3D, values[i]->m_gl_texture_id);
  493. }
  494. // Pass texture unit indices to shader
  495. glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]);
  496. }
  497. gl_shader_texture_cube::gl_shader_texture_cube(std::size_t size, GLint gl_uniform_location, GLint gl_first_texture_unit_index):
  498. shader_variable(size),
  499. gl_uniform_location{gl_uniform_location},
  500. gl_texture_unit_indices(size)
  501. {
  502. std::iota(gl_texture_unit_indices.begin(), gl_texture_unit_indices.end(), gl_first_texture_unit_index);
  503. }
  504. void gl_shader_texture_cube::update(const texture_cube& value) const noexcept
  505. {
  506. // Bind texture to texture unit
  507. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices.front()));
  508. glBindTexture(GL_TEXTURE_CUBE_MAP, value.m_gl_texture_id);
  509. // Pass texture unit index to shader
  510. glUniform1i(gl_uniform_location, gl_texture_unit_indices.front());
  511. }
  512. void gl_shader_texture_cube::update(const texture_cube& value, std::size_t index) const
  513. {
  514. const GLint gl_texture_index = gl_texture_unit_indices[index];
  515. // Bind texture to texture unit
  516. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_index));
  517. glBindTexture(GL_TEXTURE_CUBE_MAP, value.m_gl_texture_id);
  518. // Pass texture unit index to shader
  519. glUniform1i(gl_uniform_location + static_cast<GLint>(index), gl_texture_index);
  520. }
  521. void gl_shader_texture_cube::update(std::span<const texture_cube* const> values, std::size_t index) const
  522. {
  523. // Bind textures
  524. for (std::size_t i = 0; i < values.size(); ++i)
  525. {
  526. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i]));
  527. glBindTexture(GL_TEXTURE_CUBE_MAP, values[i]->m_gl_texture_id);
  528. }
  529. // Pass texture unit indices to shader
  530. glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]);
  531. }
  532. void gl_shader_texture_cube::update(std::span<const std::shared_ptr<texture_cube>> values, std::size_t index) const
  533. {
  534. // Bind textures
  535. for (std::size_t i = 0; i < values.size(); ++i)
  536. {
  537. glActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(gl_texture_unit_indices[index + i]));
  538. glBindTexture(GL_TEXTURE_CUBE_MAP, values[i]->m_gl_texture_id);
  539. }
  540. // Pass texture unit indices to shader
  541. glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), &gl_texture_unit_indices[index]);
  542. }
  543. } // namespace gl