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