cgv
Loading...
Searching...
No Matches
gl_texture_tools.cxx
1#include "gl_tools.h"
2
3#include <cgv_gl/gl/gl.h>
4#include <cgv/render/frame_buffer.h>
5#include <cgv/render/attribute_array_binding.h>
6#include <cgv/math/ftransform.h>
7#include <cgv/render/shader_program.h>
8#include <iostream>
9
10#ifndef GL_CLAMP_TO_EDGE
11#define GL_CLAMP_TO_EDGE 0x812F
12#endif
13
14using namespace cgv::data;
15
16namespace cgv {
17 namespace render {
18 namespace gl {
19
21{
22 static unsigned cf_to_gl[] = {
23 0,
24 GL_RED,
25 GL_GREEN,
26 GL_BLUE,
27 GL_ALPHA,
28 GL_LUMINANCE,
29 GL_LUMINANCE,
30 GL_LUMINANCE_ALPHA,
31 GL_LUMINANCE_ALPHA,
32 GL_RG,
33 GL_RGB,
34 GL_RGBA,
35 GL_BGR,
36 GL_BGRA,
37 GL_DEPTH_COMPONENT,
38 GL_STENCIL_INDEX,
39 };
40 static unsigned cf_to_gl_integer[] = {
41 0,
42 GL_RED_INTEGER,
43 GL_GREEN_INTEGER,
44 GL_BLUE_INTEGER,
45 GL_ALPHA_INTEGER,
46 GL_LUMINANCE_INTEGER_EXT,
47 GL_LUMINANCE_INTEGER_EXT,
48 GL_LUMINANCE_ALPHA_INTEGER_EXT,
49 GL_LUMINANCE_ALPHA_INTEGER_EXT,
50 GL_RG_INTEGER,
51 GL_RGB_INTEGER,
52 GL_RGBA_INTEGER,
53 GL_BGR_INTEGER,
54 GL_BGRA_INTEGER,
55 GL_DEPTH_COMPONENT,
56 GL_STENCIL_INDEX,
57 };
58 if (cf == 0 || cf > cgv::data::CF_S)
59 return -1;
60
61 if (cii == CII_INTEGER)
62 return cf_to_gl_integer[cf];
63 return cf_to_gl[cf];
64}
65
66unsigned map_to_gl(cgv::type::info::TypeId ti)
67{
68 static unsigned ti_to_gl[] = {
69 0,
70 0, // bit
71 0,
72 0,
73 GL_BYTE,
74 GL_SHORT,
75 GL_INT,
76 0,
77 GL_UNSIGNED_BYTE,
78 GL_UNSIGNED_SHORT,
79 GL_UNSIGNED_INT,
80 0,
81 0,
82 GL_FLOAT,
83 GL_DOUBLE,
84 0,
85 0,
86 0,
87 0
88 };
89 if (ti_to_gl[ti] == 0) {
90 std::cerr << "could not map component type " << ti << " to gl type" << std::endl;
91 return GL_UNSIGNED_BYTE;
92 }
93 return ti_to_gl[ti];
94}
95
96unsigned get_gl_cube_map_target(unsigned side)
97{
98 GLint gl_cube_map_target[] = {
99 GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT,
100 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT,
101 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT,
102 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT,
103 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT,
104 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT
105 };
106 return gl_cube_map_target[side];
107}
108
109GLuint gl_tex_dim[] = { GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_EXT };
110
111bool generate_mipmaps(unsigned int dim, bool is_cubemap, bool is_array, std::string* last_error)
112{
113 if (dim == 0 || dim > 3) {
114 if (last_error)
115 *last_error = "wrong dimension of texture";
116 return false;
117 }
118 if(is_array && (dim < 2 || dim > 3)) {
119 if(last_error)
120 *last_error = "wrong dimension for array texture";
121 return false;
122 }
123 if(is_cubemap && dim != 2) {
124 if(last_error)
125 *last_error = "wrong dimension for cubemap texture";
126 return false;
127 }
128 if (!(ensure_glew_initialized() && GLEW_EXT_framebuffer_object)) {
129 if (last_error)
130 *last_error = "automatic generation of mipmaps not supported";
131 return false;
132 }
133 if(is_array)
134 dim += 2;
135 if(is_cubemap)
136 dim = 6;
137 glGenerateMipmap(gl_tex_dim[dim-1]);
138 return true;
139}
140
141static const GLenum gl_std_texture_format_ids[] =
142{
143 GL_ALPHA,
144 GL_ALPHA4,
145 GL_ALPHA8,
146 GL_ALPHA12,
147 GL_ALPHA16,
148
149 GL_LUMINANCE,
150 GL_LUMINANCE4,
151 GL_LUMINANCE8,
152 GL_LUMINANCE12,
153 GL_LUMINANCE16,
154
155 GL_LUMINANCE_ALPHA,
156 GL_LUMINANCE4_ALPHA4,
157 GL_LUMINANCE6_ALPHA2,
158 GL_LUMINANCE8_ALPHA8,
159 GL_LUMINANCE12_ALPHA4,
160 GL_LUMINANCE12_ALPHA12,
161 GL_LUMINANCE16_ALPHA16,
162
163 GL_INTENSITY,
164 GL_INTENSITY4,
165 GL_INTENSITY8,
166 GL_INTENSITY12,
167 GL_INTENSITY16,
168
169 GL_R3_G3_B2,
170 GL_RGB,
171 GL_RGB4,
172 GL_RGB5,
173 GL_RGB8,
174 GL_RGB10,
175 GL_RGB12,
176 GL_RGB16,
177
178 GL_RGBA,
179 GL_RGBA2,
180 GL_RGBA4,
181 GL_RGB5_A1,
182 GL_RGBA8,
183 GL_RGB10_A2,
184 GL_RGBA12,
185 GL_RGBA16
186};
187
188static const char* std_texture_formats[] = {
189 "[A]",
190 "uint8:4[A]",
191 "uint8[A]",
192 "uint16:12[A]",
193 "uint16[A]",
194
195 "[L]",
196 "uint8:4[L]",
197 "uint8[L]",
198 "uint16:12[L]",
199 "uint16[L]",
200
201 "[L,A]",
202 "uint8:4[L,A]",
203 "uint8[L:6,A:2]",
204 "uint8[L,8]",
205 "uint16[L:12,A:4]",
206 "uint16:12[L,A]",
207 "uint16[L]",
208
209 "[I]",
210 "uint8:4[I]",
211 "uint8[I]",
212 "uint16:12[I]",
213 "uint16[I]",
214
215 "uint8[R:3,G:3,B:2]",
216 "[R,G,B]",
217 "uint8:4|16[R,G,B]",
218 "uint8:5|16[R,G,B]",
219 "uint8[R,G,B]",
220 "uint16:10[R,G,B]",
221 "uint16:12[R,G,B]",
222 "uint16[R,G,B]",
223
224 "[R,G,B,A]",
225 "uint8:2[R,G,B,A]",
226 "uint8:4[R,G,B,A]",
227 "uint8[R:5,G:5,B:5,A:1]",
228 "uint8[R,G,B,A]",
229 "uint16[R:10,G:10,B:10,A:2]",
230 "uint16:12[R,G,B,A]",
231 "uint16[R,G,B,A]",
232 0
233};
234static const GLenum gl_float_texture_format_ids[] =
235{
236 GL_RGBA32F_ARB,
237 GL_RGB32F_ARB,
238 GL_ALPHA32F_ARB,
239 GL_INTENSITY32F_ARB,
240 GL_LUMINANCE32F_ARB,
241 GL_LUMINANCE_ALPHA32F_ARB,
242
243 GL_RGBA16F_ARB,
244 GL_RGB16F_ARB,
245 GL_ALPHA16F_ARB,
246 GL_INTENSITY16F_ARB,
247 GL_LUMINANCE16F_ARB,
248 GL_LUMINANCE_ALPHA16F_ARB,
249};
250
251
252static const char* float_texture_formats[] = {
253 "flt32[R,G,B,A]",
254 "flt32[R,G,B]",
255 "flt32[A]",
256 "flt32[I]",
257 "flt32[L]",
258 "flt32[L,A]",
259
260 "flt16[R,G,B,A]",
261 "flt16[R,G,B]",
262 "flt16[A]",
263 "flt16[I]",
264 "flt16[L]",
265 "flt16[L,A]",
266 0
267};
268
269static const GLenum gl_snorm_texture_format_ids[] =
270{
271 GL_RED_SNORM,
272 GL_RG_SNORM,
273 GL_RGB_SNORM,
274 GL_RGBA_SNORM,
275 GL_ALPHA_SNORM,
276 GL_LUMINANCE_SNORM,
277 GL_LUMINANCE_ALPHA_SNORM,
278 GL_INTENSITY_SNORM,
279 GL_R8_SNORM,
280 GL_RG8_SNORM,
281 GL_RGB8_SNORM,
282 GL_RGBA8_SNORM,
283 GL_ALPHA8_SNORM,
284 GL_LUMINANCE8_SNORM,
285 GL_LUMINANCE8_ALPHA8_SNORM,
286 GL_INTENSITY8_SNORM,
287 GL_R16_SNORM,
288 GL_RG16_SNORM,
289 GL_RGB16_SNORM,
290 GL_RGBA16_SNORM,
291 GL_ALPHA16_SNORM,
292 GL_LUMINANCE16_SNORM,
293 GL_LUMINANCE16_ALPHA16_SNORM,
294 GL_INTENSITY16_SNORM
295};
296
297static const char* snorm_texture_formats[] = {
298 "s[R]",
299 "s[R,G]",
300 "s[R,G,B]",
301 "s[R,G,B,A]",
302 "s[A]",
303 "s[L]",
304 "s[L,A]",
305 "s[I]",
306 "sint8[R]",
307 "sint8[R,G]",
308 "sint8[R,G,B]",
309 "sint8[R,G,B,A]",
310 "sint8[A]",
311 "sint8[L]",
312 "sint8[L,A]",
313 "sint8[I]",
314 "sint16[R]",
315 "sint16[R,G]",
316 "sint16[R,G,B]",
317 "sint16[R,G,B,A]",
318 "sint16[A]",
319 "sint16[L]",
320 "sint16[L,A]",
321 "sint16[I]",
322 0
323};
324
325static const GLenum gl_int_texture_format_ids[] =
326{
327 GL_RGBA32UI_EXT,
328 GL_RGB32UI_EXT,
329 GL_ALPHA32UI_EXT,
330 GL_INTENSITY32UI_EXT,
331 GL_LUMINANCE32UI_EXT,
332 GL_LUMINANCE_ALPHA32UI_EXT,
333
334 GL_RGBA16UI_EXT,
335 GL_RGB16UI_EXT,
336 GL_ALPHA16UI_EXT,
337 GL_INTENSITY16UI_EXT,
338 GL_LUMINANCE16UI_EXT,
339 GL_LUMINANCE_ALPHA16UI_EXT,
340
341 GL_RGBA8UI_EXT,
342 GL_RGB8UI_EXT,
343 GL_ALPHA8UI_EXT,
344 GL_INTENSITY8UI_EXT,
345 GL_LUMINANCE8UI_EXT,
346 GL_LUMINANCE_ALPHA8UI_EXT,
347
348 GL_RGBA32I_EXT,
349 GL_RGB32I_EXT,
350 GL_ALPHA32I_EXT,
351 GL_INTENSITY32I_EXT,
352 GL_LUMINANCE32I_EXT,
353 GL_LUMINANCE_ALPHA32I_EXT,
354
355 GL_RGBA16I_EXT,
356 GL_RGB16I_EXT,
357 GL_ALPHA16I_EXT,
358 GL_INTENSITY16I_EXT,
359 GL_LUMINANCE16I_EXT,
360 GL_LUMINANCE_ALPHA16I_EXT,
361
362 GL_RGBA8I_EXT,
363 GL_RGB8I_EXT,
364 GL_ALPHA8I_EXT,
365 GL_INTENSITY8I_EXT,
366 GL_LUMINANCE8I_EXT,
367 GL_LUMINANCE_ALPHA8I_EXT
368};
369
370static const char* int_texture_formats[] = {
371 "_uint32[R,G,B,A]",
372 "_uint32[R,G,B]",
373 "_uint32[A]",
374 "_uint32[I]",
375 "_uint32[L]",
376 "_uint32[L,A]",
377
378 "_uint16[R,G,B,A]",
379 "_uint16[R,G,B]",
380 "_uint16[A]",
381 "_uint16[I]",
382 "_uint16[L]",
383 "_uint16[L,A]",
384
385 "_uint8[R,G,B,A]",
386 "_uint8[R,G,B]",
387 "_uint8[A]",
388 "_uint8[I]",
389 "_uint8[L]",
390 "_uint8[L,A]",
391
392 "_int32[R,G,B,A]",
393 "_int32[R,G,B]",
394 "_int32[A]",
395 "_int32[I]",
396 "_int32[L]",
397 "_int32[L,A]",
398
399 "_int16[R,G,B,A]",
400 "_int16[R,G,B]",
401 "_int16[A]",
402 "_int16[I]",
403 "_int16[L]",
404 "_int16[L,A]",
405
406 "_int8[R,G,B,A]",
407 "_int8[R,G,B]",
408 "_int8[A]",
409 "_int8[I]",
410 "_int8[L]",
411 "_int8[L,A]",
412 0
413};
414
415static const GLenum gl_depth_format_ids[] =
416{
417 GL_DEPTH_COMPONENT,
418 GL_DEPTH_COMPONENT16_ARB,
419 GL_DEPTH_COMPONENT24_ARB,
420 GL_DEPTH_COMPONENT32_ARB
421};
422
423static const char* depth_formats[] =
424{
425 "[D]",
426 "uint16[D]",
427 "uint32[D:24]",
428 "uint32[D]",
429 0
430};
431
432static const GLenum gl_rg_texture_format_ids[] =
433{
434 GL_RED,
435 GL_RG,
436
437 GL_R8,
438 GL_R16,
439
440 GL_R8,
441 GL_R16,
442
443 GL_R16F,
444 GL_R32F,
445
446 GL_RG16F,
447 GL_RG32F,
448
449 GL_R8I,
450 GL_R8UI,
451 GL_R16I,
452 GL_R16UI,
453 GL_R32I,
454 GL_R32UI,
455
456 GL_RG8I,
457 GL_RG8UI,
458 GL_RG16I,
459 GL_RG16UI,
460 GL_RG32I,
461 GL_RG32UI,
462
463 GL_RG8,
464 GL_RG16
465};
466
467
468static const char* rg_texture_formats[] = {
469 "[R]",
470 "[R,G]",
471
472 "int8[R]",
473 "int16[R]",
474
475 "uint8[R]",
476 "uint16[R]",
477
478 "flt16[R]",
479 "flt32[R]",
480
481 "flt16[R,G]",
482 "flt32[R,G]",
483
484 "_int8[R]",
485 "_uint8[R]",
486 "_int16[R]",
487 "_uint16[R]",
488 "_int32[R]",
489 "_uint32[R]",
490
491 "_int8[R,G]",
492 "_uint8[R,G]",
493 "_int16[R,G]",
494 "_uint16[R,G]",
495 "_int32[R,G]",
496 "_uint32[R,G]",
497
498 "int8[R,G]",
499 "int16[R,G]",
500 0
501};
502
503
504unsigned find_best_texture_format(const cgv::data::component_format& _cf, cgv::data::component_format* best_cf, const std::vector<data_view>* palettes, bool show_debug_info)
505{
507 if (cf.get_nr_components() == 1 && (cf.get_component_name(0) == "L" || cf.get_component_name(0) == "I"))
508 cf.set_component_names("R");
510 if (!best_cf)
511 best_cf = &best_cf_;
512 if (palettes && palettes->size() > 0 && cf.get_nr_components() == 1 && cf.get_component_name(0) == "0")
513 cf = *palettes->at(0).get_format();
514 if (show_debug_info)
515 std::cout << "find best match in std_texture_formats:" << std::endl;
516 unsigned int i = find_best_match(cf, std_texture_formats, 0, cgv::data::fmt1_compares_better, show_debug_info);
517 if (best_cf)
518 *best_cf = cgv::data::component_format(std_texture_formats[i]);
519 unsigned gl_format = gl_std_texture_format_ids[i];
520
521 if (ensure_glew_initialized() && GLEW_ARB_depth_texture) {
522 if (show_debug_info)
523 std::cout << "find best match in depth_formats:" << std::endl;
524 i = find_best_match(cf,depth_formats, best_cf, cgv::data::fmt1_compares_better, show_debug_info);
525 if (i != -1) {
526 if (best_cf)
527 *best_cf = cgv::data::component_format(depth_formats[i]);
528 gl_format = gl_depth_format_ids[i];
529 }
530 }
531 if (true){//ensure_glew_initialized() && GLEW_EXT_texture_snorm) {
532 if (show_debug_info)
533 std::cout << "find best match in snorm_texture_formats:" << std::endl;
534 i = find_best_match(cf, snorm_texture_formats, best_cf, cgv::data::fmt1_compares_better, show_debug_info);
535 if (i != -1) {
536 if (best_cf)
537 *best_cf = cgv::data::component_format(snorm_texture_formats[i]);
538 gl_format = gl_snorm_texture_format_ids[i];
539 }
540 }
541 if (ensure_glew_initialized() && GLEW_EXT_texture_integer) {
542 if (show_debug_info)
543 std::cout << "find best match in int_texture_formats:" << std::endl;
544 i = find_best_match(cf,int_texture_formats, best_cf, cgv::data::fmt1_compares_better, show_debug_info);
545 if (i != -1) {
546 if (best_cf)
547 *best_cf = cgv::data::component_format(int_texture_formats[i]);
548 gl_format = gl_int_texture_format_ids[i];
549 }
550 }
551 if (ensure_glew_initialized() && GLEW_ARB_texture_float) {
552 if (show_debug_info)
553 std::cout << "find best match in float_texture_formats:" << std::endl;
554 i = find_best_match(cf, float_texture_formats, best_cf, cgv::data::fmt1_compares_better, show_debug_info);
555 if (i != -1) {
556 if (best_cf)
557 *best_cf = cgv::data::component_format(float_texture_formats[i]);
558 gl_format = gl_float_texture_format_ids[i];
559 }
560 }
561 if (ensure_glew_initialized() && GLEW_ARB_texture_rg) {
562 if (show_debug_info)
563 std::cout << "find best match in rg_texture_formats:" << std::endl;
564 i = find_best_match(cf, rg_texture_formats, best_cf, cgv::data::fmt1_compares_better, show_debug_info);
565 if (i != -1) {
566 if (best_cf)
567 *best_cf = cgv::data::component_format(rg_texture_formats[i]);
568 gl_format = gl_rg_texture_format_ids[i];
569 }
570 }
571 return gl_format;
572}
573
574// return nr components
575unsigned configure_src_format(const cgv::data::const_data_view& data, GLuint& src_type, GLuint& src_fmt, const std::vector<data_view>* palettes)
576{
577 unsigned nr_comp = data.get_format()->get_nr_components();
578 // configure pixel transfer
579 // glPixelStorei(GL_PACK_SWAP_BYTES, swap_bytes ? GL_TRUE : GL_FALSE);
580 // glPixelStorei(GL_PACK_LSB_FIRST, lsb_first ? GL_TRUE : GL_FALSE);
581 // glPixelStorei(GL_PACK_ROW_LENGTH, (GLint) row_length);
582 glPixelStorei(GL_UNPACK_ALIGNMENT, (GLint) data.get_format()->get_alignment(0));
583 src_type = map_to_gl(data.get_format()->get_component_type());
585 if (cf != CF_UNDEF)
586 src_fmt = map_to_gl(cf, data.get_format()->get_integer_interpretation());
587 else {
588 if (palettes && palettes->size() > 0 && nr_comp == 1 && data.get_format()->get_component_name(0) == "0") {
589 src_fmt = GL_COLOR_INDEX;
590 const data_view& pv(palettes->at(0));
591 const data_format& pf(*pv.get_format());
592 nr_comp = pf.get_nr_components();
593 unsigned comp_size = pf.get_entry_size() / pf.get_nr_components();
594 std::vector<float> tmp;
595 tmp.resize(pf.get_width());
596 for (unsigned ci=0; ci<nr_comp; ++ci) {
597 glPixelTransferf(GL_RED_BIAS, 0.000001f);
598 for (unsigned i=0; i<pf.get_width(); ++i)
599 tmp[i] = pf.get<unsigned char>(ci, pv.step_i(pv.get_ptr<unsigned char>(), i))/255.0f;
600 switch (pf.get_component_name(ci)[0]) {
601 case 'R' : glPixelMapfv(GL_PIXEL_MAP_I_TO_R, GLsizei(pf.get_width()), &tmp.front()); break;
602 case 'G' : glPixelMapfv(GL_PIXEL_MAP_I_TO_G, GLsizei(pf.get_width()), &tmp.front()); break;
603 case 'B' : glPixelMapfv(GL_PIXEL_MAP_I_TO_B, GLsizei(pf.get_width()), &tmp.front()); break;
604 case 'A' : glPixelMapfv(GL_PIXEL_MAP_I_TO_A, GLsizei(pf.get_width()), &tmp.front()); break;
605 case 'L' :
606 glPixelMapfv(GL_PIXEL_MAP_I_TO_R, GLsizei(pf.get_width()), &tmp.front());
607 glPixelMapfv(GL_PIXEL_MAP_I_TO_G, GLsizei(pf.get_width()), &tmp.front());
608 glPixelMapfv(GL_PIXEL_MAP_I_TO_B, GLsizei(pf.get_width()), &tmp.front());
609 break;
610 }
611 }
612 }
613 }
614 return nr_comp;
615}
616
617bool load_texture(const cgv::data::const_data_view& data, unsigned gl_tex_format, unsigned level, unsigned cube_side, int num_array_layers, const std::vector<data_view>* palettes)
618{
619 unsigned nr_dim = data.get_format()->get_nr_dimensions();
620 const unsigned char* data_ptr = data.get_ptr<unsigned char>();
621 GLsizei w = GLsizei(data.get_format()->get_width());
622 bool cube_map = (nr_dim == 2) && (cube_side != -1);
623 bool texture_array = (nr_dim > 0) && (nr_dim < 4) && !cube_map && num_array_layers != 0;
624
625 if(!(ensure_glew_initialized() && GLEW_EXT_texture_array))
626 texture_array = false;
627
628 GLuint src_type, src_fmt;
629 unsigned nr_comp = configure_src_format(data, src_type, src_fmt, palettes);
630
631 bool gen_mipmap = level == -1;
632 if (gen_mipmap)
633 level = 0;
634 switch(nr_dim) {
635 case 1:
636 if(texture_array) {
637 glTexImage2D(GL_TEXTURE_1D_ARRAY, level, gl_tex_format, w, 1, 0, src_fmt, src_type, data_ptr);
638 } else {
639 glTexImage1D(GL_TEXTURE_1D, level, gl_tex_format, w, 0, src_fmt, src_type, data_ptr);
640 }
641 break;
642 case 2:
643 if(texture_array) {
644 if(num_array_layers < 0) {
645 glTexImage2D(GL_TEXTURE_1D_ARRAY, level, gl_tex_format, w, GLsizei(data.get_format()->get_height()), 0, src_fmt, src_type, data_ptr);
646 } else {
647 if(ensure_glew_initialized() && GLEW_EXT_texture3D) {
648 glTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_tex_format, w, GLsizei(data.get_format()->get_height()), 1, 0, src_fmt, src_type, data_ptr);
649 }
650 }
651 } else {
652 glTexImage2D(cube_map ? get_gl_cube_map_target(cube_side) : GL_TEXTURE_2D, level,
653 gl_tex_format, w, GLsizei(data.get_format()->get_height()), 0, src_fmt, src_type, data_ptr);
654 }
655 break;
656 case 3:
657 if(ensure_glew_initialized() && GLEW_EXT_texture3D) {
658 if(texture_array) {
659 GLsizei num_layers = GLsizei(data.get_format()->get_depth());
660 if(num_array_layers > 0)
661 num_layers = std::min(GLsizei(data.get_format()->get_depth()), num_array_layers);
662
663 glTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_tex_format, w, GLsizei(data.get_format()->get_height()),
664 num_layers, 0, src_fmt, src_type, data_ptr);
665 } else {
666 glTexImage3D(GL_TEXTURE_3D, level, gl_tex_format, w, GLsizei(data.get_format()->get_height()),
667 GLsizei(data.get_format()->get_depth()), 0, src_fmt, src_type, data_ptr);
668 }
669 }
670 break;
671 }
672 if(gen_mipmap) {
673 gen_mipmap = generate_mipmaps(nr_dim, texture_array);
674 }
675 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
676
677 return gen_mipmap;
678}
679
680bool replace_texture(const cgv::data::const_data_view& data, int level, int x, int y, int z, const std::vector<cgv::data::data_view>* palettes)
681{
682 unsigned nr_dim = data.get_format()->get_nr_dimensions();
683 const unsigned char* data_ptr = data.get_ptr<unsigned char>();
684 GLsizei w = GLsizei(data.get_format()->get_width());
685 bool cube_map = (nr_dim == 2) && (z != -1);
686
687 GLuint src_type, src_fmt;
688 unsigned nr_comp = configure_src_format(data, src_type, src_fmt, palettes);
689
690 bool gen_mipmap = level == -1;
691 if (gen_mipmap)
692 level = 0;
693 switch (nr_dim) {
694 case 1 :
695 glTexSubImage1D(GL_TEXTURE_1D, level, x, w, src_fmt, src_type, data_ptr);
696 break;
697 case 2 :
698 if (cube_map)
699 glTexSubImage2D(get_gl_cube_map_target(z), level, x, y, w,
700 GLsizei(data.get_format()->get_height()), src_fmt, src_type, data_ptr);
701 else
702 glTexSubImage2D(GL_TEXTURE_2D, level, x, y, w,
703 GLsizei(data.get_format()->get_height()), src_fmt, src_type, data_ptr);
704 break;
705 case 3 :
706 glTexSubImage3D(GL_TEXTURE_3D, level, x, y, z, w,
707 GLsizei(data.get_format()->get_height()), GLsizei(data.get_format()->get_depth()), src_fmt, src_type, data_ptr);
708 break;
709 }
710 if (gen_mipmap)
711 gen_mipmap = generate_mipmaps(nr_dim, false);
712 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
713 return gen_mipmap;
714}
715
716unsigned int create_texture(const cgv::data::const_data_view& dv, bool mipmap, const std::vector<data_view>* palettes, unsigned tex_id)
717{
718 return create_texture(dv,mipmap?(unsigned)-1:0, (unsigned)-1, palettes, tex_id);
719}
720
721unsigned int create_texture(const cgv::data::const_data_view& dv, unsigned level, unsigned cube_side, const std::vector<cgv::data::data_view>* palettes, unsigned tex_id)
722{
723 if (tex_id == -1)
724 glGenTextures(1,&tex_id);
725 unsigned nr_dim = dv.get_format()->get_nr_dimensions();
726 if ((nr_dim == 2) && (cube_side != -1))
727 glBindTexture(gl_tex_dim[3], tex_id);
728 else
729 glBindTexture(gl_tex_dim[nr_dim-1], tex_id);
730
731 unsigned gl_tex_format = find_best_texture_format(*dv.get_format(), 0, palettes);
732
733 if (load_texture(dv, gl_tex_format, level, cube_side, false, palettes))
734 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
735 else
736 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
737
738 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
739 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
740 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
741 return tex_id;
742}
743
744void read_texture(cgv::data::data_view& data, unsigned level) {
745 if(level == -1)
746 level = 0;
747
748 // Todo: Support arrays and cube maps.
749
750 unsigned nr_dim = data.get_format()->get_nr_dimensions();
751 unsigned char* data_ptr = data.get_ptr<unsigned char>();
752
753 GLuint src_type, src_fmt;
754 unsigned nr_comp = configure_src_format(data, src_type, src_fmt, nullptr);
755
756 glGetTexImage(gl_tex_dim[nr_dim-1], level, src_fmt, src_type, data_ptr);
757}
758
760bool cover_screen(context& ctx, shader_program* prog_ptr, bool flip_tex_v_coord, float xmin, float ymin, float xmax, float ymax, float umin, float vmin, float umax, float vmax)
761{
762 shader_program& prog = prog_ptr ? *prog_ptr : ctx.ref_default_shader_program(true);
763 bool was_enabled = prog.is_enabled();
764 if (!was_enabled) {
765 if (!prog.enable(ctx)) {
766 return false;
767 }
768 else
769 if (!prog_ptr)
770 ctx.set_color(rgba(1, 1, 1, 1));
771 }
772 int pos_idx = prog.get_position_index();
773 int tex_idx = prog.get_texcoord_index();
774 if (pos_idx == -1) {
775 ctx.error("cgv::render::gl::render_2d_texture_to_screen() passed program does not have position vertex attributes", &prog);
776 if (!was_enabled)
777 prog.disable(ctx);
778 return false;
779 }
781 ctx.set_modelview_matrix(cgv::math::identity4<double>());
783 ctx.set_projection_matrix(cgv::math::identity4<double>());
784
785 vec4 positions[4] = {
786 vec4(xmin,ymin, 0, 1),
787 vec4(xmax,ymin, 0, 1),
788 vec4(xmin,ymax, 0, 1),
789 vec4(xmax,ymax, 0, 1)
790 };
791 vec2 texcoords[8] = {
792 vec2(umin, vmin),
793 vec2(umax, vmin),
794 vec2(umin, vmax),
795 vec2(umax, vmax),
796 vec2(umin, vmax),
797 vec2(umax, vmax),
798 vec2(umin, vmin),
799 vec2(umax, vmin)
800 };
801
802 attribute_array_binding::set_global_attribute_array(ctx, pos_idx, positions, 4);
804 if (tex_idx != -1) {
805 attribute_array_binding::set_global_attribute_array(ctx, tex_idx, &texcoords[flip_tex_v_coord?4:0], 4);
807 }
808 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
809
811 if (tex_idx != -1)
813
816
817 if (!was_enabled)
818 prog.disable(ctx);
819 return true;
820}
821
823void gl_texture_to_screen(float xmin, float ymin, float xmax, float ymax, float umin, float vmin, float umax, float vmax)
824{
825 GLint mm;
826 glGetIntegerv(GL_MATRIX_MODE, &mm);
827
828 glMatrixMode(GL_MODELVIEW);
829 glPushMatrix();
830 glLoadIdentity();
831
832 glMatrixMode(GL_PROJECTION);
833 glPushMatrix();
834 glLoadIdentity();
835
836 glBegin(GL_QUADS);
837 glTexCoord2f(umin,vmin);
838 glVertex2f(xmin, ymin);
839
840 glTexCoord2f(umax,vmin);
841 glVertex2f(xmax, ymin);
842
843 glTexCoord2f(umax,vmax);
844 glVertex2f(xmax, ymax);
845
846 glTexCoord2f(umin,vmax);
847 glVertex2f(xmin, ymax);
848 glEnd();
849
850 glPopMatrix();
851
852 glMatrixMode(GL_MODELVIEW);
853 glPopMatrix();
854
855 glMatrixMode(mm);
856}
857
858void gl_1D_texture_to_screen(bool vary_along_x, float xmin, float ymin, float xmax, float ymax)
859{
860 GLint mm;
861 glGetIntegerv(GL_MATRIX_MODE, &mm);
862
863 glMatrixMode(GL_MODELVIEW);
864 glPushMatrix();
865 glLoadIdentity();
866
867 glMatrixMode(GL_PROJECTION);
868 glPushMatrix();
869 glLoadIdentity();
870
871 glBegin(GL_QUADS);
872 glTexCoord1f(0);
873 glVertex2f(xmin, ymin);
874
875 glTexCoord1f(vary_along_x ? 1.0f : 0.0f);
876 glVertex2f(xmax, ymin);
877
878 glTexCoord1f(1);
879 glVertex2f(xmax, ymax);
880
881 glTexCoord1f(vary_along_x ? 0.0f : 1.0f);
882 glVertex2f(xmin, ymax);
883 glEnd();
884
885 glPopMatrix();
886
887 glMatrixMode(GL_MODELVIEW);
888 glPopMatrix();
889
890 glMatrixMode(mm);
891}
892
894{
895 const char* vertex_shader_source = "\
896#version 330\n\
897\n\
898uniform float slice_coord;\n\
899layout(location = 0) in vec3 position;\n\
900layout(location = 3) in vec2 texcoord;\n\
901out vec3 tex_coord;\n\
902\n\
903void main()\n\
904{\n\
905 tex_coord.xy = texcoord;\n\
906 tex_coord.z = slice_coord;\n\
907 gl_Position = vec4(position,1.0);\n\
908}";
909
910 if (!prog.attach_code(ctx, vertex_shader_source, cgv::render::ST_VERTEX)) {
911 if (error_message)
912 *error_message = "could not attach vertex shader source";
913 return false;
914 }
915 if (!prog.link(ctx)) {
916 if (error_message)
917 *error_message = "could not link render to texture 3D program";
918 return false;
919 }
920
921 return true;
922}
923
924
925bool render_to_texture3D(context& ctx, shader_program& prog, TextureSampling texture_sampling, texture& target_tex, texture* target_tex2, texture* target_tex3, texture* target_tex4)
926{
927 // extract texture resolution
928 size_t tex_res[3] = { target_tex.get_width(), target_tex.get_height(), target_tex.get_depth() };
929 // check consistency of all texture resolutions
930 if (target_tex2) {
931 if (target_tex2->get_width() != tex_res[0] || target_tex2->get_height() != tex_res[1] || target_tex2->get_depth() != tex_res[2]) {
932 std::cerr << "ERROR in cgv:render::gl::render_to_texture3D: texture resolution of target_tex2 does not match resolution of target_tex" << std::endl;
933 return false;
934 }
935 }
936 if (target_tex3) {
937 if (target_tex3->get_width() != tex_res[0] || target_tex3->get_height() != tex_res[1] || target_tex3->get_depth() != tex_res[2]) {
938 std::cerr << "ERROR in cgv:render::gl::render_to_texture3D: texture resolution of target_tex3 does not match resolution of target_tex" << std::endl;
939 return false;
940 }
941 }
942 if (target_tex4) {
943 if (target_tex4->get_width() != tex_res[0] || target_tex4->get_height() != tex_res[1] || target_tex4->get_depth() != tex_res[2]) {
944 std::cerr << "ERROR in cgv:render::gl::render_to_texture3D: texture resolution of target_tex4 does not match resolution of target_tex" << std::endl;
945 return false;
946 }
947 }
948 // create fbo with resolution of slices
950 fbo.create(ctx, int(tex_res[0]), int(tex_res[1]));
951 fbo.attach(ctx, target_tex, 0, 0, 0);
952 if (!fbo.is_complete(ctx)) {
953 std::cerr << "fbo to update volume gradient not complete" << std::endl;
954 return false;
955 }
956 static float V[4 * 3] = {
957 -1, -1, 0, +1, -1, 0,
958 +1, +1, 0, -1, +1, 0
959 };
960 static int F[1 * 4] = {
961 0, 1, 2, 3
962 };
963 float T[4 * 2] = {
964 0, 0, 1, 0,
965 1, 1, 0, 1
966 };
967 if (texture_sampling == TS_VERTEX) {
968 T[0] = T[6] = float(-0.5 / tex_res[0]);
969 T[2] = T[4] = float(1.0 + 0.5 / tex_res[0]);
970 T[1] = T[3] = float(-0.5 / tex_res[1]);
971 T[5] = T[7] = float(1.0 + 0.5 / tex_res[1]);
972 }
974 ctx.set_viewport(ivec4(0, 0, int(tex_res[0]), int(tex_res[1])));
975 int slice_coord_loc = prog.get_uniform_location(ctx, "slice_coord");
976 // go through slices
977 for (int i = 0; i < (int) tex_res[2]; i++) {
978
979 if (slice_coord_loc != -1) {
980 float slice_coord = (texture_sampling == TS_CELL) ? (i + 0.5f) / tex_res[2] : (float)i / (tex_res[2] - 1);
981 prog.set_uniform(ctx, slice_coord_loc, slice_coord);
982 }
983 // attach textures to fbo
984 fbo.attach(ctx, target_tex, i, 0, 0);
985 if (target_tex2)
986 fbo.attach(ctx, *target_tex2, i, 0, 1);
987 if (target_tex3)
988 fbo.attach(ctx, *target_tex3, i, 0, 2);
989 if (target_tex4)
990 fbo.attach(ctx, *target_tex4, i, 0, 3);
991 fbo.enable(ctx, 0);
992 ctx.draw_faces(V, 0, T, F, 0, F, 1, 4);
993 fbo.disable(ctx);
994 }
996 return true;
997}
998
999
1000 }
1001 }
1002}
the component format inherits the information of a packing_info and adds information on the component...
std::string get_component_name(unsigned int i) const
return the name of the component with index i
ComponentIntegerInterpretation get_integer_interpretation() const
return current integer interpretation
cgv::type::info::TypeId get_component_type() const
return the component type
ComponentFormat get_standard_component_format() const
return whether the component format is one of the standard formats
void set_component_names(const std::string &_component_name_list)
set component names from a comma or colon separated list of names
unsigned int get_nr_components() const
return the number of components
The const_data_view has the functionality of the data_view but uses a const pointer and therefore doe...
Definition data_view.h:221
A data_format describes a multidimensional data block of data entries.
Definition data_format.h:17
unsigned get_nr_dimensions() const
return the number of dimensions of the data set
size_t get_depth() const
return the resolution in the third dimension, or 1 if not defined
unsigned get_alignment(unsigned i) const
return the alignment of a given dimension, where the alignment of the last dimension is always 1 and ...
size_t get_width() const
return the resolution in the first dimension, or 1 if not defined
size_t get_height() const
return the resolution in the second dimension, or 1 if not defined
const data_format * get_format() const
return the component format
Definition data_view.cxx:73
cgv::type::func::transfer_const< P, S * >::type get_ptr() const
return a data pointer to type S
Definition data_view.h:61
the data view gives access to a data array of one, two, three or four dimensions.
Definition data_view.h:153
static bool enable_global_array(const context &ctx, int loc)
enable attribute array of given location
static bool set_global_attribute_array(const context &ctx, int loc, const vertex_buffer &vbo, type_descriptor td, size_t size, size_t offset, unsigned stride=0)
point array of vertex attribute at location loc to vertex buffer array array stored in CPU memory; in...
static bool disable_global_array(const context &ctx, int loc)
disable attribute array of given location
base class for all drawables, which is independent of the used rendering API.
Definition context.h:668
void push_window_transformation_array()
push a copy of the current viewport and depth range arrays defining the window transformations
Definition context.cxx:1964
virtual void set_color(const rgba &clr)
set the current color
Definition context.cxx:1711
virtual void error(const std::string &message, const render_component *rc=0) const
error handling
Definition context.cxx:306
virtual shader_program & ref_default_shader_program(bool texture_support=false)=0
return a reference to a shader program used to render without illumination
virtual void draw_faces(const float *vertices, const float *normals, const float *tex_coords, const int *vertex_indices, const int *normal_indices, const int *tex_coord_indices, int nr_faces, int face_degree, bool flip_normals=false) const =0
pass geometry of given faces to current shader program and generate draw calls to render triangles
virtual void pop_window_transformation_array()
restore previous viewport and depth range arrays defining the window transformations
Definition context.cxx:1969
void pop_projection_matrix()
see push_P for an explanation
Definition context.cxx:1919
void push_projection_matrix()
same as push_V but for the projection matrix - a different matrix stack is used.
Definition context.cxx:1914
virtual void set_projection_matrix(const dmat4 &P)
set the current projection matrix, which transforms from eye to clip space
Definition context.cxx:1947
void pop_modelview_matrix()
see push_V for an explanation
Definition context.cxx:1908
void push_modelview_matrix()
push the current viewing matrix onto a matrix stack for viewing matrices.
Definition context.cxx:1896
virtual void set_viewport(const ivec4 &viewport, int array_index=-1)
set the current viewport or one of the viewports in the window transformation array
Definition context.cxx:1995
virtual void set_modelview_matrix(const dmat4 &MV)
set the current modelview matrix, which transforms from world to eye space
Definition context.cxx:1930
this class encapsulate frame buffers that live on the GPU and can be used as destination for the rend...
bool create(const context &ctx, int _width=-1, int _height=-1)
create framebuffer if extension is supported, otherwise return false.
bool is_complete(const context &ctx) const
check for completeness, if not complete, get the reason in last_error
bool attach(const context &ctx, const render_buffer &rb, int i=0)
attach render buffer to depth buffer if it is a depth buffer, to stencil if it is a stencil buffer or...
bool enable(context &ctx, int i0=-1, int i1=-1, int i2=-1, int i3=-1, int i4=-1, int i5=-1, int i6=-1, int i7=-1, int i8=-1, int i9=-1, int i10=-1, int i11=-1, int i12=-1, int i13=-1, int i14=-1, int i15=-1)
enable the framebuffer either with all color attachments if no arguments are given or if arguments ar...
bool disable(context &ctx)
disable the framebuffer object
a shader program combines several shader code fragments to a complete definition of the shading pipel...
bool enable(context &ctx)
enable the shader program
bool disable(context &ctx)
disable shader program and restore fixed functionality
bool set_uniform(const context &ctx, const std::string &name, const T &value, bool generate_error=false)
Set the value of a uniform by name, where the type can be any of int, unsigned, float,...
bool attach_code(const context &ctx, const shader_code &code)
attach a compiled shader code instance that is managed outside of program
bool link(const context &ctx, bool show_error=false)
link shaders to an executable program
bool is_enabled() const
check whether program is currently enabled
int get_uniform_location(const context &ctx, const std::string &name) const
query location index of an uniform
the texture class encapsulates all functionality independent of the rendering api.
Definition texture.h:15
namespace for data management components
ComponentFormat
define standard formats, which should be used to avoid wrong assignment of component names
@ CF_S
depth component
ComponentIntegerInterpretation
define different interpretations of integer components
unsigned find_best_match(const component_format &fmt, const char **format_descriptions, const component_format *fmt0, bool(*fmt1_better_match)(const component_format &fmt, const component_format &fmt1, const component_format &fmt2), bool show_debug_info)
find the best matching format in a list of formats described by strings and return index of best matc...
bool fmt1_compares_better(const component_format &fmt, const component_format &fmt1, const component_format &fmt2)
default function to check whether fmt1 is a better match to fmt than fmt2
void gl_texture_to_screen(float xmin, float ymin, float xmax, float ymax, float umin, float vmin, float umax, float vmax)
cover the current viewport with a textured quad
bool load_texture(const cgv::data::const_data_view &data, unsigned gl_tex_format, unsigned level, unsigned cube_side, int num_array_layers, const std::vector< data_view > *palettes)
load data to a texture with the glTexImage commands and generate mipmaps if the level parameter is -1...
unsigned int create_texture(const cgv::data::const_data_view &dv, bool mipmap, const std::vector< data_view > *palettes, unsigned tex_id)
create a texture from the given data view creating a mipmap pyramid
void read_texture(cgv::data::data_view &data, unsigned level)
read back a texture into a data view with the glGetTexImage command
bool complete_program_form_render_to_texture3D(cgv::render::context &ctx, cgv::render::shader_program &prog, std::string *error_message)
complete the given shader program that is assumed to have a working fragment shader.
bool replace_texture(const cgv::data::const_data_view &data, int level, int x, int y, int z, const std::vector< cgv::data::data_view > *palettes)
replace part or complete data of currently bound texture with the data in the given data view
bool ensure_glew_initialized()
initialize glew in the first call to this function and always return whether this was successful
Definition gl.cxx:19
bool cover_screen(context &ctx, shader_program *prog_ptr, bool flip_tex_v_coord, float xmin, float ymin, float xmax, float ymax, float umin, float vmin, float umax, float vmax)
cover the current viewport with a textured quad using the textured default shader program or the one ...
void gl_1D_texture_to_screen(bool vary_along_x, float xmin, float ymin, float xmax, float ymax)
cover the current viewport or a rectangle with it with a quad textured by a 1D texture
unsigned find_best_texture_format(const cgv::data::component_format &_cf, cgv::data::component_format *best_cf, const std::vector< data_view > *palettes, bool show_debug_info)
map the given component format to the best matching available gl component format
bool generate_mipmaps(unsigned int dim, bool is_cubemap, bool is_array, std::string *last_error)
generate mipmaps for the currently bound texture, which has the given texture dimension; optionally p...
unsigned get_gl_cube_map_target(unsigned side)
return one of the six cube map sides gl enums
bool render_to_texture3D(context &ctx, shader_program &prog, TextureSampling texture_sampling, texture &target_tex, texture *target_tex2, texture *target_tex3, texture *target_tex4)
Render to the given target 3D texture with the given shader program that must be completed with the f...
TextureSampling
different sampling strategies for rendering to textures that steer the computation of the tex_coord i...
Definition context.h:301
@ TS_VERTEX
tex_coord ranges from [0,0,0] to [1,1,1]
Definition context.h:303
@ TS_CELL
for texture resulution N x M x L the tex_coord ranges from [1/2N, 1/2M, 1/2L] to [1-1/2N,...
Definition context.h:302
TypeId
ids for the different types and type constructs
Definition type_id.h:12
the cgv namespace
Definition print.h:11
cgv::math::fvec< float, 4 > vec4
declare type of 4d single precision floating point vectors (used for homogeneous coordinates)
Definition fvec.h:663
cgv::media::color< float, cgv::media::RGB, cgv::media::OPACITY > rgba
declare rgba color type with 32 bit components
Definition color.h:893
cgv::math::fvec< int32_t, 4 > ivec4
declare type of 4d 32 bit integer vectors
Definition fvec.h:690
cgv::math::fvec< float, 2 > vec2
declare type of 2d single precision floating point vectors
Definition fvec.h:659