Tatooine
texture.h
Go to the documentation of this file.
1#ifndef TATOOINE_GL_TEXTURE_H
2#define TATOOINE_GL_TEXTURE_H
3//==============================================================================
4#include <tatooine/concepts.h>
6#include <tatooine/vec.h>
11#include <tatooine/gl/shader.h>
15#include <tatooine/gl/type.h>
16
17#include <iostream>
18#include <type_traits>
19#include <utility>
20//==============================================================================
21namespace tatooine::gl {
22//==============================================================================
23template <typename ValueType>
26//==============================================================================
27enum class wrap_mode : GLint {
28 clamp_to_border = GL_CLAMP_TO_BORDER,
29 clamp_to_edge = GL_CLAMP_TO_EDGE,
30 repeat = GL_REPEAT,
31 mirrored_repeat = GL_MIRRORED_REPEAT
32};
33//==============================================================================
34enum class interpolation_mode : GLint {
35 nearest = GL_NEAREST,
36 linear = GL_LINEAR,
37 nearest_mipmap_nearest = GL_NEAREST_MIPMAP_NEAREST,
38 linear_mipmap_nearest = GL_LINEAR_MIPMAP_NEAREST,
39 nearest_mipmap_linear = GL_NEAREST_MIPMAP_LINEAR,
40 linear_mipmap_linear = GL_LINEAR_MIPMAP_LINEAR
41};
42//==============================================================================
43enum class compare_func : GLint {
44 never = GL_NEVER,
45 less = GL_LESS,
46 lequal = GL_LEQUAL,
47 greater = GL_GREATER,
48 notequal = GL_NOTEQUAL,
49 gequal = GL_GEQUAL,
50 always = GL_ALWAYS
51};
52//==============================================================================
53enum class compare_mode : GLint {
54 compare_r_to_texture = GL_COMPARE_R_TO_TEXTURE,
55 none = GL_NONE
56};
57//==============================================================================
58template <std::size_t NumDimensions, texture_value ValueType,
59 texture_component Components>
60requires (NumDimensions >= 1 && NumDimensions <= 3)
61class texture : public id_holder<GLuint> {
62 public:
63 //============================================================================
64 using value_type = ValueType;
65 using components_type = Components;
66 static constexpr auto target = tex::target<NumDimensions>;
67 static constexpr auto binding = tex::binding<NumDimensions>;
68 static constexpr auto default_interpolation = interpolation_mode::linear;
69 static constexpr auto default_wrap_mode = wrap_mode::repeat;
70 static constexpr auto num_components() -> GLsizei {
71 return components_type::num_components;
72 }
73 static constexpr std::size_t num_dimensions() { return NumDimensions; }
74
75 static constexpr auto gl_internal_format =
77 static constexpr auto gl_format =
80 static constexpr std::array<GLenum, 3> wrapmode_indices{
81 GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_TEXTURE_WRAP_R};
82
83 protected:
84 //============================================================================
85 std::array<GLsizei, NumDimensions> m_size;
86
87 public:
88 //============================================================================
89 texture() : texture{std::make_index_sequence<NumDimensions>{}} {}
90 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
91 template <std::size_t... Is>
92 texture(std::index_sequence<Is...>) : m_size{((void)Is, 0)...} {
93 create_id();
94 set_wrap_mode(default_wrap_mode);
95 set_interpolation_mode(default_interpolation);
96 }
97 //----------------------------------------------------------------------------
99 texture(texture const& other) : texture{} { copy_data(other); }
100 //----------------------------------------------------------------------------
102 : id_holder{std::move(other)}, m_size{std::move(other.m_size)} {}
103 //----------------------------------------------------------------------------
104 auto& operator=(texture const& other) {
105 copy_data(other);
106 return *this;
107 }
108 //----------------------------------------------------------------------------
109 auto& operator=(texture&& other) {
110 id_holder::operator=(std::move(other));
111 m_size = std::move(other.m_size);
112 return *this;
113 }
114 //----------------------------------------------------------------------------
116 if constexpr (NumDimensions == 1) {
117 if (bound_texture1d() == id()) {
118 unbind();
119 }
120 } else if constexpr (NumDimensions == 2) {
121 if (bound_texture2d() == id()) {
122 unbind();
123 }
124 } else if constexpr (NumDimensions == 3) {
125 if (bound_texture3d() == id()) {
126 unbind();
127 }
128 }
129 if (id()) {
130 gl::delete_textures(1, &id_ref());
131 }
132 }
133 //----------------------------------------------------------------------------
134 texture(integral auto const... sizes)
135 requires(sizeof...(sizes) == NumDimensions)
136 : m_size{static_cast<GLsizei>(sizes)...} {
137 create_id();
138 set_wrap_mode(default_wrap_mode);
139 set_interpolation_mode(default_interpolation);
140 resize(sizes...);
141 }
142 //----------------------------------------------------------------------------
143 template <convertible_to<value_type> OtherType>
144 texture(OtherType const* const data, integral auto const... sizes)
145 requires(sizeof...(sizes) == NumDimensions)
146 : m_size{static_cast<std::size_t>(sizes)...} {
147 upload_data(
148 std::vector<ValueType>(data, data + num_components() * (sizes * ...)));
149 }
150 //----------------------------------------------------------------------------
151 texture(ValueType const* const data, integral auto const... sizes)
152 requires(sizeof...(sizes) == NumDimensions)
153 : m_size{static_cast<GLsizei>(sizes)...} {
154 create_id();
155 set_interpolation_mode(default_interpolation);
156 set_wrap_mode(default_wrap_mode);
157 m_size = std::array{static_cast<GLsizei>(sizes)...};
158 upload_data(data);
159 }
160 //----------------------------------------------------------------------------
161 template <convertible_to<value_type> OtherType>
162 texture(std::vector<OtherType> const& data, integral auto const... sizes)
163 requires (sizeof...(sizes) == NumDimensions) &&
164 (num_components() == 1)
165 : m_size{static_cast<std::size_t>(sizes)...} {
166 create_id();
167 set_interpolation_mode(default_interpolation);
168 set_wrap_mode(default_wrap_mode);
169 upload_data(data.data());
170 }
171 //----------------------------------------------------------------------------
172 template <convertible_to<value_type> OtherType>
173 texture(std::vector<vec<OtherType, num_components()>> const& data,
174 integral auto const... sizes)
175 requires (sizeof...(sizes) == NumDimensions) &&
176 (num_components() > 1)
177 : m_size{static_cast<std::size_t>(sizes)...} {
178 create_id();
179 set_interpolation_mode(default_interpolation);
180 set_wrap_mode(default_wrap_mode);
181 upload_data(data.data());
182 }
183 //----------------------------------------------------------------------------
184 template <convertible_to<value_type> OtherType>
185 requires(num_components() == 1)
187 auto const converted_data = std::vector<value_type>(
189 std::ranges::copy(data.size(), begin(m_size));
190 upload_data(converted_data.data());
191 }
192 //----------------------------------------------------------------------------
193 template <convertible_to<value_type> OtherType>
194 requires(num_components() > 1)
195 texture(dynamic_multidim_array<vec<OtherType, num_components()>> const& data)
196 : texture{} {
197 auto const converted_data = std::vector<vec<value_type, num_components()>>(
199 std::ranges::copy(data.size(), begin(m_size));
200 upload_data(converted_data.data());
201 }
202 //----------------------------------------------------------------------------
203 template <std::size_t... Is>
205 std::index_sequence<Is...>)
206 : m_size{((void)Is, 0)...} {
207 create_id();
208 set_interpolation_mode(interp_mode);
209 set_wrap_mode(wrap_mode);
210 }
211 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
213 : texture{interp_mode, wrap_mode,
214 std::make_index_sequence<NumDimensions>{}} {}
215
216 //----------------------------------------------------------------------------
217 template <integral... Sizes>
218 requires(sizeof...(Sizes) == NumDimensions)
220 Sizes const... sizes)
221 : m_size{sizes...} {
222 create_id();
223 set_interpolation_mode(interp_mode);
224 set_wrap_mode(wrap_mode);
225 resize(sizes...);
226 }
227 //----------------------------------------------------------------------------
228 template <convertible_to<value_type> OtherType, integral... Sizes>
229 requires(sizeof...(Sizes) == NumDimensions)
231 std::vector<OtherType> const& data, Sizes const... sizes)
232 : m_size{sizes...} {
233 create_id();
234 set_interpolation_mode(interp_mode);
235 set_wrap_mode(wrap_mode);
236 upload_data(data);
237 }
238
239 private:
240 //----------------------------------------------------------------------------
241 auto create_id() { gl::create_textures(target, 1, &id_ref()); }
242
243 public:
244 //----------------------------------------------------------------------------
245 auto bind(GLuint unit = 0) const {
246 assert(unit < GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
247 gl::active_texture(GL_TEXTURE0 + unit);
248 auto last_tex = bound_texture(binding);
249 gl::bind_texture(target, id());
250 return last_tex;
251 }
252
253 //----------------------------------------------------------------------------
254 static void unbind(GLuint unit = 0) {
255 gl::active_texture(GL_TEXTURE0 + unit);
256 gl::bind_texture(target, 0);
257 }
258
259 //------------------------------------------------------------------------------
260 void bind_image_texture(GLuint unit) const {
261 gl::bind_image_texture(unit, id(), 0, GL_FALSE, 0, GL_READ_ONLY,
262 gl_internal_format);
263 }
264
265 //------------------------------------------------------------------------------
267 gl::bind_image_texture(unit, id(), 0, GL_FALSE, 0, GL_READ_WRITE,
268 gl_internal_format);
269 }
270 //------------------------------------------------------------------------------
272
273 //------------------------------------------------------------------------------
275 gl::bind_image_texture(unit, id(), 0, GL_FALSE, 0, GL_WRITE_ONLY,
276 gl_internal_format);
277 }
278
279 //------------------------------------------------------------------------------
281 gl::bind_image_texture(unit, 0, 0, GL_FALSE, 0, GL_READ_WRITE,
282 gl_internal_format);
283 }
284
285 //------------------------------------------------------------------------------
286
287 void bind_image_texture_layer(GLuint unit, GLint layer) const
288 requires(NumDimensions == 3) {
289 gl::bind_image_texture(unit, id(), 0, GL_TRUE, layer, GL_READ_ONLY,
290 gl_internal_format);
291 }
292
293 //------------------------------------------------------------------------------
294
296 GLint layer) requires(NumDimensions == 3) {
297 gl::bind_image_texture(unit, id(), 0, GL_TRUE, layer, GL_READ_WRITE,
298 gl_internal_format);
299 }
300
301 //------------------------------------------------------------------------------
302
304 GLint layer) requires(NumDimensions ==
305 3) {
306 gl::bind_image_texture(unit, 0, 0, GL_TRUE, layer, GL_READ_WRITE,
307 gl_internal_format);
308 }
309
310 //----------------------------------------------------------------------------
311 template <std::size_t... Is>
312 auto num_texels(std::index_sequence<Is...>) const -> GLsizei {
313 return (m_size[Is] * ...);
314 }
315 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
316 auto num_texels() const -> GLsizei {
317 return num_texels(std::make_index_sequence<NumDimensions>{});
318 }
319
320 //----------------------------------------------------------------------------
321 auto copy_data(texture const& other) -> void {
322 resize(other.m_size);
323 if constexpr (NumDimensions == 1) {
324 gl::copy_image_sub_data(other.id(), target, 0, 0, 0, 0, id(), target, 0,
325 0, 0, 0, m_size[0], 1, 1);
326 } else if constexpr (NumDimensions == 2) {
327 gl::copy_image_sub_data(other.id(), target, 0, 0, 0, 0, id(), target, 0,
328 0, 0, 0, m_size[0], m_size[1], 1);
329
330 } else {
331 gl::copy_image_sub_data(other.id(), target, 0, 0, 0, 0, id(), target, 0,
332 0, 0, 0, m_size[0], m_size[1], m_size[2]);
333 }
334 }
335 //------------------------------------------------------------------------------
336 template <integral Size>
337 auto resize(std::array<Size, NumDimensions> const& size) -> void {
338 auto last_tex = bind();
339 if constexpr (is_same<GLsizei, Size>) {
340 m_size = size;
341 } else {
342 m_size = std::array<GLsizei, NumDimensions>{begin(size), end(size)};
343 }
344 if constexpr (NumDimensions == 1) {
345 gl::tex_image_1d(target, 0, gl_internal_format, width(), 0, gl_format,
346 gl_type, nullptr);
347 } else if constexpr (NumDimensions == 2) {
348 gl::tex_image_2d(target, 0, gl_internal_format, width(), height(), 0,
349 gl_format, gl_type, nullptr);
350 } else if constexpr (NumDimensions == 3) {
351 gl::tex_image_3d(target, 0, gl_internal_format, width(), height(),
352 depth(), 0, gl_format, gl_type, nullptr);
353 }
354 if (last_tex > 0) {
355 gl::bind_texture(target, last_tex);
356 }
357 }
358 //------------------------------------------------------------------------------
359 template <integral... Sizes>
360 requires(sizeof...(Sizes) == NumDimensions)
361 auto resize(Sizes const... sizes)
362 -> void {
363 m_size = std::array{static_cast<GLsizei>(sizes)...};
364 auto last_tex = bind();
365 if constexpr (NumDimensions == 1) {
366 gl::tex_image_1d(target, 0, gl_internal_format, width(), 0, gl_format,
367 gl_type, nullptr);
368 } else if constexpr (NumDimensions == 2) {
369 gl::tex_image_2d(target, 0, gl_internal_format, width(), height(), 0,
370 gl_format, gl_type, nullptr);
371 } else if constexpr (NumDimensions == 3) {
372 gl::tex_image_3d(target, 0, gl_internal_format, width(), height(),
373 depth(), 0, gl_format, gl_type, nullptr);
374 }
375 if (last_tex > 0) {
376 gl::bind_texture(target, last_tex);
377 }
378 }
379 //------------------------------------------------------------------------------
381 private:
382 auto upload_data(value_type const* const data) -> void {
383 auto last_tex = bind();
384 if constexpr (NumDimensions == 1) {
385 gl::tex_image_1d(target, 0, gl_internal_format, width(), 0, gl_format,
386 gl_type, data);
387 } else if constexpr (NumDimensions == 2) {
388 gl::tex_image_2d(target, 0, gl_internal_format, width(), height(), 0,
389 gl_format, gl_type, data);
390 } else if constexpr (NumDimensions == 3) {
391 gl::tex_image_3d(target, 0, gl_internal_format, width(), height(),
392 depth(), 0, gl_format, gl_type, data);
393 }
394 if (last_tex > 0) {
395 gl::bind_texture(target, last_tex);
396 }
397 }
398 //------------------------------------------------------------------------------
399 auto upload_data(vec<value_type, num_components()> const* data) -> void
400 requires (num_components() > 1) {
401 auto last_tex = bind();
402 if constexpr (NumDimensions == 1) {
403 gl::tex_image_1d(target, 0, gl_internal_format, width(), 0, gl_format,
404 gl_type, data[0].data());
405 } else if constexpr (NumDimensions == 2) {
406 gl::tex_image_2d(target, 0, gl_internal_format, width(), height(), 0,
407 gl_format, gl_type, data[0].data());
408 } else if constexpr (NumDimensions == 3) {
409 gl::tex_image_3d(target, 0, gl_internal_format, width(), height(),
410 depth(), 0, gl_format, gl_type, data[0].data());
411 }
412 if (last_tex > 0) {
413 gl::bind_texture(target, last_tex);
414 }
415 }
416
417 public:
418 //------------------------------------------------------------------------------
419 template <integral... Sizes>
420 requires (sizeof...(Sizes) == NumDimensions)
421 auto upload_data(value_type const* const data, Sizes const... sizes) {
422 m_size = std::array{static_cast<GLsizei>(sizes)...};
423 upload_data(data);
424 }
425 //------------------------------------------------------------------------------
426 template <integral... Sizes>
427 requires (sizeof...(Sizes) == NumDimensions) &&
428 (num_components() > 1)
429 auto upload_data(vec<value_type, num_components()> const* const data,
430 Sizes const... sizes) {
431 m_size = std::array{static_cast<GLsizei>(sizes)...};
432 upload_data(data->data());
433 }
434 //------------------------------------------------------------------------------
436 requires (num_components() == 1) {
437 for (std::size_t i = 0; i < NumDimensions; ++i) {
438 m_size[i] = static_cast<GLsizei>(data.size()[i]);
439 }
440 upload_data(data.data());
441 }
442 //------------------------------------------------------------------------------
444 dynamic_multidim_array<vec<value_type, num_components()>> const& data)
445 requires(num_components() > GLsizei(1)) {
446 for (std::size_t i = 0; i < NumDimensions; ++i) {
447 m_size[i] = static_cast<GLsizei>(data.size()[i]);
448 }
449 upload_data(data.internal_container().front().data());
450 }
451 //------------------------------------------------------------------------------
452 template <convertible_to<value_type> OtherType>
453 requires (num_components() == GLsizei(1))
456 for (std::size_t i = 0; i < NumDimensions; ++i) {
457 m_size[i] = static_cast<GLsizei>(data.size()[i]);
458 }
459 std::vector<value_type>{begin(data.internal_container()),
460 end(data.internal_container())};
461 upload_data(data.data());
462 }
463 //------------------------------------------------------------------------------
464 template <convertible_to<value_type> OtherType>
465 requires (num_components() > 1)
467 dynamic_multidim_array<vec<OtherType, num_components()>> const& data) {
468 for (std::size_t i = 0; i < NumDimensions; ++i) {
469 m_size[i] = static_cast<GLsizei>(data.size()[i]);
470 }
471 auto const converted_data = std::vector<value_type>{
473 upload_data(converted_data.data());
474 }
475 //------------------------------------------------------------------------------
476 template <integral... Sizes>
477 requires (num_components() == 1) &&
478 (sizeof...(Sizes) == NumDimensions)
479 auto upload_data(std::vector<value_type> const& data,
480 Sizes const... sizes) {
481 assert((sizes * ...) == size(data));
482 m_size = std::array{static_cast<GLsizei>(sizes)...};
483 upload_data(data.data());
484 }
485 //------------------------------------------------------------------------------
486 template <integral... Sizes>
487 requires (num_components() > 1) &&
488 (sizeof...(Sizes) == NumDimensions)
489 auto upload_data(std::vector<vec<value_type, num_components()>> const& data,
490 Sizes const... sizes) {
491 assert((sizes * ...) = data.size());
492 m_size = std::array{static_cast<GLsizei>(sizes)...};
493 upload_data(data.data());
494 }
495 //------------------------------------------------------------------------------
496 template <convertible_to<value_type> OtherType, integral... Sizes>
497 requires (num_components() == 1) &&
498 (sizeof...(Sizes) == NumDimensions)
499 auto upload_data(std::vector<OtherType> const& data, Sizes const... sizes) {
500 assert((sizes * ...) = size(data));
501 m_size = std::array{static_cast<GLsizei>(sizes)...};
502 auto converted_data = std::vector<value_type>(begin(data), end(data));
503 upload_data(converted_data.data());
504 }
505 //------------------------------------------------------------------------------
506 template <convertible_to<value_type> OtherType, integral... Sizes>
507 requires (num_components() > 1) &&
508 (sizeof...(Sizes) == NumDimensions)
509 auto upload_data(std::vector<vec<OtherType, num_components()>> const& data,
510 Sizes const... sizes) {
511 assert((sizes * ...) = size(data));
512 m_size = std::array{static_cast<GLsizei>(sizes)...};
513 auto converted_data =
514 std::vector<vec<value_type, num_components()>>(begin(data), end(data));
515 upload_data(converted_data.data());
516 }
518 //------------------------------------------------------------------------------
520 auto download_data() const {
521 if constexpr (num_components() == 1) {
522 auto data = dynamic_multidim_array<ValueType>{m_size};
523 auto const s = static_cast<GLsizei>(sizeof(value_type)) * num_texels() *
524 num_components();
525 gl::get_texture_image(id(), 0, gl_format, gl_type, s, data.data());
526 return data;
527 } else {
528 auto data =
529 dynamic_multidim_array<vec<ValueType, num_components()>>{m_size};
530 auto const s = num_components() * num_texels() *
531 static_cast<GLsizei>(sizeof(value_type));
532 gl::get_texture_image(id(), 0, gl_format, gl_type, s, data.data());
533 return data;
534 }
535 }
536 //------------------------------------------------------------------------------
537 auto download_data(std::vector<value_type>& data) const -> void {
538 auto const n = static_cast<std::size_t>(num_components() * num_texels());
539 if (data.size() != n) {
540 data.resize(n);
541 }
542 download_data(data.data());
543 }
544 //------------------------------------------------------------------------------
545 auto download_data(std::vector<vec<value_type, num_components()>>& data) const
546 -> void
547 requires(num_components() > 1) {
548 auto const n = static_cast<std::size_t>(num_texels());
549 if (data.size() != n) {
550 data.resize(n);
551 }
552 download_data(data.front().data());
553 }
554 //------------------------------------------------------------------------------
555 auto download_data(value_type* data) const -> void {
556 auto const s = static_cast<GLsizei>(num_components() * sizeof(value_type)) *
557 num_texels();
558 gl::get_texture_image(id(), 0, gl_format, gl_type, s, data);
559 }
560 //------------------------------------------------------------------------------
561 auto& download_sub_data(GLint xoffset, GLsizei width,
562 std::vector<ValueType>& data, GLint level = 0) const
563 requires (num_components() == 1) && (num_dimensions() == 1) {
564 using container_type = std::vector<vec<ValueType, num_components()>>;
565 using size_type = typename container_type::size_type;
566 auto const size = static_cast<size_type>(width * num_components());
567
568 if (data.size() != size) {
569 data.resize(size);
570 }
571 auto const s = static_cast<GLsizei>(data.size() * sizeof(value_type));
572 gl::get_texture_sub_image(id(), level, xoffset, 0, 0, width, 1, 1,
573 gl_format, gl_type,
574 s, data.data());
575 return data;
576 }
577 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
578 auto& download_sub_data(GLint xoffset, GLsizei width,
579 std::vector<vec<ValueType, num_components()>>& data,
580 GLint level = 0) const
581 requires (num_components() > 1) &&
582 (num_dimensions() == 1) {
583 if (data.size() != static_cast<std::size_t>(width)) {
584 using container_type = std::vector<vec<ValueType, num_components()>>;
585 using size_type = typename container_type::size_type;
586 data.resize(static_cast<size_type>(width * num_components()));
587 }
588 auto const s = static_cast<GLsizei>(data.size() * num_components() *
589 sizeof(value_type));
590 gl::get_texture_sub_image(id(), level, xoffset, 0, 0, width, 1, 1,
591 gl_format, gl_type, s, data.front().data());
592 return data;
593 }
594 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
595 auto download_sub_data(GLint xoffset, GLsizei width, GLint level = 0) const
596 requires (NumDimensions == 1) {
597 if constexpr (num_components() == 1) {
598 using container_type = std::vector<ValueType>;
599 using size_type = typename container_type::size_type;
600 auto data = container_type(static_cast<size_type>(width));
601 auto const s = static_cast<GLsizei>(data.size() * sizeof(value_type));
602 gl::get_texture_sub_image(id(), level, xoffset, 0, 0, width, 1, 1,
603 gl_format, gl_type, s, data.data());
604 return data;
605 } else {
606 using container_type = std::vector<vec<ValueType, num_components()>>;
607 using size_type = typename container_type::size_type;
608 auto data = container_type(static_cast<size_type>(width));
609 auto const s = static_cast<GLsizei>(data.size() * num_components() *
610 sizeof(value_type));
611 gl::get_texture_sub_image(id(), level, xoffset, 0, 0, width, 1, 1,
612 gl_format, gl_type, s, data.front().data());
613 return data;
614 }
615 }
616 //------------------------------------------------------------------------------
617 auto& download_sub_data(GLint xoffset, GLint yoffset, GLsizei width,
618 GLsizei height, std::vector<ValueType>& data,
619 GLint level = 0) const
620 requires (num_components() == 1) &&
621 (NumDimensions == 2) {
622 if (data.size() != static_cast<std::size_t>(width * height)) {
623 using container_type = std::vector<ValueType>;
624 using size_type = typename container_type::size_type;
625 data.resize(static_cast<size_type>(width * height));
626 }
627 auto const s = static_cast<GLsizei>(data.size() * sizeof(value_type));
628 gl::get_texture_sub_image(id(), level, xoffset, yoffset, 0, width, height,
629 1, gl_format, gl_type,
630 s, data.data());
631 return data;
632 }
633 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
634 auto& download_sub_data(GLint xoffset, GLint yoffset, GLsizei width,
635 GLsizei height,
636 std::vector<vec<ValueType, num_components()>>& data,
637 GLint level = 0) const
638 requires (num_components() > 1) &&
639 (NumDimensions == 2) {
640 using container_type = std::vector<vec<ValueType, num_components()>>;
641 using size_type = typename container_type::size_type;
642 auto const size = static_cast<size_type>(width * height);
643 if (data.size() != size) {
644 data.resize(size);
645 }
646 auto const s = static_cast<GLsizei>(data.size() * sizeof(value_type)) *
647 num_components();
648 gl::get_texture_sub_image(id(), level, xoffset, yoffset, 0, width, height,
649 1, gl_format, gl_type, s, data.front().data());
650 return data;
651 }
652 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
653 auto download_sub_data(GLint xoffset, GLint yoffset, GLsizei width,
654 GLsizei height, GLint level = 0) const
655 requires (NumDimensions == 2) {
656 if constexpr (num_components() == 1) {
657 auto data = dynamic_multidim_array<ValueType>{width, height};
658 auto const s =
659 static_cast<GLsizei>(data.num_components() * sizeof(value_type));
660 gl::get_texture_sub_image(id(), level, xoffset, yoffset, 0, width, height,
661 1, gl_format, gl_type, s, data.data());
662 return data;
663 } else {
664 auto data = dynamic_multidim_array<vec<ValueType, num_components()>>{width, height};
665 auto const s = static_cast<GLsizei>(
666 data.num_components() * num_components() * sizeof(value_type));
667 gl::get_texture_sub_image(id(), level, xoffset, yoffset, 0, width, height,
668 1, gl_format, gl_type, s, data.data());
669 return data;
670 }
671 }
672 //------------------------------------------------------------------------------
673 auto& download_sub_data(GLint xoffset, GLint yoffset, GLint zoffset,
674 GLsizei width, GLsizei height, GLsizei depth,
675 std::vector<ValueType>& data, GLint level = 0) const
676 requires (num_components() == 1) &&
677 (NumDimensions == 3) {
678 using container_type = std::vector<ValueType>;
679 using size_type = typename container_type::size_type;
680 auto const size = static_cast<size_type>(width * height * depth);
681 if (data.size() != size) {
682 data.resize(size);
683 }
684 auto const s = static_cast<GLsizei>(data.size() * sizeof(value_type));
685 gl::get_texture_sub_image(id(), level, xoffset, yoffset, zoffset, width,
686 height, depth, gl_format, gl_type, s,
687 data.data());
688 return data;
689 }
690 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
691 auto& download_sub_data(GLint xoffset, GLint yoffset, GLint zoffset,
692 GLsizei width, GLsizei height, GLsizei depth,
693 std::vector<vec<ValueType, num_components()>>& data,
694 GLint level = 0) const
695 requires (num_components() > 1) &&
696 (NumDimensions == 3) {
697 using container_type = std::vector<vec<ValueType, num_components()>>;
698 using size_type = typename container_type::size_type;
699 auto const size = static_cast<size_type>(width * height * depth);
700 if (data.size() != size) {
701 data.resize(size);
702 }
703 auto const s = static_cast<GLsizei>(data.size() * num_components() *
704 sizeof(value_type));
705 gl::get_texture_sub_image(id(), level, xoffset, yoffset, zoffset, width,
706 height, depth, gl_format, gl_type, s,
707 data.front().data());
708 return data;
709 }
710 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
711 auto download_sub_data(GLint xoffset, GLint yoffset, GLint zoffset,
712 GLsizei width, GLsizei height, GLsizei depth,
713 GLint level = 0) const
714 requires(NumDimensions == 3) {
715 if constexpr (num_components() == 1) {
716 auto data = dynamic_multidim_array<ValueType>{width, height, depth};
717 auto const s = static_cast<GLsizei>(data.num_components() * sizeof(value_type));
718 gl::get_texture_sub_image(id(), level, xoffset, yoffset, zoffset, width,
719 height, depth, gl_format, gl_type,
720 s, data.data());
721 return data;
722 } else {
723 auto data = dynamic_multidim_array<vec<ValueType, num_components()>>{
724 width, height, depth};
725 auto const s = static_cast<GLsizei>(data.num_components() * sizeof(value_type));
726 gl::get_texture_sub_image(id(), level, xoffset, yoffset, zoffset, width,
727 height, depth, gl_format, gl_type, s,
728 data.internal_container().front().data());
729 return data;
730 }
731 }
733 //----------------------------------------------------------------------------
734 template <integral... Indices>
735 requires(sizeof...(Indices) == NumDimensions)
736 auto operator()(Indices const... indices) const {
737 return download_sub_data(indices..., ((void)indices, 1)..., 0).front();
738 }
739 //----------------------------------------------------------------------------
740 auto width() const { return m_size[0]; }
741 //----------------------------------------------------------------------------
742 auto height() const requires(NumDimensions > 1) { return m_size[1]; }
743 //----------------------------------------------------------------------------
744 auto depth() const requires(NumDimensions > 2) { return m_size[2]; }
745 //----------------------------------------------------------------------------
747 auto set_wrap_mode(wrap_mode mode) -> void {
748 set_wrap_mode_s(mode);
749 if constexpr (NumDimensions > 1) {
750 set_wrap_mode_t(mode);
751 }
752 if constexpr (NumDimensions > 2) {
753 set_wrap_mode_r(mode);
754 }
755 }
756
757 //----------------------------------------------------------------------------
759 template <std::size_t... Is>
760 auto set_wrap_mode(std::index_sequence<Is...>,
761 same_as<wrap_mode> auto const... modes) -> void
762 requires(sizeof...(modes) == NumDimensions) {
763 using discard = int[];
764 (void)discard{((void)set_wrap_mode(Is, modes), 0)...};
765 }
766 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
768 auto set_wrap_mode(same_as<wrap_mode> auto const... modes) -> void
769 requires (sizeof...(modes) == NumDimensions) {
770 set_wrap_mode(std::make_index_sequence<NumDimensions>{}, modes...);
771 }
772 //----------------------------------------------------------------------------
774 auto set_wrap_mode(std::size_t const i, wrap_mode const mode) -> void{
775 gl::texture_parameter_i(id(), wrapmode_indices[i],
776 static_cast<GLint>(mode));
777 }
778 //----------------------------------------------------------------------------
780 auto set_repeat() -> void { set_wrap_mode(wrap_mode::repeat); }
781 //----------------------------------------------------------------------------
782 auto set_wrap_mode_s(wrap_mode const mode) -> void {
783 set_wrap_mode(0, mode);
784 }
785 //----------------------------------------------------------------------------
786 auto set_wrap_mode_t(wrap_mode const mode) -> void
787 requires(NumDimensions > 1) {
788 set_wrap_mode(1, mode);
789 }
790 //----------------------------------------------------------------------------
791 auto set_wrap_mode_r(wrap_mode const mode) -> void
792 requires(NumDimensions > 2) {
793 set_wrap_mode(2, mode);
794 }
795 //------------------------------------------------------------------------------
797 set_interpolation_mode_min(mode);
798 set_interpolation_mode_mag(mode);
799 }
800 //------------------------------------------------------------------------------
802 gl::texture_parameter_i(id(), GL_TEXTURE_MIN_FILTER, static_cast<GLint>(mode));
803 }
804 //------------------------------------------------------------------------------
806 gl::texture_parameter_i(id(), GL_TEXTURE_MAG_FILTER, static_cast<GLint>(mode));
807 }
808 //----------------------------------------------------------------------------
809 auto set_compare_func(compare_func const f) -> void
810 requires is_same<components_type, Depth> {
811 gl::texture_parameter_i(id(), GL_TEXTURE_COMPARE_FUNC, static_cast<GLint>(f));
812 }
813 //----------------------------------------------------------------------------
814 auto set_compare_mode(compare_mode const m) -> void
815 requires is_same<components_type, Depth> {
816 gl::texture_parameter_i(id(), GL_TEXTURE_COMPARE_MODE, static_cast<GLint>(m));
817 }
818 //----------------------------------------------------------------------------
819 auto clear(arithmetic auto const... comps)
820 requires(sizeof...(comps) == num_components()) {
821 clear(std::array<value_type, num_components()>{
822 static_cast<value_type>(comps)...});
823 }
824 //------------------------------------------------------------------------------
825 auto clear(std::array<value_type, num_components()> const& col) {
826 gl::clear_tex_image(id(), 0, gl_format, gl_type, col.data());
827 }
828 //------------------------------------------------------------------------------
829 auto set_data(pixelunpackbuffer<value_type> const& pbo) requires(
830 NumDimensions == 2) {
831 pbo.bind();
832 auto last_tex = bind();
833 gl::tex_sub_image_2d(GL_TEXTURE_2D, 0, 0, 0, width(), m_size[1], gl_format,
834 gl_type, 0);
835 if (last_tex > 0) {
836 gl::bind_texture(target, last_tex);
837 }
838 }
839};
840//==============================================================================
841template <texture_value ValueType, texture_component Components>
843template <texture_value ValueType, texture_component Components>
845template <texture_value ValueType, texture_component Components>
847
848template <texture_value ValueType>
850template <texture_value ValueType>
852template <texture_value ValueType>
854template <texture_value ValueType>
856template <texture_value ValueType>
858template <texture_value ValueType>
860template <texture_value ValueType>
862template <texture_value ValueType>
864template <texture_value ValueType>
866template <texture_value ValueType>
868template <texture_value ValueType>
870template <texture_value ValueType>
872template <texture_value ValueType>
874template <texture_value ValueType>
876template <texture_value ValueType>
878template <texture_value ValueType>
880template <texture_value ValueType>
882template <texture_value ValueType>
884template <texture_value ValueType>
886
895
904
913
922
931
940
949
958
963
964template <texture_value ValueType, texture_component Components>
966template <>
968 static constexpr std::string_view value = "r32f";
969};
970template <>
972 static constexpr std::string_view value = "rg32f";
973};
974template <>
976 static constexpr std::string_view value = "rgba32f";
977};
978template <>
980 static constexpr std::string_view value = "rgba32f";
981};
982template <>
983struct texture_format_qualifier_impl<std::uint8_t, RGBA> {
984 static constexpr std::string_view value = "rgba8";
985};
986template <texture_value ValueType, texture_component Components>
987static auto constexpr texture_format_qualifier =
989//------------------------------------------------------------------------------
990template <either_of<R, RG, RGBA> Components>
991auto to_2d(tex1<float, Components> const& t1, std::size_t const height,
992 std::size_t const local_size_x = 32,
993 std::size_t const local_size_y = 32) {
994 auto t2 = tex2<float, Components>{t1.width(), height};
995 auto s = shader{};
996 auto ss = std::stringstream{};
997 ss << "#version 430\n"
998 << "uniform int width;\n"
999 << "uniform int height;\n"
1000 << "layout(local_size_x = " << local_size_x
1001 << ", local_size_y = " << local_size_y << ") in;\n"
1002 << "layout("
1004 float, Components> << ", binding = 0) uniform image1D t1;\n"
1005 << "layout("
1007 float, Components> << ", binding = 1) uniform image2D t2;\n"
1008 << "void main() {\n"
1009 << " ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy);\n"
1010 << " if(pixel_coords.x < width && pixel_coords.y < height) {\n"
1011 << " imageStore(t2, pixel_coords, imageLoad(t1, pixel_coords.x));\n"
1012 << " }\n"
1013 << "}\n";
1014 s.add_stage<computeshader>(gl::shadersource{ss.str()});
1015 s.create();
1016 s.bind();
1017 s.set_uniform("width", static_cast<int>(t1.width()));
1018 s.set_uniform("height", static_cast<int>(height));
1019 t1.bind_image_texture(0);
1020 t2.bind_image_texture(1);
1022 static_cast<GLuint>(
1023 std::ceil(t1.width() / static_cast<double>(local_size_x))),
1024 static_cast<GLuint>(std::ceil(static_cast<double>(height) /
1025 static_cast<double>(local_size_y))),
1026 1);
1027 return t2;
1028}
1029//==============================================================================
1030} // namespace tatooine::gl
1031//==============================================================================
1032#endif
Definition: dynamic_multidim_array.h:18
constexpr auto data(std::size_t const i) -> auto &
Definition: dynamic_multidim_array.h:311
auto size() const -> auto const &
Definition: dynamic_multidim_size.h:107
constexpr auto internal_container() -> auto &
Definition: dynamic_multidim_array.h:306
Definition: computeshader.h:11
Definition: pixelunpackbuffer.h:17
Definition: shader.h:24
Definition: texture.h:61
auto upload_data(std::vector< vec< OtherType, num_components()> > const &data, Sizes const ... sizes)
Definition: texture.h:509
auto download_sub_data(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLint level=0) const
Definition: texture.h:711
auto upload_data(std::vector< value_type > const &data, Sizes const ... sizes)
Definition: texture.h:479
auto num_texels(std::index_sequence< Is... >) const -> GLsizei
Definition: texture.h:312
auto download_data(std::vector< value_type > &data) const -> void
Definition: texture.h:537
auto & download_sub_data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, std::vector< ValueType > &data, GLint level=0) const
Definition: texture.h:617
auto download_sub_data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLint level=0) const
Definition: texture.h:653
auto depth() const
Definition: texture.h:744
auto upload_data(value_type const *const data, Sizes const ... sizes)
Definition: texture.h:421
auto set_wrap_mode_s(wrap_mode const mode) -> void
Definition: texture.h:782
std::array< GLsizei, NumDimensions > m_size
Definition: texture.h:85
auto set_wrap_mode(wrap_mode mode) -> void
setting all wrapmodes to same mode
Definition: texture.h:747
auto upload_data(std::vector< OtherType > const &data, Sizes const ... sizes)
Definition: texture.h:499
static constexpr std::size_t num_dimensions()
Definition: texture.h:73
auto set_wrap_mode_r(wrap_mode const mode) -> void requires(NumDimensions > 2)
Definition: texture.h:791
static constexpr auto num_components() -> GLsizei
Definition: texture.h:70
auto copy_data(texture const &other) -> void
Definition: texture.h:321
auto set_interpolation_mode_min(interpolation_mode const mode) -> void
Definition: texture.h:801
auto download_sub_data(GLint xoffset, GLsizei width, GLint level=0) const
Definition: texture.h:595
void bind_image_texture_write(GLuint unit)
Definition: texture.h:274
texture(texture const &other)
TODO: copy wrap and interpolation modes.
Definition: texture.h:99
auto set_compare_func(compare_func const f) -> void
Definition: texture.h:809
texture(std::index_sequence< Is... >)
Definition: texture.h:92
auto set_compare_mode(compare_mode const m) -> void
Definition: texture.h:814
texture(dynamic_multidim_array< OtherType > const &data)
Definition: texture.h:186
auto download_data(value_type *data) const -> void
Definition: texture.h:555
auto set_interpolation_mode(interpolation_mode const mode) -> void
Definition: texture.h:796
static void unbind_image_texture_layer(GLuint unit, GLint layer)
Definition: texture.h:303
auto & operator=(texture const &other)
Definition: texture.h:104
auto upload_data(dynamic_multidim_array< OtherType > const &data)
Definition: texture.h:454
auto set_interpolation_mode_mag(interpolation_mode const mode) -> void
Definition: texture.h:805
auto create_id()
Definition: texture.h:241
auto & download_sub_data(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, std::vector< vec< ValueType, num_components()> > &data, GLint level=0) const
Definition: texture.h:634
texture(interpolation_mode interp_mode, wrap_mode wrap_mode)
Definition: texture.h:212
auto upload_data(dynamic_multidim_array< vec< OtherType, num_components()> > const &data)
Definition: texture.h:466
auto set_wrap_mode(same_as< wrap_mode > auto const ... modes) -> void
setting all wrapmodes individual modes
Definition: texture.h:768
Components components_type
Definition: texture.h:65
texture(interpolation_mode interp_mode, wrap_mode wrap_mode, std::index_sequence< Is... >)
Definition: texture.h:204
auto num_texels() const -> GLsizei
Definition: texture.h:316
auto clear(std::array< value_type, num_components()> const &col)
Definition: texture.h:825
auto & download_sub_data(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, std::vector< vec< ValueType, num_components()> > &data, GLint level=0) const
Definition: texture.h:691
void bind_image_texture_read_write(GLuint unit)
Definition: texture.h:271
auto upload_data(dynamic_multidim_array< vec< value_type, num_components()> > const &data)
Definition: texture.h:443
auto upload_data(vec< value_type, num_components()> const *const data, Sizes const ... sizes)
Definition: texture.h:429
texture(ValueType const *const data, integral auto const ... sizes)
Definition: texture.h:151
auto upload_data(std::vector< vec< value_type, num_components()> > const &data, Sizes const ... sizes)
Definition: texture.h:489
void unbind_image_texture(GLuint unit)
Definition: texture.h:280
texture(integral auto const ... sizes)
Definition: texture.h:134
auto resize(std::array< Size, NumDimensions > const &size) -> void
Definition: texture.h:337
texture(OtherType const *const data, integral auto const ... sizes)
Definition: texture.h:144
auto width() const
Definition: texture.h:740
auto & operator=(texture &&other)
Definition: texture.h:109
auto set_wrap_mode(std::size_t const i, wrap_mode const mode) -> void
setting wrapmode with index i to modes
Definition: texture.h:774
auto set_wrap_mode(std::index_sequence< Is... >, same_as< wrap_mode > auto const ... modes) -> void requires(sizeof...(modes)==NumDimensions)
setting all wrapmodes individual modes
Definition: texture.h:760
ValueType value_type
Definition: texture.h:64
void bind_image_texture(GLuint unit)
Definition: texture.h:266
auto clear(arithmetic auto const ... comps)
Definition: texture.h:819
auto set_data(pixelunpackbuffer< value_type > const &pbo)
Definition: texture.h:829
texture(texture &&other)
Definition: texture.h:101
auto & download_sub_data(GLint xoffset, GLsizei width, std::vector< vec< ValueType, num_components()> > &data, GLint level=0) const
Definition: texture.h:578
auto set_wrap_mode_t(wrap_mode const mode) -> void requires(NumDimensions > 1)
Definition: texture.h:786
auto height() const
Definition: texture.h:742
void bind_image_texture_layer(GLuint unit, GLint layer)
Definition: texture.h:295
auto upload_data(vec< value_type, num_components()> const *data) -> void
Definition: texture.h:399
auto upload_data(value_type const *const data) -> void
Definition: texture.h:382
auto & download_sub_data(GLint xoffset, GLsizei width, std::vector< ValueType > &data, GLint level=0) const
Definition: texture.h:561
void bind_image_texture_layer(GLuint unit, GLint layer) const
Definition: texture.h:287
texture(std::vector< vec< OtherType, num_components()> > const &data, integral auto const ... sizes)
Definition: texture.h:173
texture()
Definition: texture.h:89
auto download_data() const
Definition: texture.h:520
static void unbind(GLuint unit=0)
Definition: texture.h:254
~texture()
Definition: texture.h:115
texture(std::vector< OtherType > const &data, integral auto const ... sizes)
Definition: texture.h:162
auto bind(GLuint unit=0) const
Definition: texture.h:245
void bind_image_texture(GLuint unit) const
Definition: texture.h:260
auto set_repeat() -> void
setting all wrapmodes to repeat
Definition: texture.h:780
texture(dynamic_multidim_array< vec< OtherType, num_components()> > const &data)
Definition: texture.h:195
auto download_data(std::vector< vec< value_type, num_components()> > &data) const -> void requires(num_components() > 1)
Definition: texture.h:545
auto & download_sub_data(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, std::vector< ValueType > &data, GLint level=0) const
Definition: texture.h:673
auto upload_data(dynamic_multidim_array< value_type > const &data)
Definition: texture.h:435
Definition: concepts.h:33
Definition: texture.h:24
Definition: concepts.h:21
Definition: concepts.h:15
format
Definition: base.h:54
Definition: ansiformat.h:6
DLL_API auto bound_texture1d() -> GLuint
DLL_API auto delete_textures(GLsizei n, GLuint *textures) -> void
compare_func
Definition: texture.h:43
DLL_API auto bound_texture3d() -> GLuint
auto begin(buffer_map< ArrayType, T, Access > &map)
Definition: buffer.h:94
auto to_2d(tex1< float, Components > const &t1, std::size_t const height, std::size_t const local_size_x=32, std::size_t const local_size_y=32)
Definition: texture.h:991
DLL_API auto bind_image_texture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) -> void
tex2r< GLfloat > tex2r32f
Definition: texture.h:930
DLL_API auto bound_texture(GLenum binding) -> GLuint
compare_mode
Definition: texture.h:53
auto end(buffer_map< ArrayType, T, Access > &map)
Definition: buffer.h:104
static auto constexpr texture_format_qualifier
Definition: texture.h:987
DLL_API auto clear(GLbitfield mask) -> void
interpolation_mode
Definition: texture.h:34
tex2rgba< GLfloat > tex2rgba32f
Definition: texture.h:957
DLL_API auto dispatch_compute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) -> void
DLL_API auto bound_texture2d() -> GLuint
wrap_mode
Definition: texture.h:27
tex1rgba< GLfloat > tex1rgba32f
Definition: texture.h:921
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto end(Range &&range)
Definition: iterator_facade.h:322
auto size(vec< ValueType, N > const &v)
Definition: vec.h:148
constexpr auto bind(F &&f, Args &&... args)
Binds first arguments of f (either all or only partially).
Definition: bind.h:10
T type
Definition: common_type.h:13
Definition: texcomponents.h:18
Definition: texcomponents.h:15
Definition: texcomponents.h:12
Definition: texcomponents.h:9
Definition: gltype.h:11
Definition: idholder.h:31
auto operator=(id_holder const &other) -> id_holder &=delete
Definition: shadersource.h:8
Definition: texsettings.h:11
Definition: utility.h:13
Definition: vec.h:12