cgv
Loading...
Searching...
No Matches
gl_context.cxx
1#include <cgv/base/group.h>
2#include "gl_context.h"
3#include "gl_tools.h"
4#include <cgv_gl/gl/wgl.h>
5#ifdef _WIN32
6#undef TA_LEFT
7#undef TA_TOP
8#undef TA_RIGHT
9#undef TA_BOTTOM
10#endif
11#include <cgv/base/base.h>
12#include <cgv/base/action.h>
13#include <cgv/render/drawable.h>
14#include <cgv/render/shader_program.h>
15#include <cgv/render/attribute_array_binding.h>
16#include <cgv/render/vertex_buffer.h>
17#include <cgv/render/textured_material.h>
18#include <cgv/utils/scan.h>
19#include <cgv/media/image/image_writer.h>
20#include <cgv/gui/event_handler.h>
21#include <cgv/math/ftransform.h>
22#include <cgv/math/geom.h>
23#include <cgv/math/inv.h>
24#include <cgv/type/standard_types.h>
25#include <cgv/os/clipboard.h>
26
27using namespace cgv::base;
28using namespace cgv::type;
29using namespace cgv::type::info;
30using namespace cgv::gui;
31using namespace cgv::os;
32using namespace cgv::math;
33using namespace cgv::media::font;
34using namespace cgv::media::illum;
35
36namespace cgv {
37 namespace render {
38 namespace gl {
39
41{
42#ifdef _WIN32
51#else
60#endif
61 std::vector<int> attrib_list;
62 int version = 0;
63 if (cc.version_major < 1)
64 version = 46;
65 else
66 version = 10 * cc.version_major + (cc.version_minor >= 0 ? cc.version_minor : 0);
67 if ((version > 30 && cc.forward_compatible) || cc.debug) {
68 attrib_list.push_back(CONTEXT_FLAGS);
69 attrib_list.push_back(
70 (cc.forward_compatible ? CONTEXT_FORWARD_COMPATIBLE_BIT : 0) +
71 (cc.debug ? CONTEXT_DEBUG_BIT : 0));
72 }
73 if (cc.version_major > 0) {
75 attrib_list.push_back(cc.version_major);
76 }
77 if (cc.version_minor >= 0) {
79 attrib_list.push_back(cc.version_minor);
80 }
81 if (version > 31) {
83 attrib_list.push_back(
85 }
86 attrib_list.push_back(0);
87 return attrib_list;
88}
89
90GLenum map_to_gl(PrimitiveType primitive_type)
91{
92 static const GLenum gl_primitive_type[] = {
93 GLenum(-1),
105 GL_QUADS,
109 };
110 return gl_primitive_type[primitive_type];
111}
112
114{
115 static const GLenum gl_material_side[] = {
116 GLenum(0),
117 GL_FRONT,
118 GL_BACK,
120 };
122}
123
125{
126 static const GLenum gl_access_type[] = {
130 };
132}
133
135{
136 static const GLenum gl_blend_func[] = {
137 GL_ZERO,
138 GL_ONE,
156 };
158}
159
161{
162 static const GLenum gl_compare_func[] = {
163 GL_LEQUAL,
164 GL_GEQUAL,
165 GL_LESS,
167 GL_EQUAL,
169 GL_ALWAYS,
171 };
173}
174
175static const GLenum gl_depth_format_ids[] =
176{
181};
182
183static const GLenum gl_color_buffer_format_ids[] =
184{
185 GL_RGB,
186 GL_RGBA
187};
188
189static const char* depth_formats[] =
190{
191 "[D]",
192 "uint16[D]",
193 "uint32[D:24]",
194 "uint32[D]",
195 0
196};
197
198static const char* color_buffer_formats[] =
199{
200 "[R,G,B]",
201 "[R,G,B,A]",
202 0
203};
204
206{
207 static const GLenum gl_texture_type[] = {
208 GLenum(0),
217 };
219}
220
221GLenum get_tex_bind(TextureType texture_type)
222{
223 static const GLenum gl_tex_binding[] = {
224 GLenum(0),
234 };
236}
237
239{
240 static const GLenum gl_texture_wrap[] = {
241 GL_REPEAT,
242 GL_CLAMP,
243 GL_CLAMP_TO_EDGE,
249 };
251}
252
254{
255 static const GLenum gl_texture_filter[] = {
257 GL_LINEAR,
263 };
265}
266
267GLboolean map_to_gl(bool flag) {
268 return flag ? GL_TRUE : GL_FALSE;
269}
270
271GLuint get_gl_id(const void* handle)
272{
273 return (const GLuint&)handle - 1;
274}
275
276void* get_handle(GLuint id)
277{
278 void* handle = 0;
279 (GLuint&)handle = id + 1;
280 return handle;
281}
282
283void gl_context::put_id(void* handle, void* ptr) const
284{
285 *static_cast<GLuint*>(ptr) = get_gl_id(handle);
286}
287
290{
292 (GLuint&)tex.internal_format = gl_format;
293}
294
297{
298 if (tex.internal_format)
299 return (const GLuint&)tex.internal_format;
302 return gl_format;
303}
304
305
306void gl_set_material_color(GLenum side, const cgv::media::illum::phong_material::color_type& c, float alpha, GLenum type)
307{
308 GLfloat v[4] = { c[0],c[1],c[2],c[3] * alpha };
309 glMaterialfv(side, type, v);
310}
311
314{
315 if (ms == MS_NONE)
316 return;
317 unsigned side = map_to_gl(ms);
318 gl_set_material_color(side, mat.ambient, alpha, GL_AMBIENT);
319 gl_set_material_color(side, mat.diffuse, alpha, GL_DIFFUSE);
320 gl_set_material_color(side, mat.specular, alpha, GL_SPECULAR);
321 gl_set_material_color(side, mat.emission, alpha, GL_EMISSION);
322 glMaterialf(side, GL_SHININESS, mat.shininess);
323}
324
327{
328 return info_font_size;
329}
332{
333 if (info_font_face.empty()) {
335 if (!info_font.empty())
336 info_font_face = info_font->get_font_face(FFA_REGULAR);
337 }
338 return info_font_face;
339}
340
343{
344 frame_buffer_stack.top()->handle = get_handle(0);
345 max_nr_indices = 0;
346 max_nr_vertices = 0;
347 info_font_size = 14;
348 show_help = false;
349 show_stats = false;
350
351 // set initial GL state from stack contents
356
361}
362
365{
366 return RA_OPENGL;
367}
368
369//GL_STACK_OVERFLOW, "stack overflow"
370//GL_STACK_UNDERFLOW, "stack underflow",
371std::string get_source_tag_name(GLenum tag)
372{
373 static std::map<GLenum, const char*> source_tags = {
374 { GL_DEBUG_SOURCE_API, "api" },
375 { GL_DEBUG_SOURCE_WINDOW_SYSTEM, "window system" },
376 { GL_DEBUG_SOURCE_SHADER_COMPILER, "shader compiler" },
377 { GL_DEBUG_SOURCE_THIRD_PARTY, "3rd party" },
378 { GL_DEBUG_SOURCE_APPLICATION, "application" },
379 { GL_DEBUG_SOURCE_OTHER, "other" }
380 };
381 return source_tags[tag];
382}
383
384std::string get_type_tag_name(GLenum tag)
385{
386 static std::map<GLenum, const char*> type_tags = {
387 { GL_DEBUG_TYPE_ERROR, "error" },
388 { GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, "deprecated behavior" },
389 { GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, "undefinded behavior" },
390 { GL_DEBUG_TYPE_PORTABILITY, "portability" },
391 { GL_DEBUG_TYPE_PERFORMANCE, "performance" },
392 { GL_DEBUG_TYPE_OTHER, "other" },
393 { GL_DEBUG_TYPE_MARKER, "marker" },
394 { GL_DEBUG_TYPE_PUSH_GROUP, "push group" },
395 { GL_DEBUG_TYPE_POP_GROUP, "pop group" }
396 };
397 return type_tags[tag];
398}
399
400std::string get_severity_tag_name(GLenum tag)
401{
402 static std::map<GLenum, const char*> severity_tags = {
403 { GL_DEBUG_SEVERITY_NOTIFICATION, "notification" },
404 { GL_DEBUG_SEVERITY_HIGH, "high" },
405 { GL_DEBUG_SEVERITY_MEDIUM, "medium" },
406 { GL_DEBUG_SEVERITY_LOW, "low" }
407 };
408 return severity_tags[tag];
409};
410
411void GLAPIENTRY debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
412{
414 return;
415 const gl_context* ctx = reinterpret_cast<const gl_context*>(userParam);
416 std::string msg(message, length);
417 msg = std::string("GLDebug Message[") + cgv::utils::to_string(id) + "] from " + get_source_tag_name(source) + " of type " + get_type_tag_name(type) + " of severity " + get_severity_tag_name(severity) + "\n" + msg;
418 ctx->error(msg);
419}
420
423{
425 error("gl_context::configure_gl could not initialize glew");
426 return false;
427 }
429 version_major = version_string[0] - '0';
430 version_minor = version_string[2] - '0';
431 if (version_major >= 3) {
434 // weird behavior under windows or just nvidia or just my laptop (Stefan)??
437 }
438 else {
439 debug = false;
440 forward_compatible = false;
441 }
442 int version = 10 * version_major + version_minor;
443 if (version >= 32) {
446#ifdef _DEBUG
447 if (context_profile != 0) {
449 if (core_profile)
450 std::cerr << "WARNING: Ignoring that GL_CONTEXT_PROFILE_MASK yields compatibility profile for context created as core." << std::endl;
451 else
452 std::cerr << "WARNING: Ignoring that GL_CONTEXT_PROFILE_MASK does not yield compatibility profile for context created as such." << std::endl;
453 }
454 }
455 else {
456 std::cerr << "WARNING: Ignoring that GL_CONTEXT_PROFILE_MASK yields zero." << std::endl;
457 }
458#endif
459 }
460 else
461 core_profile = false;
463 std::string vendor_string(reinterpret_cast<const char*>(vendor_c_string));
465
466 if (vendor_string.find("NVIDIA") != std::string::npos)
467 gpu_vendor = GPU_VENDOR_NVIDIA;
468 else if (vendor_string.find("INTEL") != std::string::npos)
469 gpu_vendor = GPU_VENDOR_INTEL;
470 else if (vendor_string.find("AMD") != std::string::npos || vendor_string.find("ATI") != std::string::npos)
471 gpu_vendor = GPU_VENDOR_AMD;
472
473 // query device capabilities
474 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &gpu_capabilities.max_render_buffer_size);
478 for(unsigned i = 0; i < 3; ++i)
480 for(unsigned i = 0; i < 3; ++i)
482
483#ifdef _DEBUG
484 std::cout << "OpenGL version " << version_major << "." << version_minor << (core_profile?" (core)":" (compatibility)") << (debug?" (debug)":"") << (forward_compatible?" (forward_compatible)":"") << std::endl;
487 if (vendor_c_string)
488 std::cout << " vendor : " << vendor_c_string << std::endl;
490 std::cout << " renderer : " << renderer_c_string << std::endl;
492 std::cout << " glslversion: " << glslversion_c_string << std::endl;
493#endif
494 if (debug) {
496 if (version >= 43) {
498 if (!check_gl_error("gl_context::configure() debug output"))
499 glDebugMessageCallback(debug_callback, this);
500 }
501 }
502 // use the eye location to compute the specular lighting
503 if (!core_profile) {
505 // this makes opengl normalize all surface normals before lighting calculations,
506 // which is essential when using scaling to deform tesselated primities
508
509 // should be initialized by the driver, but better be safe than risk errors later
511 }
513// if (check_gl_error("gl_context::configure_gl before init of children"))
514// return false;
515
516 group_ptr grp(dynamic_cast<group*>(this));
518 for (unsigned i = 0; i<grp->get_nr_children(); ++i)
519 traverser(sma, "nc").traverse(grp->get_child(i));
520
521// if (check_gl_error("gl_context::configure_gl after init of children."))
522// return false;
523
524 return true;
525}
526
527void gl_context::resize_gl()
528{
529 group_ptr grp(dynamic_cast<group*>(this));
531 if (grp) {
534 }
535}
536
541
546
551
557
558void gl_context::clear_background(bool color_flag, bool depth_flag, bool stencil_flag, bool accum_flag) {
559 GLenum bits = 0;
560 if(color_flag)
562 if(depth_flag)
564 if(stencil_flag)
568 if(bits)
569 glClear(bits);
570}
571
574{
575 if (current_font_size == 0)
576 return get_info_font_size();
577 return current_font_size;
578}
586
587void gl_context::init_render_pass()
588{
589#ifdef WIN32
591#else
593#endif
596 else
598
602 for (unsigned i = 0; i < nr_default_light_sources; ++i)
604
605 for (unsigned i = 0; i < nr_default_light_sources; ++i)
608 else
610 }
611 else if ((last_render_pass_flags & RPF_SET_LIGHTS) == 0) {
612 for (unsigned i = 0; i < nr_default_light_sources; ++i)
615 }
617
620 }
622 // this mode allows to define the ambient and diffuse color of the surface material
623 // via the glColor commands
625 }
627 // set some default settings
629 set_cull_state(CM_BACKFACE);
630 if (!core_profile)
632 }
634 set_projection_matrix(cgv::math::perspective4<double>(45.0, (double)get_width()/get_height(),0.001,1000.0));
635
637 set_modelview_matrix(cgv::math::look_at4<double>(vec3(0,0,10), vec3(0,0,0), vec3(0,1,0)));
638
639 if (check_gl_error("gl_context::init_render_pass before init_frame"))
640 return;
641
642 group* grp = dynamic_cast<group*>(this);
646 }
647
648 if (check_gl_error("gl_context::init_render_pass after init_frame"))
649 return;
650 // this defines the background color to which the frame buffer is set by glClear
653 // this defines the background depth buffer value set by glClear
656 // this defines the background depth buffer value set by glClear
659 // this defines the background color to which the accum buffer is set by glClear
667 );
668}
669
671void gl_context::finish_render_pass()
672{
673}
674
676{
677 std::ostream& os;
678 format_callback_handler(std::ostream& _os) : os(_os)
679 {
680 }
683 {
684 os << "\a";
685 return false;
686 }
689 {
690 os << "\b";
691 return false;
692 }
693
694};
695
696void gl_context::draw_textual_info()
697{
698 if (show_help || show_stats) {
702
705
706 set_cursor(20, get_height()-1-20);
707
708 vec4 bg = get_bg_color();
709 //if (bg_r + bg_g + bg_b < 1.5f)
710 if (bg[0] + bg[1] + bg[2] < 1.5f)
711 set_color(rgba(1, 1, 1, 1));
712 else
713 set_color(rgba(0, 0, 0, 1));
714
715 // traverse objects for show_stats callback
716 format_callback_handler fch(output_stream());
717 group_ptr grp(dynamic_cast<group*>(this));
718 if (grp && show_stats) {
720 traverser(sma, "nc").traverse(grp, &fch);
721 output_stream() << std::endl;
722 }
723 //if (bg_r + bg_g + bg_b < 1.5f)
724 if(bg[0] + bg[1] + bg[2] < 1.5f)
725 set_color(rgba(1, 1, 0, 1));
726 else
727 set_color(rgba(0.4f, 0.3f, 0, 1));
728
729 if (grp && show_help) {
730 // collect help from myself and all children
732 traverser(sma, "nc").traverse(grp, &fch);
733 output_stream().flush();
734 }
737 }
738}
739
740void gl_context::perform_screen_shot()
741{
742 glFlush();
744 if (!read_frame_buffer(dv))
745 return;
746 std::string ext("bmp");
748 if (cgv::utils::is_element("png",exts))
749 ext = "png";
750 else if (cgv::utils::is_element("tif",exts))
751 ext = "tif";
752 cgv::media::image::image_writer wr(std::string("screen_shot.")+ext);
753 if (wr.is_format_supported(*dv.get_format()))
754 wr.write_image(dv);
755}
756
758void gl_context::enumerate_program_uniforms(shader_program& prog, std::vector<std::string>& names, std::vector<int>* locations_ptr, std::vector<int>* sizes_ptr, std::vector<int>* types_ptr, bool show) const
759{
760 GLint count;
761 glGetProgramiv(get_gl_id(prog.handle), GL_ACTIVE_UNIFORMS, &count);
762 for (int i = 0; i < count; ++i) {
763 GLchar name[1000];
764 GLsizei length;
765 GLint size;
766 GLenum type;
767 glGetActiveUniform(get_gl_id(prog.handle), i, 1000, &length, &size, &type, name);
768 std::string name_str(name, length);
769 names.push_back(name_str);
770 if (sizes_ptr)
771 sizes_ptr->push_back(size);
772 if (types_ptr)
773 types_ptr->push_back(type);
774 int loc = glGetUniformLocation(get_gl_id(prog.handle), name_str.c_str());
775 if (locations_ptr)
776 locations_ptr->push_back(loc);
777 if (show)
778 std::cout << i << " at " << loc << " = " << name_str << ":" << type << "[" << size << "]" << std::endl;
779 }
780}
781
783void gl_context::enumerate_program_attributes(shader_program& prog, std::vector<std::string>& names, std::vector<int>* locations_ptr, std::vector<int>* sizes_ptr, std::vector<int>* types_ptr, bool show) const
784{
785 GLint count;
786 glGetProgramiv(get_gl_id(prog.handle), GL_ACTIVE_ATTRIBUTES, &count);
787 for (int i = 0; i < count; ++i) {
788 GLchar name[1000];
789 GLsizei length;
790 GLint size;
791 GLenum type;
792 glGetActiveAttrib(get_gl_id(prog.handle), i, 1000, &length, &size, &type, name);
793 std::string name_str(name, length);
794 names.push_back(name_str);
795 if (sizes_ptr)
796 sizes_ptr->push_back(size);
797 if (types_ptr)
798 types_ptr->push_back(type);
799 int loc = glGetAttribLocation(get_gl_id(prog.handle), name_str.c_str());
800 if (locations_ptr)
801 locations_ptr->push_back(loc);
802 if (show)
803 std::cout << i << " at " << loc << " = " << name_str << ":" << type << "[" << size << "]" << std::endl;
804 }
805}
806
809{
812 glColor4fv(&clr[0]);
813 }
814 if (shader_program_stack.empty())
815 return;
817 if (!prog.does_context_set_color())
818 return;
819 int clr_loc = prog.get_color_index();
820 if (clr_loc == -1)
821 return;
822 prog.set_attribute(*this, clr_loc, clr);
823}
824
827{
829 unsigned side = map_to_gl(MS_FRONT_AND_BACK);
830 float alpha = 1.0f - material.transparency;
831 gl_set_material_color(side, material.ambient_occlusion * material.diffuse_reflectance, alpha, GL_AMBIENT);
832 gl_set_material_color(side, material.diffuse_reflectance, alpha, GL_DIFFUSE);
833 gl_set_material_color(side, material.specular_reflectance, alpha, GL_SPECULAR);
834 gl_set_material_color(side, material.emission, alpha, GL_EMISSION);
835 glMaterialf(side, GL_SHININESS, 1.0f / (material.roughness + 1.0f / 128.0f));
836 }
837 context::set_material(material);
838}
839
842{
844 mat.enable_textures(*this);
845}
846
849{
850 mat.disable_textures(*this);
853}
854
855void gl_context::destruct_render_objects()
856{
857 for (unsigned i = 0; i < 4; ++i)
858 progs[i].destruct(*this);
859}
860
863{
864 if (!texture_support) {
865 if (!progs[0].is_created()) {
866 if (!progs[0].build_program(*this, "default.glpr")) {
867 error("could not build default shader program from default.glpr");
868 exit(0);
869 }
870 progs[0].specify_standard_uniforms(true, false, false, true);
871 progs[0].specify_standard_vertex_attribute_names(*this, true, false, false);
872 progs[0].allow_context_to_set_color(true);
873 }
874 return progs[0];
875 }
876 if (!progs[1].is_created()) {
877 if (!progs[1].build_program(*this, "textured_default.glpr")) {
878 error("could not build default shader program with texture support from textured_default.glpr");
879 exit(0);
880 }
881 progs[1].set_uniform(*this, "texture", 0);
882 progs[1].specify_standard_uniforms(true, false, false, true);
883 progs[1].specify_standard_vertex_attribute_names(*this, true, false, true);
884 progs[1].allow_context_to_set_color(true);
885 }
886 return progs[1];
887}
888
891{
892 if (!texture_support) {
893 if (!progs[2].is_created()) {
894 if (!progs[2].build_program(*this, "default_surface.glpr")) {
895 error("could not build surface shader program from default_surface.glpr");
896 exit(0);
897 }
898 progs[2].specify_standard_uniforms(true, true, true, true);
899 progs[2].specify_standard_vertex_attribute_names(*this, true, true, false);
900 progs[2].allow_context_to_set_color(true);
901 }
902 return progs[2];
903 }
904 if (!progs[3].is_created()) {
905 if (!progs[3].build_program(*this, "textured_surface.glpr")) {
906 error("could not build surface shader program with texture support from textured_surface.glpr");
907 exit(0);
908 }
909 progs[3].specify_standard_uniforms(true, true, true, true);
910 progs[3].specify_standard_vertex_attribute_names(*this, true, true, true);
911 progs[3].allow_context_to_set_color(true);
912 }
913 return progs[3];
914}
915
917{
919 GLint max_nr_lights;
920 glGetIntegerv(GL_MAX_LIGHTS, &max_nr_lights);
921 for (GLint light_idx = 0; light_idx < max_nr_lights; ++light_idx) {
924 continue;
925 }
926 GLfloat col[4] = { 1,1,1,1 };
928 *(rgb*)col = light.get_emission()*light.get_ambient_scale();
930 *(rgb*)col = light.get_emission();
932 *(rgb*)col = light.get_emission();
934
935 GLfloat pos[4] = { 0,0,0,light.get_type() == cgv::media::illum::LT_DIRECTIONAL ? 0.0f : 1.0f };
936 *(vec3*)pos = light.get_position();
938 if (light.get_type() != cgv::media::illum::LT_DIRECTIONAL) {
939 glLightf(GL_LIGHT0 + light_idx, GL_CONSTANT_ATTENUATION, light.get_constant_attenuation());
940 glLightf(GL_LIGHT0 + light_idx, GL_LINEAR_ATTENUATION, light.get_linear_attenuation());
941 glLightf(GL_LIGHT0 + light_idx, GL_QUADRATIC_ATTENUATION, light.get_quadratic_attenuation());
942 }
943 else {
947 }
948 if (light.get_type() == cgv::media::illum::LT_SPOT) {
949 glLightf(GL_LIGHT0 + light_idx, GL_SPOT_CUTOFF, light.get_spot_cutoff());
950 glLightf(GL_LIGHT0 + light_idx, GL_SPOT_EXPONENT, light.get_spot_exponent());
951 glLightfv(GL_LIGHT0 + light_idx, GL_SPOT_DIRECTION, light.get_spot_direction().data());
952 }
953 else {
956 static float dir[3] = { 0,0,1 };
958 }
960 }
961 }
963}
964
965void gl_context::tesselate_arrow(double length, double aspect, double rel_tip_radius, double tip_aspect, int res, bool edges)
966{
967 double cyl_radius = length*aspect;
970 double cyl_length = length - cone_length;
974 mul_modelview_matrix(cgv::math::rotate4(180.0,1.0,0.0,0.0));
975 tesselate_unit_disk(res, false, edges);
977
978 mul_modelview_matrix(cgv::math::translate4(0.0,0.0,1.0));
979 tesselate_unit_cylinder(res, false, edges);
980
981 mul_modelview_matrix(cgv::math::translate4(0.0, 0.0, 1.0));
984 mul_modelview_matrix(cgv::math::rotate4(180.0, 1.0, 0.0, 0.0));
985 tesselate_unit_disk(res, false, edges);
987 mul_modelview_matrix(cgv::math::translate4(0.0, 0.0, 1.0));
988 tesselate_unit_cone(res, false, edges);
990}
991
993void gl_context::rotate_vector_to_target(const dvec3& vector, const dvec3& target)
994{
995 double angle;
996 dvec3 axis;
997 compute_rotation_axis_and_angle_from_vector_pair(vector, target, axis, angle);
998 mul_modelview_matrix(cgv::math::rotate4<double>(180.0 / M_PI * angle, axis));
999}
1000
1002void gl_context::tesselate_arrow(const dvec3& start, const dvec3& end, double aspect, double rel_tip_radius, double tip_aspect, int res, bool edges)
1003{
1004 if ((start - end).length() < 1e-8) {
1005 error("ignored tesselate arrow called with start and end closer then 1e-8");
1006 return;
1007 }
1009 mul_modelview_matrix(cgv::math::translate4<double>(start));
1010 rotate_vector_to_target(dvec3(0, 0, 1), end - start);
1011 tesselate_arrow((end-start).length(), aspect, rel_tip_radius, tip_aspect, res, edges);
1013}
1014
1016{
1017 set_color(i*l.get_emission());
1019 switch (l.get_type()) {
1020 case LT_DIRECTIONAL :
1021 mul_modelview_matrix(cgv::math::scale4<double>(light_scale, light_scale, light_scale));
1022 tesselate_arrow(vec3(0.0f), l.get_position(), 0.1f,2.0f,0.5f);
1023 break;
1024 case LT_POINT :
1026 cgv::math::translate4<double>(l.get_position())*
1027 cgv::math::scale4<double>(vec3(0.3f*light_scale)));
1029 break;
1030 case LT_SPOT :
1032 cgv::math::translate4<double>(l.get_position())*
1033 cgv::math::scale4<double>(vec3(light_scale))
1034 );
1035 rotate_vector_to_target(dvec3(0, 0, -1), l.get_spot_direction());
1036 {
1037 float t = tan(l.get_spot_cutoff()*(float)M_PI/180);
1038 if (l.get_spot_cutoff() > 45.0f)
1039 mul_modelview_matrix(cgv::math::scale4<double>(1, 1, 0.5f / t));
1040 else
1041 mul_modelview_matrix(cgv::math::scale4<double>(t, t, 0.5f));
1042 mul_modelview_matrix(cgv::math::translate4<double>(0, 0, -1));
1044 set_cull_state(CM_OFF);
1047 }
1048 }
1050}
1051
1053{
1054 if (frame_buffer_stack.empty()) {
1055 error("gl_context::announce_external_frame_buffer_change() called with empty frame buffer stack");
1056 return;
1057 }
1058 GLint fbo_id = 0;
1060 fbo_handle = frame_buffer_stack.top()->handle;
1061 frame_buffer_stack.top()->handle = get_handle(fbo_id);
1062}
1063
1065{
1066 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(fbo_handle));
1067 if (frame_buffer_stack.empty())
1068 return;
1069 frame_buffer_stack.top()->handle = fbo_handle;
1070}
1071
1073{
1074 if (window_transformation_stack.empty()) {
1075 error("gl_context::announce_external_viewport_change() called with empty window transformation stack");
1076 return;
1077 }
1078 GLint vp[4];
1080 cgv_viewport_storage = window_transformation_stack.top().front().viewport;
1081 window_transformation_stack.top().front().viewport = ivec4(vp[0], vp[1], vp[2], vp[3]);
1082}
1083
1091
1094{
1097
1098 GLint vp[4];
1100
1102 // push projection matrix
1104 // set orthogonal projection
1106 glOrtho(vp[0], vp[0]+vp[2], vp[1], vp[1]+vp[3], -1, 1);
1107 // push modelview matrix
1109 // use identity for modelview
1111 }
1112 set_modelview_matrix(cgv::math::identity4<double>());
1113 set_projection_matrix(cgv::math::ortho4<double>(vp[0], vp[0] + vp[2], vp[1], vp[1]+vp[3], -1, 1));
1114}
1115
1122
1125 unsigned int x, unsigned int y, FrameBufferType buffer_type,
1126 TypeId type, data::ComponentFormat cf, int w, int h)
1127{
1128 const cgv::data::data_format* df = dv.get_format();
1129 if (df) {
1130 w = int(df->get_width());
1131 h = int(df->get_height());
1132 type = df->get_component_type();
1134 if (w < 1 || h < 1) {
1135 error(std::string("read_frame_buffer: received invalid dimensions (") + cgv::utils::to_string(w) + "," + cgv::utils::to_string(h) + ")");
1136 return false;
1137 }
1138 }
1139 else {
1140 if (w < 1 || h < 1) {
1141 GLint vp[4];
1143 w = w < 1 ? vp[2] : w;
1144 h = h < 1 ? vp[3] : h;
1145 }
1146 }
1147 GLuint gl_type = map_to_gl(type);
1148 if (gl_type == 0) {
1149 error(std::string("read_frame_buffer: could not make component type ")+cgv::type::info::get_type_name(df->get_component_type())+" to gl type");
1150 return false;
1151 }
1153 if (cf != cgv::data::CF_D) {
1155 if (cf != cgv::data::CF_S) {
1156 gl_format = map_to_gl(cf);
1157 if (gl_format == GL_RGB && cf != cgv::data::CF_RGB) {
1158 error(std::string("read_frame_buffer: could not match component format ") + cgv::utils::to_string(df->get_component_format()));
1159 return false;
1160 }
1161 }
1162 }
1164 if (buffer_type < FB_BACK)
1166 else {
1167 switch (buffer_type) {
1168 case FB_FRONT : gl_buffer = GL_FRONT; break;
1169 case FB_BACK : gl_buffer = GL_BACK; break;
1170 case FB_FRONT_LEFT : gl_buffer = GL_FRONT_LEFT; break;
1171 case FB_FRONT_RIGHT : gl_buffer = GL_FRONT_RIGHT; break;
1172 case FB_BACK_LEFT : gl_buffer = GL_BACK_LEFT; break;
1173 case FB_BACK_RIGHT : gl_buffer = GL_BACK_RIGHT; break;
1174 default:
1175 error(std::string("invalid buffer type ")+cgv::utils::to_string(buffer_type));
1176 return false;
1177 }
1178 }
1179 // after all necessary information could be extracted, ensure that format
1180 // and data view are created
1181 if (!df) {
1182 df = new cgv::data::data_format(w,h,type,cf);
1183 dv.~data_view();
1184 new(&dv) data::data_view(df);
1185 dv.manage_format(true);
1186 }
1192 glReadPixels(x,y,w,h,gl_format,gl_type,dv.get_ptr<void>());
1196 return true;
1197}
1198
1199
1200void render_vertex(int k, const float* vertices, const float* normals, const float* tex_coords,
1201 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices, bool flip_normals)
1202{
1203 if (normals && normal_indices) {
1204 if (flip_normals) {
1205 float n[3] = { -normals[3*normal_indices[k]],-normals[3*normal_indices[k]+1],-normals[3*normal_indices[k]+2] };
1206 glNormal3fv(n);
1207 }
1208 else
1209 glNormal3fv(normals+3*normal_indices[k]);
1210 }
1211 if (tex_coords && tex_coord_indices)
1212 glTexCoord2fv(tex_coords+2*tex_coord_indices[k]);
1213 glVertex3fv(vertices+3*vertex_indices[k]);
1214}
1215
1216attribute_array_binding*& get_aab_ptr()
1217{
1218 static attribute_array_binding* aab_ptr = 0;
1219 return aab_ptr;
1220}
1221
1222vertex_buffer*& get_vbo_ptr()
1223{
1224 static vertex_buffer* vbo_ptr = 0;
1225 return vbo_ptr;
1226}
1227
1228bool gl_context::release_attributes(const float* normals, const float* tex_coords, const int* normal_indices, const int* tex_coord_indices) const
1229{
1230 shader_program* prog_ptr = static_cast<shader_program*>(get_current_program());
1231 if (!prog_ptr || prog_ptr->get_position_index() == -1)
1232 return false;
1233
1234 attribute_array_binding*& aab_ptr = get_aab_ptr();
1235 if (!aab_ptr) {
1236 attribute_array_binding::disable_global_array(*this, prog_ptr->get_position_index());
1237 if (prog_ptr->get_normal_index() != -1 && normals && normal_indices)
1238 attribute_array_binding::disable_global_array(*this, prog_ptr->get_normal_index());
1239 if (prog_ptr->get_texcoord_index() != -1 && tex_coords && tex_coord_indices)
1240 attribute_array_binding::disable_global_array(*this, prog_ptr->get_texcoord_index());
1241 }
1242 else {
1243 aab_ptr->disable(const_cast<gl_context&>(*this));
1244 aab_ptr->disable_array(*this, prog_ptr->get_position_index());
1245 if (prog_ptr->get_normal_index() != -1 && normals && normal_indices)
1246 aab_ptr->disable_global_array(*this, prog_ptr->get_normal_index());
1247 if (prog_ptr->get_texcoord_index() != -1 && tex_coords && tex_coord_indices)
1248 aab_ptr->disable_global_array(*this, prog_ptr->get_texcoord_index());
1249 vertex_buffer*& vbo_ptr = get_vbo_ptr();
1250 vbo_ptr->destruct(*this);
1251 delete vbo_ptr;
1252 vbo_ptr = 0;
1253 }
1254 return true;
1255}
1256
1257bool gl_context::prepare_attributes(std::vector<vec3>& P, std::vector<vec3>& N, std::vector<vec2>& T, unsigned nr_vertices,
1258 const float* vertices, const float* normals, const float* tex_coords,
1259 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices, bool flip_normals) const
1260{
1261 unsigned i;
1262 shader_program* prog_ptr = static_cast<shader_program*>(get_current_program());
1263 if (!prog_ptr || prog_ptr->get_position_index() == -1)
1264 return false;
1265 P.resize(nr_vertices);
1266 for (i = 0; i < nr_vertices; ++i)
1267 P[i] = *reinterpret_cast<const vec3*>(vertices + 3 * vertex_indices[i]);
1268
1269 if (prog_ptr->get_normal_index() != -1 && normals && normal_indices) {
1270 N.resize(nr_vertices);
1271 for (i = 0; i < nr_vertices; ++i) {
1272 N[i] = *reinterpret_cast<const vec3*>(normals + 3 * normal_indices[i]);
1273 if (flip_normals)
1274 N[i] = -N[i];
1275 }
1276 }
1277 if (prog_ptr->get_texcoord_index() != -1 && tex_coords && tex_coord_indices) {
1278 T.resize(nr_vertices);
1279 for (i = 0; i < nr_vertices; ++i)
1280 T[i] = *reinterpret_cast<const vec2*>(tex_coords + 2 * tex_coord_indices[i]);
1281 }
1282
1283 attribute_array_binding*& aab_ptr = get_aab_ptr();
1284 if (core_profile && !aab_ptr) {
1285 aab_ptr = new attribute_array_binding();
1286 aab_ptr->create(*this);
1287 }
1288 if (!aab_ptr) {
1289 attribute_array_binding::set_global_attribute_array<>(*this, prog_ptr->get_position_index(), P);
1290 attribute_array_binding::enable_global_array(*this, prog_ptr->get_position_index());
1291 if (prog_ptr->get_normal_index() != -1) {
1292 if (normals && normal_indices) {
1293 attribute_array_binding::set_global_attribute_array<>(*this, prog_ptr->get_normal_index(), N);
1294 attribute_array_binding::enable_global_array(*this, prog_ptr->get_normal_index());
1295 }
1296 else
1297 attribute_array_binding::disable_global_array(*this, prog_ptr->get_normal_index());
1298 }
1299 if (prog_ptr->get_texcoord_index() != -1) {
1300 if (tex_coords && tex_coord_indices) {
1301 attribute_array_binding::set_global_attribute_array<>(*this, prog_ptr->get_texcoord_index(), T);
1302 attribute_array_binding::enable_global_array(*this, prog_ptr->get_texcoord_index());
1303 }
1304 else
1305 attribute_array_binding::disable_global_array(*this, prog_ptr->get_texcoord_index());
1306 }
1307 }
1308 else {
1309 vertex_buffer*& vbo_ptr = get_vbo_ptr();
1310 if (!vbo_ptr)
1311 vbo_ptr = new vertex_buffer();
1312 else
1313 vbo_ptr->destruct(*this);
1314 vbo_ptr->create(*this, P.size() * sizeof(vec3) + N.size() * sizeof(vec3) + T.size() * sizeof(vec2));
1315 vbo_ptr->replace(const_cast<gl_context&>(*this), 0, P.data(), P.size());
1316 size_t nml_off = P.size() * sizeof(vec3);
1317 size_t tex_off = nml_off;
1318 if (!N.empty()) {
1319 vbo_ptr->replace(const_cast<gl_context&>(*this), nml_off, N.data(), N.size());
1320 tex_off += N.size() * sizeof(vec3);
1321 }
1322 if (!T.empty())
1323 vbo_ptr->replace(const_cast<gl_context&>(*this), tex_off, T.data(), T.size());
1324
1326 aab_ptr->set_attribute_array(*this, prog_ptr->get_position_index(), td3, *vbo_ptr, 0, P.size());
1327 aab_ptr->enable_array(*this, prog_ptr->get_position_index());
1328 if (prog_ptr->get_normal_index() != -1) {
1329 if (normals && normal_indices) {
1330 aab_ptr->set_attribute_array(*this, prog_ptr->get_normal_index(), td3, *vbo_ptr, nml_off, N.size());
1331 aab_ptr->enable_array(*this, prog_ptr->get_normal_index());
1332 }
1333 else
1334 aab_ptr->disable_array(*this, prog_ptr->get_normal_index());
1335 }
1336 if (prog_ptr->get_texcoord_index() != -1) {
1337 if (tex_coords && tex_coord_indices) {
1339 aab_ptr->set_attribute_array(*this, prog_ptr->get_texcoord_index(), td2, *vbo_ptr, tex_off, T.size());
1340 aab_ptr->enable_array(*this, prog_ptr->get_texcoord_index());
1341 }
1342 else
1343 aab_ptr->disable_array(*this, prog_ptr->get_texcoord_index());
1344 }
1345 aab_ptr->enable(const_cast<gl_context&>(*this));
1346 }
1347 return true;
1348}
1349
1352 const float* vertices, const float* normals, const float* tex_coords,
1353 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices,
1354 int nr_faces, int face_degree, bool flip_normals) const
1355{
1357 int k = 0;
1358 for (int i = 0; i < nr_faces; ++i) {
1360 for (int j = 0; j < face_degree; ++j, ++k)
1361 render_vertex(k, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1362 glEnd();
1363 }
1364 return;
1365 }
1366 unsigned nr_vertices = face_degree * nr_faces;
1367 std::vector<vec3> P, N;
1368 std::vector<vec2> T;
1369 if (!prepare_attributes(P, N, T, nr_vertices, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals))
1370 return;
1371 for (int i = 0; i < nr_faces; ++i)
1372 glDrawArrays(GL_LINE_LOOP, i*face_degree, face_degree);
1373 release_attributes(normals, tex_coords, normal_indices, tex_coord_indices);
1374}
1375
1376
1377void gl_context::draw_elements_void(GLenum mode, size_t total_count, GLenum type, size_t type_size, const void* indices) const
1378{
1379 ensure_configured();
1380 size_t drawn = 0;
1381 const cgv::type::uint8_type* index_ptr = static_cast<const cgv::type::uint8_type*>(indices);
1382 while (drawn < total_count) {
1383 size_t count = total_count - drawn;
1384 if (count > max_nr_indices)
1385 count = size_t(max_nr_indices);
1386 glDrawElements(mode, GLsizei(count), type, index_ptr + drawn * type_size);
1387 drawn += count;
1388 }
1389}
1390
1391size_t max_nr_indices, max_nr_vertices;
1392void gl_context::ensure_configured() const
1393{
1394 if (max_nr_indices != 0)
1395 return;
1396 glGetInteger64v(GL_MAX_ELEMENTS_INDICES, reinterpret_cast<GLint64*>(&max_nr_indices));
1397 glGetInteger64v(GL_MAX_ELEMENTS_VERTICES, reinterpret_cast<GLint64*>(&max_nr_vertices));
1398}
1399
1402 const float* vertices, const float* normals, const float* tex_coords,
1403 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices,
1404 int nr_faces, int face_degree, bool is_fan, bool flip_normals) const
1405{
1406 int s = face_degree - 2;
1407 int i, k = 2;
1408 std::vector<GLuint> I;
1409 I.push_back(0); I.push_back(1);
1410 for (i = 0; i < nr_faces; ++i) {
1411 if (is_fan) {
1412 I.push_back(k - 1); I.push_back(k);
1413 I.push_back(0); I.push_back(k);
1414 continue;
1415 }
1416 if (s == 1) {
1417 I.push_back(k - 1); I.push_back(k);
1418 I.push_back(k - 2); I.push_back(k);
1419 }
1420 else {
1421 I.push_back(k - 1); I.push_back(k + 1);
1422 I.push_back(k - 2); I.push_back(k);
1423 I.push_back(k); I.push_back(k + 1);
1424 }
1425 k += 2;
1426 }
1427
1430 for (GLuint j:I)
1431 render_vertex(j, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1432 glEnd();
1433 return;
1434 }
1435 unsigned nr_vertices = 2 + (face_degree - 2) * nr_faces;
1436 std::vector<vec3> P, N;
1437 std::vector<vec2> T;
1438 if (!prepare_attributes(P, N, T, nr_vertices, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals))
1439 return;
1440 draw_elements(GL_LINES, I.size(), &I[0]);
1441 release_attributes(normals, tex_coords, normal_indices, tex_coord_indices);
1442}
1443
1445 const float* vertices, const float* normals, const float* tex_coords,
1446 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices,
1447 int nr_faces, int face_degree, bool flip_normals) const
1448{
1450 int k = 0;
1451 if (face_degree < 5)
1452 glBegin(face_degree == 3 ? GL_TRIANGLES : GL_QUADS);
1453 for (int i = 0; i < nr_faces; ++i) {
1454 if (face_degree >= 5)
1456 for (int j = 0; j < face_degree; ++j, ++k)
1457 render_vertex(k, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1458 if (face_degree >= 5)
1459 glEnd();
1460 }
1461 if (face_degree < 5)
1462 glEnd();
1463 return;
1464 }
1465 unsigned nr_vertices = face_degree * nr_faces;
1466 std::vector<vec3> P, N;
1467 std::vector<vec2> T;
1468 if (!prepare_attributes(P, N, T, nr_vertices, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals))
1469 return;
1470 /*
1471 for (unsigned x = 0; x < nr_vertices; ++x) {
1472 std::cout << x << ": [" << P[x] << "]";
1473 if (N.size() > 0)
1474 std::cout << ", <" << N[x] << ">";
1475 if (T.size() > 0)
1476 std::cout << ", {" << T[x] << "}";
1477 std::cout << std::endl;
1478 }
1479 */
1480 if (face_degree == 3)
1481 glDrawArrays(GL_TRIANGLES, 0, nr_vertices);
1482 else {
1483 for (int i = 0; i < nr_faces; ++i) {
1484 glDrawArrays(GL_TRIANGLE_FAN, i*face_degree, face_degree);
1485 }
1486 }
1487 release_attributes(normals, tex_coords, normal_indices, tex_coord_indices);
1488}
1489
1491 const float* vertices, const float* normals, const float* tex_coords,
1492 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices,
1493 int nr_faces, int face_degree, bool is_fan, bool flip_normals) const
1494{
1495 int s = face_degree - 2;
1496 int k = 2;
1498 glBegin(face_degree == 3 ? (is_fan ? GL_TRIANGLE_FAN : GL_TRIANGLE_STRIP) : GL_QUAD_STRIP);
1499 render_vertex(0, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1500 render_vertex(1, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1501 for (int i = 0; i < nr_faces; ++i)
1502 for (int j = 0; j < s; ++j, ++k)
1503 render_vertex(k, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1504 glEnd();
1505 return;
1506 }
1507 unsigned nr_vertices = 2 + (face_degree-2) * nr_faces;
1508 std::vector<vec3> P, N;
1509 std::vector<vec2> T;
1510 if (!prepare_attributes(P, N, T, nr_vertices, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals))
1511 return;
1513 release_attributes(normals, tex_coords, normal_indices, tex_coord_indices);
1514}
1515
1517 if(state.enabled)
1519 else
1521 glDepthFunc(map_to_gl(state.test_func));
1523}
1524
1526 glDepthFunc(map_to_gl(func));
1528}
1529
1534
1539
1541 switch(culling_mode) {
1542 case CM_OFF:
1544 break;
1545 case CM_BACKFACE:
1548 break;
1549 case CM_FRONTFACE:
1552 break;
1553 default:
1554 break;
1555 }
1556 context::set_cull_state(culling_mode);
1557}
1558
1560 if(state.enabled)
1562 else
1566 map_to_gl(state.src_color),
1567 map_to_gl(state.dst_color),
1568 map_to_gl(state.src_alpha),
1569 map_to_gl(state.dst_alpha)
1570 );
1571 } else {
1572 glBlendFunc(map_to_gl(state.src_color), map_to_gl(state.dst_color));
1573 }
1575}
1576
1581
1591
1596
1601
1603 glDepthMask(map_to_gl(mask.depth_flag));
1605 map_to_gl(mask.red_flag),
1606 map_to_gl(mask.green_flag),
1607 map_to_gl(mask.blue_flag),
1608 map_to_gl(mask.alpha_flag)
1609 );
1611}
1612
1614 glDepthMask(map_to_gl(flag));
1616}
1617
1620 map_to_gl(flags[0]),
1621 map_to_gl(flags[1]),
1622 map_to_gl(flags[2]),
1623 map_to_gl(flags[3])
1624 );
1626}
1627
1630{
1632 GLdouble V[16];
1634 return dmat4(4,4,V);
1635 }
1636 if (modelview_matrix_stack.empty())
1637 return identity4<double>();
1638 return modelview_matrix_stack.top();
1639}
1640
1643{
1645 GLdouble P[16];
1647 return dmat4(4,4,P);
1648 }
1649 if (projection_matrix_stack.empty())
1650 return identity4<double>();
1651 return projection_matrix_stack.top();
1652}
1655{
1657 update_window_transformation_array();
1658}
1659
1660void gl_context::update_window_transformation_array()
1661{
1662 const std::vector<window_transformation>& wta = window_transformation_stack.top();
1663 if (wta.size() == 1) {
1664 const ivec4& viewport = wta.front().viewport;
1665 const dvec2& depth_range = wta.front().depth_range;
1666 glViewport(viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1667 glScissor(viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1668 glDepthRange(depth_range[0], depth_range[1]);
1669 }
1670 else {
1671 for (GLuint array_index = 0; array_index < (GLuint)wta.size(); ++array_index) {
1672 const ivec4& viewport = wta[array_index].viewport;
1673 const dvec2& depth_range = wta[array_index].depth_range;
1674 glViewportIndexedf(array_index, (GLfloat)viewport[0], (GLfloat)viewport[1], (GLfloat)viewport[2], (GLfloat)viewport[3]);
1675 glScissorIndexed(array_index, viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1676 glDepthRangeIndexed(array_index, (GLclampd)depth_range[0], (GLclampd)depth_range[1]);
1677 }
1678 }
1679}
1680
1682{
1683 GLint max_value = 1;
1684 if (GLEW_VERSION_4_1)
1685 glGetIntegerv(GL_MAX_VIEWPORTS, &max_value);
1686 return max_value;
1687}
1688
1691{
1692 size_t nr = window_transformation_stack.top().size();
1694 if (nr != window_transformation_stack.top().size())
1695 update_window_transformation_array();
1696 else {
1697 if (array_index < 1) {
1698 glViewport(viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1699 glScissor(viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1700 }
1701 else {
1702 glViewportIndexedf(array_index, (GLfloat)viewport[0], (GLfloat)viewport[1], (GLfloat)viewport[2], (GLfloat)viewport[3]);
1703 glScissorIndexed(array_index, viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1704 }
1705 }
1706}
1707
1709void gl_context::set_depth_range(const dvec2& depth_range, int array_index)
1710{
1711 size_t nr = window_transformation_stack.top().size();
1713 if (nr != window_transformation_stack.top().size())
1714 update_window_transformation_array();
1715 else {
1716 if (array_index < 1)
1717 glDepthRange(depth_range[0], depth_range[1]);
1718 else
1719 glDepthRangeIndexed(array_index, (GLclampd)depth_range[0], (GLclampd)depth_range[1]);
1720 }
1721}
1722/*
1724gl_context::dmat4 gl_context::get_device_matrix() const
1725{
1726 GLint vp[4];
1727 glGetIntegerv(GL_VIEWPORT, vp);
1728 dmat4 D; D.zeros();
1729 D(0, 0) = 0.5*vp[2];
1730 D(0, 3) = 0.5*vp[2] + vp[0];
1731 D(1, 1) = -0.5*vp[3]; // flip y-coordinate
1732 D(1, 3) = get_height() - 0.5*vp[3] - vp[1];
1733 D(2, 2) = 0.5;
1734 D(2, 3) = 0.5;
1735 D(3, 3) = 1.0;
1736 return D;
1737}
1738*/
1750
1762
1765{
1767
1768 if (!in_render_process() && !is_current())
1769 make_current();
1770
1772 /*
1773 GLenum err = glGetError();
1774 if (err != GL_NO_ERROR) {
1775 std::cout << "gl error:";
1776 switch (err) {
1777 case GL_INVALID_ENUM : std::cout << "invalid enum"; break;
1778 case GL_INVALID_VALUE : std::cout << "invalid value"; break;
1779 case GL_INVALID_OPERATION : std::cout << "invalid operation"; break;
1780 case GL_STACK_OVERFLOW : std::cout << "stack overflow"; break;
1781 case GL_STACK_UNDERFLOW : std::cout << "stack underflow"; break;
1782 case GL_OUT_OF_MEMORY : std::cout << "out of memory"; break;
1783 default: std::cout << "unknown error"; break;
1784 }
1785 std::cout << std::endl;
1786
1787 }
1788 */
1789 return z_window;
1790}
1791
1792#include <iomanip>
1793cgv::data::component_format gl_context::texture_find_best_format(
1795 render_component& rc, const std::vector<cgv::data::data_view>* palettes) const
1796{
1797 GLuint& gl_format = (GLuint&)rc.internal_format;
1799 if (debug_texture_format_matching)
1800 std::cout << "Texture Format Search for '" << cf << "':" << std::endl;
1801 gl_format = find_best_texture_format(cf, &best_cf, palettes, debug_texture_format_matching);
1802 if (debug_texture_format_matching)
1803 std::cout << "found: '" << best_cf << "' = " << std::hex << gl_format << std::endl;
1804 return best_cf;
1805}
1806
1807std::string gl_error_to_string(GLenum eid) {
1808 switch (eid) {
1809 case GL_NO_ERROR: return "";
1810 case GL_INVALID_ENUM: return "invalid enum";
1811 case GL_INVALID_VALUE: return "invalid value";
1812 case GL_INVALID_OPERATION: return "invalid operation";
1813 case GL_INVALID_FRAMEBUFFER_OPERATION: return "invalid framebuffe";
1814 case GL_OUT_OF_MEMORY: return "out of memory";
1815 case GL_STACK_UNDERFLOW: return "stack underflow";
1816 case GL_STACK_OVERFLOW: return "stack overflow";
1817 default:
1818 return "undefined error (id: " + std::to_string(eid) + ")";
1819 }
1820 //return std::string((const char*)gluErrorString(eid));
1821}
1822
1823std::string gl_error() {
1824 GLenum eid = glGetError();
1825 return gl_error_to_string(eid);
1826}
1827
1828bool gl_context::check_gl_error(const std::string& where, const cgv::render::render_component* rc) const
1829{
1830 GLenum eid = glGetError();
1831 if (eid == GL_NO_ERROR)
1832 return false;
1833 std::string error_string = where + ": " + gl_error_to_string(eid);
1835 return true;
1836}
1837
1838bool gl_context::check_texture_support(TextureType tt, const std::string& where, const cgv::render::render_component* rc) const
1839{
1840 switch (tt) {
1841 case TT_3D:
1842 if (!GLEW_VERSION_1_2) {
1843 error(where + ": 3D texture not supported", rc);
1844 return false;
1845 }
1846 break;
1847 case TT_CUBEMAP:
1848 if (!GLEW_VERSION_1_3) {
1849 error(where + ": cubemap texture not supported", rc);
1850 return false;
1851 }
1852 default:
1853 break;
1854 }
1855 return true;
1856}
1857
1858bool gl_context::check_shader_support(ShaderType st, const std::string& where, const cgv::render::render_component* rc) const
1859{
1860 switch (st) {
1861 case ST_COMPUTE:
1862 if (GLEW_VERSION_4_3)
1863 return true;
1864 else {
1865 error(where+": compute shader need not supported OpenGL version 4.3", rc);
1866 return false;
1867 }
1868 case ST_TESS_CONTROL:
1869 case ST_TESS_EVALUATION:
1870 if (GLEW_VERSION_4_0)
1871 return true;
1872 else {
1873 error(where+": tessellation shader need not supported OpenGL version 4.0", rc);
1874 return false;
1875 }
1876 case ST_GEOMETRY:
1877 if (GLEW_VERSION_3_2)
1878 return true;
1879 else {
1880 error(where + ": geometry shader need not supported OpenGL version 3.2", rc);
1881 return false;
1882 }
1883 default:
1884 if (GLEW_VERSION_2_0)
1885 return true;
1886 else {
1887 error(where + ": shaders need not supported OpenGL version 2.0", rc);
1888 return false;
1889 }
1890 }
1891}
1892
1893bool gl_context::check_fbo_support(const std::string& where, const cgv::render::render_component* rc) const
1894{
1895 if (!GLEW_VERSION_3_0) {
1896 error(where + ": framebuffer objects not supported", rc);
1897 return false;
1898 }
1899 return true;
1900}
1901
1902GLuint gl_context::texture_generate(texture_base& tb) const
1903{
1904 if (!check_texture_support(tb.tt, "gl_context::texture_generate", &tb))
1905 return get_gl_id(0);
1906 GLuint tex_id = get_gl_id(0);
1907 glGenTextures(1, &tex_id);
1909 error("gl_context::texture_generate: attempt to create texture inside glBegin-glEnd-block", &tb);
1910 return tex_id;
1911}
1912
1913GLuint gl_context::texture_bind(TextureType tt, GLuint tex_id) const
1914{
1915 GLint tmp_id;
1916 glGetIntegerv(get_tex_bind(tt), &tmp_id);
1917 glBindTexture(get_tex_dim(tt), tex_id);
1918 return tmp_id;
1919}
1920
1921void gl_context::texture_unbind(TextureType tt, GLuint tmp_id) const
1922{
1923 glBindTexture(get_tex_dim(tt), tmp_id);
1924}
1925
1926bool gl_context::texture_create(texture_base& tb, cgv::data::data_format& df) const
1927{
1928 GLuint gl_format = (const GLuint&) tb.internal_format;
1929
1930 if (tb.tt == TT_UNDEF)
1931 tb.tt = (TextureType)df.get_nr_dimensions();
1932 GLuint tex_id = texture_generate(tb);
1933 if (tex_id == get_gl_id(0))
1934 return false;
1935 GLuint tmp_id = texture_bind(tb.tt, tex_id);
1936
1937 // extract component type
1938 unsigned int transfer_format = map_to_gl(df.get_standard_component_format(), df.get_integer_interpretation());
1939 if (transfer_format == -1) {
1940 error("could not determine transfer format", &tb);
1941 return false;
1942 }
1943 switch (tb.tt) {
1944 case TT_1D :
1946 gl_format, GLsizei(df.get_width()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1947 break;
1948 case TT_1D_ARRAY :
1950 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1951 break;
1952 case TT_2D :
1953 glTexImage2D(GL_TEXTURE_2D, 0, gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1954 break;
1955 case TT_MULTISAMPLE_2D:
1956 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, tb.nr_multi_samples, gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), map_to_gl(tb.fixed_sample_locations));
1957 break;
1958 case TT_2D_ARRAY :
1959 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), GLsizei(df.get_depth()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1960 break;
1961 case TT_MULTISAMPLE_2D_ARRAY:
1962 glTexStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, tb.nr_multi_samples, gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), GLsizei(df.get_depth()), map_to_gl(tb.fixed_sample_locations));
1963 break;
1964 case TT_3D :
1966 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), GLsizei(df.get_depth()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1967 break;
1968 case TT_CUBEMAP :
1970 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1972 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1974 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1976 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1978 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1980 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1981 default:
1982 break;
1983 }
1984 if (check_gl_error("gl_context::texture_create", &tb)) {
1985 glDeleteTextures(1, &tex_id);
1986 texture_unbind(tb.tt, tmp_id);
1987 return false;
1988 }
1989
1990 texture_unbind(tb.tt, tmp_id);
1991 tb.have_mipmaps = false;
1992 tb.handle = get_handle(tex_id);
1993 return true;
1994}
1995
1996bool gl_context::texture_create(
1997 texture_base& tb,
1999 const cgv::data::const_data_view& data,
2000 int level, int cube_side, int num_array_layers, const std::vector<cgv::data::data_view>* palettes) const
2001{
2002 // query the format to be used for the texture
2003 GLuint gl_tex_format = (const GLuint&) tb.internal_format;
2004
2005 // define the texture type from the data format and the cube_side parameter
2006 tb.tt = (TextureType)data.get_format()->get_nr_dimensions();
2007 if(cube_side > -1) {
2008 if(tb.tt == TT_2D)
2009 tb.tt = TT_CUBEMAP;
2010 } else if(num_array_layers != 0) {
2011 if(num_array_layers < 0) {
2012 // automatic inference of layers from texture dimensions
2013 unsigned n_dims = data.get_format()->get_nr_dimensions();
2014 if(n_dims == 2)
2015 tb.tt = TT_1D_ARRAY;
2016 if(n_dims == 3)
2017 tb.tt = TT_2D_ARRAY;
2018 } else {
2019 switch(tb.tt) {
2020 case TT_1D: tb.tt = TT_1D_ARRAY; break;
2021 case TT_2D: tb.tt = TT_2D_ARRAY; break;
2022 case TT_3D: tb.tt = TT_2D_ARRAY; break;
2023 default:
2024 break;
2025 }
2026 }
2027 }
2028 // create texture is not yet done
2029 GLuint tex_id;
2030 if (tb.is_created())
2031 tex_id = get_gl_id(tb.handle);
2032 else {
2033 tex_id = texture_generate(tb);
2034 if (tex_id == get_gl_id(0))
2035 return false;
2036 tb.handle = get_handle(tex_id);
2037 }
2038
2039 // bind texture
2040 GLuint tmp_id = texture_bind(tb.tt, tex_id);
2041
2042 // load data to texture
2043 tb.have_mipmaps = load_texture(data, gl_tex_format, level, cube_side, num_array_layers, palettes);
2044 bool result = !check_gl_error("gl_context::texture_create", &tb);
2045 // restore old texture
2046 texture_unbind(tb.tt, tmp_id);
2047 return result;
2048}
2049
2050bool gl_context::texture_create_from_buffer(
2051 texture_base& tb,
2053 int x, int y, int level) const
2054{
2055 GLuint gl_format = (const GLuint&) tb.internal_format;
2056
2057 tb.tt = (TextureType)df.get_nr_dimensions();
2058 if (tb.tt != TT_2D) {
2059 tb.last_error = "texture creation from buffer only possible for 2d textures";
2060 return false;
2061 }
2062 GLuint tex_id;
2063 if (tb.is_created())
2064 tex_id = get_gl_id(tb.handle);
2065 else {
2066 tex_id = texture_generate(tb);
2067 if (tex_id == get_gl_id(0))
2068 return false;
2069 tb.handle = get_handle(tex_id);
2070 }
2071 GLuint tmp_id = texture_bind(tb.tt, tex_id);
2072
2073 // check mipmap type
2074 bool gen_mipmap = level == -1;
2075 if (gen_mipmap)
2076 level = 0;
2077
2078 glCopyTexImage2D(GL_TEXTURE_2D, level, gl_format, x, y, GLsizei(df.get_width()), GLsizei(df.get_height()), 0);
2079 bool result = false;
2080 std::string error_string("gl_context::texture_create_from_buffer: ");
2081 switch (glGetError()) {
2082 case GL_NO_ERROR :
2083 result = true;
2084 break;
2085 case GL_INVALID_ENUM :
2086 error_string += "target was not an accepted value.";
2087 break;
2088 case GL_INVALID_VALUE :
2089 error_string += "level was less than zero or greater than log sub 2(max), where max is the returned value of GL_MAX_TEXTURE_SIZE.\n"
2090 "or border was not zero or 1.\n"
2091 "or width was less than zero, greater than 2 + GL_MAX_TEXTURE_SIZE; or width cannot be represented as 2n + 2 * border for some integer n.";
2092 break;
2093 case GL_INVALID_OPERATION :
2094 error_string += "glCopyTexImage2D was called between a call to glBegin and the corresponding call to glEnd.";
2095 break;
2096 default:
2097 error_string += gl_error_to_string(glGetError());
2098 break;
2099 }
2100 texture_unbind(tb.tt, tmp_id);
2101 if (!result)
2103 else
2104 if (gen_mipmap)
2105 result = texture_generate_mipmaps(tb, tb.tt == TT_CUBEMAP ? 2 : (int)tb.tt);
2106
2107 return result;
2108}
2109
2110bool gl_context::texture_replace(
2111 texture_base& tb,
2112 int x, int y, int z,
2113 const cgv::data::const_data_view& data,
2114 int level, const std::vector<cgv::data::data_view>* palettes) const
2115{
2116 if (!tb.is_created()) {
2117 error("gl_context::texture_replace: attempt to replace in not created texture", &tb);
2118 return false;
2119 }
2120 // determine dimension from location arguments
2121 unsigned int dim = 1;
2122 if (y != -1) {
2123 ++dim;
2124 if (z != -1)
2125 ++dim;
2126 }
2127 // check consistency
2128 if (tb.tt == TT_CUBEMAP) {
2129 if (dim != 3) {
2130 error("gl_context::texture_replace: replace on cubemap without the side defined", &tb);
2131 return false;
2132 }
2133 if (z < 0 || z > 5) {
2134 error("gl_context::texture_replace: replace on cubemap with invalid side specification", &tb);
2135 return false;
2136 }
2137 }
2138 else {
2139 if (tb.tt != dim) {
2140 error("gl_context::texture_replace: replace on texture with invalid position specification", &tb);
2141 return false;
2142 }
2143 }
2144
2145 // bind texture
2146 GLuint tmp_id = texture_bind(tb.tt, get_gl_id(tb.handle));
2147 tb.have_mipmaps = replace_texture(data, level, x, y, z, palettes) || tb.have_mipmaps;
2148 bool result = !check_gl_error("gl_context::texture_replace", &tb);
2149 texture_unbind(tb.tt, tmp_id);
2150 return result;
2151}
2152
2153bool gl_context::texture_replace_from_buffer(
2154 texture_base& tb,
2155 int x, int y, int z,
2156 int x_buffer, int y_buffer,
2157 unsigned int width, unsigned int height,
2158 int level) const
2159{
2160 if (!tb.is_created()) {
2161 error("gl_context::texture_replace_from_buffer: attempt to replace in not created texture", &tb);
2162 return false;
2163 }
2164 // determine dimension from location arguments
2165 unsigned int dim = 2;
2166 if (z != -1)
2167 ++dim;
2168
2169 // consistency checks
2170 if (tb.tt == TT_CUBEMAP) {
2171 if (dim != 3) {
2172 error("gl_context::texture_replace_from_buffer: replace on cubemap without the side defined", &tb);
2173 return false;
2174 }
2175 if (z < 0 || z > 5) {
2176 error("gl_context::texture_replace_from_buffer: replace on cubemap without invalid side specification", &tb);
2177 return false;
2178 }
2179 }
2180 else {
2181 if (tb.tt != dim) {
2182 tb.last_error = "replace on texture with invalid position specification";
2183 return false;
2184 }
2185 }
2186 // check mipmap type
2187 bool gen_mipmap = level == -1;
2188 if (gen_mipmap)
2189 level = 0;
2190
2191 // bind texture
2192 GLuint tmp_id = texture_bind(tb.tt, get_gl_id(tb.handle));
2193 switch (tb.tt) {
2194 case TT_2D : glCopyTexSubImage2D(GL_TEXTURE_2D, level, x, y, x_buffer, y_buffer, width, height); break;
2195 case TT_3D : glCopyTexSubImage3D(GL_TEXTURE_3D, level, x, y, z, x_buffer, y_buffer, width, height); break;
2196 case TT_CUBEMAP : glCopyTexSubImage2D(get_gl_cube_map_target(z), level, x, y, x_buffer, y_buffer, width, height);
2197 default: break;
2198 }
2199 bool result = !check_gl_error("gl_context::texture_replace_from_buffer", &tb);
2200 texture_unbind(tb.tt, tmp_id);
2201
2202 if (result && gen_mipmap)
2203 result = texture_generate_mipmaps(tb, tb.tt == TT_CUBEMAP ? 2 : (int)tb.tt);
2204
2205 return result;
2206}
2207
2208bool gl_context::texture_copy_back(const texture_base& tb, int level, cgv::data::data_view& dv) const
2209{
2210 if(!tb.is_created()) {
2211 error("gl_context::texture_copy_back: attempt to copy from not created texture", &tb);
2212 return false;
2213 }
2214
2215 GLuint tmp_id = texture_bind(tb.tt, get_gl_id(tb.handle));
2216 read_texture(dv, level);
2217
2218 bool result = !check_gl_error("gl_context::texture_copy_back", &tb);
2219 texture_unbind(tb.tt, tmp_id);
2220
2221 return result;
2222}
2223
2224bool gl_context::texture_create_mipmaps(texture_base& tb, cgv::data::data_format& df) const
2225{
2226 GLuint gl_format = (const GLuint&)tb.internal_format;
2227
2228 // extract component type
2229 unsigned int transfer_format = map_to_gl(df.get_standard_component_format(), df.get_integer_interpretation());
2230
2231 if(transfer_format == -1) {
2232 error("could not determine transfer format", &tb);
2233 return false;
2234 }
2235
2236 // extract texture size and compute number of mip-levels
2237 uvec3 size(unsigned(df.get_width()), unsigned(df.get_height()), unsigned(df.get_depth()));
2238
2239 unsigned max_size = cgv::math::max_value(size);
2240 unsigned num_levels = 1 + static_cast<unsigned>(log2(static_cast<float>(max_size)));
2241
2242 // compute mip-level sizes
2243 std::vector<uvec3> level_sizes(num_levels);
2244 level_sizes[0] = size;
2245
2246 for(unsigned level = 1; level < num_levels; ++level) {
2247 uvec3 level_size = level_sizes[level - 1];
2248 level_size = level_size / 2u;
2249 level_size = cgv::math::max(level_size, uvec3(1u));
2250 level_sizes[level] = level_size;
2251 }
2252
2253 GLuint tmp_id = texture_bind(tb.tt, get_gl_id(tb.handle));
2254
2255 bool result = true;
2256
2257 switch(tb.tt) {
2258 case TT_1D:
2259 for(unsigned level = 1; level < num_levels; ++level) {
2260 uvec3 level_size = level_sizes[level];
2262 }
2263 break;
2264 case TT_1D_ARRAY:
2265 //glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2266 error("create mipmaps not implemented for 1D array textures", &tb);
2267 result = false;
2268 break;
2269 case TT_2D:
2270 for(unsigned level = 1; level < num_levels; ++level) {
2271 uvec3 level_size = level_sizes[level];
2273 }
2274 break;
2275 case TT_MULTISAMPLE_2D:
2276 //glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, tb.nr_multi_samples, gl_format, df.get_width(), df.get_height(), map_to_gl(tb.fixed_sample_locations));
2277 error("create mipmaps not implemented for 2D multisample textures", &tb);
2278 result = false;
2279 break;
2280 case TT_2D_ARRAY:
2281 //glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, gl_format, df.get_width(), df.get_height(), df.get_depth(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2282 error("create mipmaps not implemented for 2D array textures", &tb);
2283 result = false;
2284 break;
2285 case TT_MULTISAMPLE_2D_ARRAY:
2286 //glTexStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, tb.nr_multi_samples, gl_format, df.get_width(), df.get_height(), df.get_depth(), map_to_gl(tb.fixed_sample_locations));
2287 error("create mipmaps not implemented for 2D multisample array textures", &tb);
2288 result = false;
2289 break;
2290 case TT_3D:
2291 for(unsigned level = 1; level < num_levels; ++level) {
2292 uvec3 level_size = level_sizes[level];
2294 }
2295 break;
2296 case TT_CUBEMAP:
2297 /*glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0,
2298 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2299 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0,
2300 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2301 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0,
2302 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2303 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0,
2304 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2305 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0,
2306 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2307 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0,
2308 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2309 */
2310 error("create mipmaps not implemented for cubemap textures", &tb);
2311 result = false;
2312 default:
2313 break;
2314 }
2315
2316 if(check_gl_error("gl_context::texture_create_mipmaps", &tb))
2317 result = false;
2318
2319 if(result)
2320 tb.have_mipmaps = true;
2321
2322 texture_unbind(tb.tt, tmp_id);
2323 return result;
2324}
2325
2326bool gl_context::texture_generate_mipmaps(texture_base& tb, unsigned int dim) const
2327{
2328 GLuint tmp_id = texture_bind(tb.tt,get_gl_id(tb.handle));
2329
2330 bool is_array = tb.tt == TT_1D_ARRAY || tb.tt == TT_2D_ARRAY;
2331 bool is_cubemap = tb.tt == TT_CUBEMAP;
2332 std::string error_string;
2333 bool result = generate_mipmaps(dim, is_cubemap, is_array, &error_string);
2334 if (result)
2335 tb.have_mipmaps = true;
2336 else
2337 error(std::string("gl_context::texture_generate_mipmaps: ") + error_string);
2338
2339 texture_unbind(tb.tt, tmp_id);
2340 return result;
2341}
2342
2343bool gl_context::texture_destruct(texture_base& tb) const
2344{
2345 if (!tb.is_created()) {
2346 error("gl_context::texture_destruct: attempt to destruct not created texture", &tb);
2347 return false;
2348 }
2349 GLuint tex_id = get_gl_id(tb.handle);
2350 glDeleteTextures(1, &tex_id);
2351 bool result = !check_gl_error("gl_context::texture_destruct", &tb);
2352 tb.handle = 0;
2353 tb.ctx_ptr = 0;
2354 return result;
2355}
2356
2357bool gl_context::texture_set_state(const texture_base& tb) const
2358{
2359 if (tb.tt == TT_UNDEF) {
2360 error("gl_context::texture_set_state: attempt to set state on texture without type", &tb);
2361 return false;
2362 }
2363 GLuint tex_id = (GLuint&) tb.handle - 1;
2364 if (tex_id == -1) {
2365 error("gl_context::texture_set_state: attempt of setting texture state of not created texture", &tb);
2366 return false;
2367 }
2368 GLint tmp_id = texture_bind(tb.tt, tex_id);
2369
2370 if (tb.tt != TT_MULTISAMPLE_2D && tb.tt != TT_MULTISAMPLE_2D_ARRAY) {
2371 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_MIN_FILTER, map_to_gl(tb.min_filter));
2372 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_MAG_FILTER, map_to_gl(tb.mag_filter));
2373 if (tb.min_filter == TF_ANISOTROP)
2374 glTexParameterf(get_tex_dim(tb.tt), GL_TEXTURE_MAX_ANISOTROPY_EXT, tb.anisotropy);
2375 else
2376 glTexParameterf(get_tex_dim(tb.tt), GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
2377 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_COMPARE_FUNC, map_to_gl(tb.compare_function));
2378 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_COMPARE_MODE, (tb.use_compare_function ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE));
2379 if (!core_profile)
2380 glTexParameterf(get_tex_dim(tb.tt), GL_TEXTURE_PRIORITY, tb.priority);
2381 glTexParameterfv(get_tex_dim(tb.tt), GL_TEXTURE_BORDER_COLOR, tb.border_color);
2382 // if (tb.border_color[0] >= 0.0f)
2383 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_WRAP_S, map_to_gl(tb.wrap_s));
2384 if (tb.tt > TT_1D)
2385 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_WRAP_T, map_to_gl(tb.wrap_t));
2386 if (tb.tt == TT_3D)
2387 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_WRAP_R, map_to_gl(tb.wrap_r));
2388 }
2389
2390 bool result = !check_gl_error("gl_context::texture_set_state", &tb);
2391 texture_unbind(tb.tt, tmp_id);
2392 return result;
2393}
2394
2395bool gl_context::texture_enable(texture_base& tb, int tex_unit, unsigned int dim) const
2396{
2397 if (dim < 1 || dim > 3) {
2398 error("gl_context::texture_enable: invalid texture dimension", &tb);
2399 return false;
2400 }
2401 GLuint tex_id = (GLuint&) tb.handle - 1;
2402 if (tex_id == -1) {
2403 error("gl_context::texture_enable: texture not created", &tb);
2404 return false;
2405 }
2406 if (tex_unit >= 0) {
2407 if (!GLEW_VERSION_1_3) {
2408 error("gl_context::texture_enable: multi texturing not supported", &tb);
2409 return false;
2410 }
2411 glActiveTexture(GL_TEXTURE0+tex_unit);
2412 }
2413 GLint& old_binding = (GLint&) tb.user_data;
2414 glGetIntegerv(get_tex_bind(tb.tt), &old_binding);
2415 ++old_binding;
2416 glBindTexture(get_tex_dim(tb.tt), tex_id);
2417 // glEnable is not needed for texture arrays and will throw an invalid enum error
2418 //if(!(tb.tt == TT_1D_ARRAY || tb.tt == TT_2D_ARRAY))
2419 // glEnable(get_tex_dim(tb.tt));
2420 bool result = !check_gl_error("gl_context::texture_enable", &tb);
2421 if (tex_unit >= 0)
2423 return result;
2424}
2425
2426bool gl_context::texture_disable(
2427 texture_base& tb,
2428 int tex_unit, unsigned int dim) const
2429{
2430 if (dim < 1 || dim > 3) {
2431 error("gl_context::texture_disable: invalid texture dimension", &tb);
2432 return false;
2433 }
2434 if (tex_unit == -2) {
2435 error("gl_context::texture_disable: invalid texture unit", &tb);
2436 return false;
2437 }
2438 GLuint old_binding = (const GLuint&) tb.user_data;
2439 --old_binding;
2440 if (tex_unit >= 0)
2441 glActiveTexture(GL_TEXTURE0+tex_unit);
2442 // glDisable is not needed for texture arrays and will throw an invalid enum error
2443 //if(!(tb.tt == TT_1D_ARRAY || tb.tt == TT_2D_ARRAY))
2444 // glDisable(get_tex_dim(tb.tt));
2445 bool result = !check_gl_error("gl_context::texture_disable", &tb);
2446 glBindTexture(get_tex_dim(tb.tt), old_binding);
2447 if (tex_unit >= 0)
2449 return result;
2450}
2451
2452bool gl_context::texture_bind_as_image(texture_base& tb, int tex_unit, int level, bool bind_array, int layer, AccessType access) const
2453{
2454 GLuint tex_id = (GLuint&)tb.handle - 1;
2455 if(tex_id == -1) {
2456 error("gl_context::texture_enable: texture not created", &tb);
2457 return false;
2458 }
2459
2460 if(!GLEW_VERSION_4_2) {
2461 error("gl_context::texture_bind_as_image: image textures not supported", &tb);
2462 return false;
2463 }
2464
2465 GLuint gl_format = (const GLuint&)tb.internal_format;
2466 glBindImageTexture(tex_unit, tex_id, level, map_to_gl(bind_array), layer, map_to_gl(access), gl_format);
2467
2468 bool result = !check_gl_error("gl_context::texture_bind_as_image", &tb);
2469 return result;
2470}
2471
2472bool gl_context::render_buffer_create(render_buffer_base& rb, cgv::data::component_format& cf, int& _width, int& _height) const
2473{
2474 if (!GLEW_VERSION_3_0) {
2475 error("gl_context::render_buffer_create: frame buffer objects not supported", &rb);
2476 return false;
2477 }
2478 if (_width == -1)
2479 _width = get_width();
2480 if (_height == -1)
2481 _height = get_height();
2482
2483 GLuint rb_id;
2486
2487 GLuint& gl_format = (GLuint&)rb.internal_format;
2488 unsigned i = find_best_match(cf, color_buffer_formats);
2489 cgv::data::component_format best_cf(color_buffer_formats[i]);
2490 gl_format = gl_color_buffer_format_ids[i];
2491
2492 i = find_best_match(cf, depth_formats, &best_cf);
2493 if (i != -1) {
2494 best_cf = cgv::data::component_format(depth_formats[i]);
2495 gl_format = gl_depth_format_ids[i];
2496 }
2497
2498 cf = best_cf;
2499 if (rb.nr_multi_samples == 0)
2501 else
2503
2504 if (check_gl_error("gl_context::render_buffer_create", &rb))
2505 return false;
2506 rb.handle = get_handle(rb_id);
2507 return true;
2508}
2509
2510bool gl_context::render_buffer_destruct(render_buffer_base& rc) const
2511{
2512 if (!GLEW_VERSION_3_0) {
2513 error("gl_context::render_buffer_destruct: frame buffer objects not supported", &rc);
2514 return false;
2515 }
2516 GLuint rb_id = ((GLuint&) rc.handle)+1;
2518 if (check_gl_error("gl_context::render_buffer_destruct", &rc))
2519 return false;
2520 rc.handle = 0;
2521 rc.ctx_ptr = 0;
2522 return true;
2523}
2524
2525bool gl_context::frame_buffer_create(frame_buffer_base& fbb) const
2526{
2527 if (!check_fbo_support("gl_context::frame_buffer_create", &fbb))
2528 return false;
2529
2530 if (!context::frame_buffer_create(fbb))
2531 return false;
2532
2533 // allocate framebuffer object
2534 GLuint fbo_id = 0;
2535 glGenFramebuffers(1, &fbo_id);
2536 if (fbo_id == 0) {
2537 error("gl_context::frame_buffer_create: could not allocate framebuffer object", &fbb);
2538 return false;
2539 }
2540 fbb.handle = get_handle(fbo_id);
2541 return true;
2542}
2543
2544bool gl_context::frame_buffer_enable(frame_buffer_base& fbb)
2545{
2546 if (!context::frame_buffer_enable(fbb))
2547 return false;
2548 std::vector<int> buffers;
2549 bool depth_buffer = false;
2550 get_buffer_list(fbb, depth_buffer, buffers, GL_COLOR_ATTACHMENT0);
2551 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(fbb.handle));
2552
2553 if (buffers.size() == 1)
2554 glDrawBuffer(buffers[0]);
2555 else if (buffers.size() > 1) {
2556 glDrawBuffers(GLsizei(buffers.size()), reinterpret_cast<GLenum*>(&buffers[0]));
2557 }
2558 else if(depth_buffer) {
2560 //glReadBuffer(GL_NONE);
2561 } else {
2562 error("gl_context::frame_buffer_enable: no attached draw buffer selected!!", &fbb);
2563 return false;
2564 }
2565 return true;
2566}
2567
2570{
2571 if (!context::frame_buffer_disable(fbb))
2572 return false;
2573 if (frame_buffer_stack.empty()) {
2574 error("gl_context::frame_buffer_disable called with empty frame buffer stack!!", &fbb);
2575 return false;
2576 }
2577 else
2578 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(frame_buffer_stack.top()->handle));
2579 return true;
2580}
2581
2582bool gl_context::frame_buffer_destruct(frame_buffer_base& fbb) const
2583{
2584 if (!context::frame_buffer_destruct(fbb))
2585 return false;
2586 GLuint fbo_id = get_gl_id(fbb.handle);
2587 glDeleteFramebuffers(1, &fbo_id);
2588 fbb.handle = 0;
2589 fbb.ctx_ptr = 0;
2590 return true;
2591}
2592
2593void complete_rect_from_vp(ivec4& D, GLint vp[4])
2594{
2595 if (D(0) == -1)
2596 D(0) = vp[0];
2597 if (D(1) == -1)
2598 D(1) = vp[1];
2599 if (D(2) == -1)
2600 D(2) = vp[0] + vp[2];
2601 if (D(3) == -1)
2602 D(3) = vp[1] + vp[3];
2603}
2604
2605void gl_context::frame_buffer_blit(
2606 const frame_buffer_base* src_fbb_ptr, const ivec4& _S,
2607 frame_buffer_base* dst_fbb_ptr, const ivec4& _D, BufferTypeBits btbs, bool interpolate) const
2608{
2609 static const GLenum masks[8]{
2610 0,
2618 };
2619 ivec4 S = _S;
2620 ivec4 D = _D;
2621 if ((src_fbb_ptr == 0 && (S(0) == -1 || S(1) == -1 || S(2) == -1 || S(3) == -1)) ||
2622 (dst_fbb_ptr == 0 && (D(0) == -1 || D(1) == -1 || D(2) == -1 || D(3) == -1))) {
2623 GLint vp[4];
2625 if (src_fbb_ptr == 0)
2626 complete_rect_from_vp(S, vp);
2627 if (dst_fbb_ptr == 0)
2628 complete_rect_from_vp(D, vp);
2629 }
2631 if (src_fbb_ptr) {
2634 }
2635 if (dst_fbb_ptr) {
2638 }
2639 glBlitFramebuffer(S(0), S(1), S(2), S(3), D(0), D(1), D(2), D(3), masks[btbs], interpolate ? GL_LINEAR : GL_NEAREST);
2640 if (src_fbb_ptr)
2642 if (dst_fbb_ptr)
2644}
2645
2646bool gl_context::frame_buffer_attach(frame_buffer_base& fbb, const render_buffer_base& rb, bool is_depth, int i) const
2647{
2648 if (!context::frame_buffer_attach(fbb, rb, is_depth, i))
2649 return false;
2652 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(fbb.handle));
2656 get_gl_id(rb.handle));
2658 return true;
2659}
2660
2662bool gl_context::frame_buffer_attach(frame_buffer_base& fbb,
2663 const texture_base& t, bool is_depth,
2664 int level, int i, int z_or_cube_side) const
2665{
2666 if (!context::frame_buffer_attach(fbb, t, is_depth, level, i, z_or_cube_side))
2667 return false;
2670 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(fbb.handle));
2671
2672 if (z_or_cube_side == -1) {
2675 t.tt == TT_2D ? GL_TEXTURE_2D : GL_TEXTURE_2D_MULTISAMPLE, get_gl_id(t.handle), level);
2676 }
2677 else {
2678 if (t.tt == TT_CUBEMAP) {
2681 get_gl_cube_map_target(z_or_cube_side), get_gl_id(t.handle), level);
2682 }
2683 else {
2686 t.tt == TT_3D ? GL_TEXTURE_3D : GL_TEXTURE_2D_MULTISAMPLE_ARRAY , get_gl_id(t.handle), level, z_or_cube_side);
2687 }
2688 }
2689 bool result = !check_gl_error("gl_context::frame_buffer_attach", &fbb);
2691 return result;
2692}
2693
2696{
2697 if (fbb.handle == 0) {
2698 error("gl_context::frame_buffer_is_complete: attempt to check completeness on frame buffer that is not created", &fbb);
2699 return false;
2700 }
2703 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(fbb.handle));
2706 switch (error) {
2708 return true;
2710 fbb.last_error = "undefined framebuffer";
2711 return false;
2713 fbb.last_error = "incomplete attachment";
2714 return false;
2716 fbb.last_error = "incomplete or missing attachment";
2717 return false;
2719 fbb.last_error = "incomplete multisample";
2720 return false;
2722 fbb.last_error = "incomplete layer targets";
2723 return false;
2725 fbb.last_error = "incomplete draw buffer";
2726 return false;
2728 fbb.last_error = "incomplete read buffer";
2729 return false;
2731 fbb.last_error = "framebuffer objects unsupported";
2732 return false;
2733 }
2734 fbb.last_error = "unknown error";
2735 return false;
2736}
2737
2738int gl_context::frame_buffer_get_max_nr_color_attachments() const
2739{
2740 if (!check_fbo_support("gl_context::frame_buffer_get_max_nr_color_attachments"))
2741 return 0;
2742
2743 GLint nr;
2745 return nr;
2746}
2747
2748int gl_context::frame_buffer_get_max_nr_draw_buffers() const
2749{
2750 if (!check_fbo_support("gl_context::frame_buffer_get_max_nr_draw_buffers"))
2751 return 0;
2752
2753 GLint nr;
2755 return nr;
2756}
2757
2758GLuint gl_shader_type[] =
2759{
2761};
2762
2763void gl_context::shader_code_destruct(render_component& sc) const
2764{
2765 if (sc.handle == 0) {
2766 error("gl_context::shader_code_destruct: shader not created", &sc);
2767 return;
2768 }
2769 glDeleteShader(get_gl_id(sc.handle));
2770 sc.handle = 0;
2771 sc.ctx_ptr = 0;
2772 check_gl_error("gl_context::shader_code_destruct", &sc);
2773}
2774
2775bool gl_context::shader_code_create(render_component& sc, ShaderType st, const std::string& source) const
2776{
2777 if (!check_shader_support(st, "gl_context::shader_code_create", &sc))
2778 return false;
2779
2780 GLuint s_id = glCreateShader(gl_shader_type[st]);
2781 if (s_id == -1) {
2782 error(std::string("gl_context::shader_code_create: ")+gl_error(), &sc);
2783 return false;
2784 }
2785 sc.handle = get_handle(s_id);
2786
2787 const char* s = source.c_str();
2788 glShaderSource(s_id, 1, &s,NULL);
2789 if (check_gl_error("gl_context::shader_code_create", &sc))
2790 return false;
2791
2792 return true;
2793}
2794
2795bool gl_context::shader_code_compile(render_component& sc) const
2796{
2797 if (sc.handle == 0) {
2798 error("gl_context::shader_code_compile: shader not created", &sc);
2799 return false;
2800 }
2801 GLuint s_id = get_gl_id(sc.handle);
2803 int result;
2805 if (result == 1)
2806 return true;
2807 sc.last_error = std::string();
2808 GLint infologLength = 0;
2810 if (infologLength > 0) {
2812 sc.last_error = std::string(infologLength, 0);
2813 glGetShaderInfoLog(s_id, infologLength, &charsWritten, &sc.last_error.front());
2814 sc.last_error.resize(static_cast<size_t>(charsWritten + 1));
2815 }
2816 return false;
2817}
2818
2819bool gl_context::shader_program_create(shader_program_base& spb) const
2820{
2821 if (!check_shader_support(ST_VERTEX, "gl_context::shader_program_create", &spb))
2822 return false;
2823 spb.handle = get_handle(glCreateProgram());
2824 return true;
2825}
2826
2827void gl_context::shader_program_attach(shader_program_base& spb, const render_component& sc) const
2828{
2829 if (spb.handle == 0) {
2830 error("gl_context::shader_program_attach: shader program not created", &spb);
2831 return;
2832 }
2833 glAttachShader(get_gl_id(spb.handle), get_gl_id(sc.handle));
2834}
2835
2836void gl_context::shader_program_detach(shader_program_base& spb, const render_component& sc) const
2837{
2838 if (spb.handle == 0) {
2839 error("gl_context::shader_program_detach: shader program not created", &spb);
2840 return;
2841 }
2842 glDetachShader(get_gl_id(spb.handle), get_gl_id(sc.handle));
2843}
2844
2845bool gl_context::shader_program_link(shader_program_base& spb) const
2846{
2847 if (spb.handle == 0) {
2848 error("gl_context::shader_program_link: shader program not created", &spb);
2849 return false;
2850 }
2851 GLuint p_id = get_gl_id(spb.handle);
2853 int result;
2855 if (result == 1)
2856 return context::shader_program_link(spb);
2857 GLint infologLength = 0;
2859 if (infologLength > 0) {
2861 spb.last_error = std::string(infologLength, 0);
2862 glGetShaderInfoLog(p_id, infologLength, &charsWritten, &spb.last_error.front());
2863 spb.last_error.resize(static_cast<size_t>(charsWritten + 1));
2864 error("gl_context::shader_program_link\n" + spb.last_error, &spb);
2865 }
2866
2867 return false;
2868}
2869
2870bool gl_context::shader_program_set_state(shader_program_base& spb) const
2871{
2872 if (spb.handle == 0) {
2873 error("gl_context::shader_program_set_state: shader program not created", &spb);
2874 return false;
2875 }
2876 GLuint p_id = get_gl_id(spb.handle);
2877 glProgramParameteri(p_id, GL_GEOMETRY_VERTICES_OUT_ARB, spb.geometry_shader_output_count);
2878 glProgramParameteri(p_id, GL_GEOMETRY_INPUT_TYPE_ARB, map_to_gl(spb.geometry_shader_input_type));
2879 glProgramParameteri(p_id, GL_GEOMETRY_OUTPUT_TYPE_ARB, map_to_gl(spb.geometry_shader_output_type));
2880 return true;
2881}
2882
2883bool gl_context::shader_program_enable(shader_program_base& spb)
2884{
2885 if (!context::shader_program_enable(spb))
2886 return false;
2887 glUseProgram(get_gl_id(spb.handle));
2888 shader_program& prog = static_cast<shader_program&>(spb);
2889 if (auto_set_lights_in_current_shader_program && spb.does_use_lights())
2890 set_current_lights(prog);
2891 if (auto_set_material_in_current_shader_program && spb.does_use_material())
2893 if (auto_set_view_in_current_shader_program && spb.does_use_view())
2894 set_current_view(prog);
2895 if (auto_set_gamma_in_current_shader_program && spb.does_use_gamma())
2896 set_current_gamma(prog);
2897 if (prog.does_context_set_color() && prog.get_color_index() >= 0)
2898 prog.set_attribute(*this, prog.get_color_index(), current_color);
2899 return true;
2900}
2901
2902bool gl_context::shader_program_disable(shader_program_base& spb)
2903{
2904 if (!context::shader_program_disable(spb))
2905 return false;
2906 if (shader_program_stack.empty())
2907 glUseProgram(0);
2908 else
2909 glUseProgram(get_gl_id(shader_program_stack.top()->handle));
2910 return true;
2911}
2912
2913bool gl_context::shader_program_destruct(shader_program_base& spb) const
2914{
2915 if (!context::shader_program_destruct(spb))
2916 return false;
2917 glDeleteProgram(get_gl_id(spb.handle));
2918 spb.handle = 0;
2919 spb.ctx_ptr = 0;
2920 return true;
2921}
2922
2923bool gl_context::shader_program_get_active_uniforms(shader_program_base& spb, std::vector<std::string>& names) const
2924{
2925 if (spb.handle == 0)
2926 return false;
2927
2928 GLuint p_id = get_gl_id(spb.handle);
2929
2932
2933 names.reserve(num_active_uniforms);
2934
2935 std::vector<GLchar> buffer(256);
2936 for (int i = 0; i < num_active_uniforms; ++i) {
2937 GLint array_size = 0;
2938 GLenum type = 0;
2940
2941 glGetActiveUniform(p_id, i, GLsizei(buffer.size()), &actual_length, &array_size, &type, buffer.data());
2942 std::string name(static_cast<char*>(buffer.data()), actual_length);
2943
2944 // Uniforms for arrays of non-compound (non-struct) types are listed once with a "[0]" suffix and a given array size greater than 1.
2945 if(array_size > 1) {
2946 // Remove the brackets to get the base name of the uniform
2947 size_t bracket_pos = name.find('[');
2948 if(bracket_pos != std::string::npos)
2949 name.resize(bracket_pos);
2950
2951 if(!name.empty()) {
2952 // Store the name without the brackets to allow setting complete arrays using just the uniform name.
2953 names.push_back(name);
2954 // Additionally store an entry for every possible indexed name to allow setting elements individually.
2955 for(GLint i = 0; i < array_size; ++i)
2956 names.push_back(name + "[" + std::to_string(i) + "]");
2957 }
2958 } else {
2959 if(!name.empty())
2960 names.push_back(name);
2961 }
2962 }
2963 return true;
2964}
2965
2966program_variable_info construct_program_variable(const std::vector<GLchar>& buffer, GLsizei actual_length, GLint array_size, GLenum type)
2967{
2968 program_variable_info V;
2969 V.name = std::string(static_cast<const char*>(buffer.data()), actual_length);
2970 // Uniforms for arrays of non-compound (non-struct) types are listed once with a "[0]" suffix and a given array size greater than 1.
2971 if (array_size > 1) {
2972 // Remove the brackets to get the base name of the uniform
2973 size_t bracket_pos = V.name.find('[');
2974 if (bracket_pos != std::string::npos)
2975 V.name.resize(bracket_pos);
2976 if (!V.name.empty())
2977 V.array_size = array_size;
2978 }
2979 else {
2980 V.array_size = 1;
2981 }
2982 switch (type) {
2983 case GL_FLOAT: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, false); break;
2984 case GL_FLOAT_VEC2: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 2u); break;
2985 case GL_FLOAT_VEC3: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 3u); break;
2986 case GL_FLOAT_VEC4: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 4u); break;
2987 case GL_FLOAT_MAT2: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 2u, 2u, false); break;
2988 case GL_FLOAT_MAT3: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 3u, 3u, false); break;
2989 case GL_FLOAT_MAT4: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 4u, 4u, false); break;
2990 case GL_FLOAT_MAT2x3: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 2u, 3u, false); break;
2991 case GL_FLOAT_MAT2x4: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 2u, 4u, false); break;
2992 case GL_FLOAT_MAT3x2: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 3u, 2u, false); break;
2993 case GL_FLOAT_MAT3x4: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 3u, 4u, false); break;
2994 case GL_FLOAT_MAT4x2: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 4u, 2u, false); break;
2995 case GL_FLOAT_MAT4x3: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 4u, 3u, false); break;
2996 case GL_BOOL: V.type_descr = type_descriptor(cgv::type::info::TI_BOOL, false); break;
2997 case GL_BOOL_VEC2:V.type_descr = type_descriptor(cgv::type::info::TI_BOOL, 2u); break;
2998 case GL_BOOL_VEC3:V.type_descr = type_descriptor(cgv::type::info::TI_BOOL, 3u); break;
2999 case GL_BOOL_VEC4:V.type_descr = type_descriptor(cgv::type::info::TI_BOOL, 4u); break;
3000 case GL_INT: V.type_descr = type_descriptor(cgv::type::info::TI_INT32, false); break;
3001 case GL_INT_VEC2:V.type_descr = type_descriptor(cgv::type::info::TI_INT32, 2u); break;
3002 case GL_INT_VEC3:V.type_descr = type_descriptor(cgv::type::info::TI_INT32, 3u); break;
3003 case GL_INT_VEC4:V.type_descr = type_descriptor(cgv::type::info::TI_INT32, 4u); break;
3004 case GL_UNSIGNED_INT:V.type_descr = type_descriptor(cgv::type::info::TI_UINT32, false); break;
3005 case GL_UNSIGNED_INT_VEC2:V.type_descr = type_descriptor(cgv::type::info::TI_UINT32, 2u); break;
3006 case GL_UNSIGNED_INT_VEC3:V.type_descr = type_descriptor(cgv::type::info::TI_UINT32, 3u); break;
3007 case GL_UNSIGNED_INT_VEC4:V.type_descr = type_descriptor(cgv::type::info::TI_UINT32, 4u); break;
3008 case GL_DOUBLE: V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, false); break;
3009 case GL_DOUBLE_VEC2:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 2u); break;
3010 case GL_DOUBLE_VEC3:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 3u); break;
3011 case GL_DOUBLE_VEC4:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 4u); break;
3012 case GL_DOUBLE_MAT2:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 2u, 2u, false); break;
3013 case GL_DOUBLE_MAT3:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 3u, 3u, false); break;
3014 case GL_DOUBLE_MAT4:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 4u, 4u, false); break;
3015 case GL_DOUBLE_MAT2x3:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 2u, 3u, false); break;
3016 case GL_DOUBLE_MAT2x4:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 2u, 4u, false); break;
3017 case GL_DOUBLE_MAT3x2:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 3u, 2u, false); break;
3018 case GL_DOUBLE_MAT3x4:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 3u, 4u, false); break;
3019 case GL_DOUBLE_MAT4x2:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 4u, 2u, false); break;
3020 case GL_DOUBLE_MAT4x3:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 4u, 3u, false); break;
3021 }
3022 return V;
3023}
3024
3025void gl_context::shader_program_inspect_variables(shader_program_base& spb, ProgramVariableKind kind, std::vector<program_variable_info>& Vs, bool get_location, bool get_value) const
3026{
3027 GLint prog_id;
3028 spb.put_id(prog_id);
3029 // name buffer and sizeing informations
3030 std::vector<GLchar> buffer(256);
3031 GLint array_size = 0;
3032 GLenum type = 0;
3034 // query number of active program variables of \c kind
3037 // for inspecting attribute values, one has to use the to be inspected program. Remember previously used program
3039 if (kind == cgv::render::PVK_ATTRIBUTE) {
3041 if (old_prog_id != prog_id)
3043 }
3044 // iterate all variables of \c kind
3045 for (int i = 0; i < num_active_variables; ++i) {
3046 // extract type and array information of program variable
3047 (kind == cgv::render::PVK_UNIFORM ? glGetActiveUniform : glGetActiveAttrib)(prog_id, i,
3048 GLsizei(buffer.size()), &actual_length, &array_size, &type, buffer.data());
3049 cgv::render::program_variable_info V = construct_program_variable(buffer, actual_length, array_size, type);
3050 // compute component count \c cnt, array element size \c s and total size \c S for all values in array
3051 size_t cnt = 1, s, S;
3052 if (get_value) {
3053 V.compute_sizes(cnt, s, S);
3054 V.current_value.resize(S);
3055 }
3056 // in case of attributes provide a read buffer to read array elements which write
3057 // always 4 components even if only one component is declared
3058 std::vector<char> read_buffer;
3059 if (kind == cgv::render::PVK_ATTRIBUTE && cnt != 4)
3060 read_buffer.resize(4 * s / cnt);
3061 for (unsigned j = 0; j < V.array_size; ++j) {
3062 // in case of array variables use per array element postfix to query location
3063 std::string postfix;
3064 if (V.array_size > 1)
3065 postfix += "[" + cgv::utils::to_string(j) + "]";
3066 // query location of variable in
3067 if (get_location || get_value)
3068 V.program_location = (kind == cgv::render::PVK_UNIFORM ? glGetUniformLocation : glGetAttribLocation)(
3069 prog_id, (V.name + postfix).c_str());
3070 // one is not allowed to query program attribute at location 0
3071 if (kind == cgv::render::PVK_ATTRIBUTE && V.program_location == 0) {
3072 V.current_value.clear();
3073 break;
3074 }
3075 if (!get_value)
3076 break;
3077 // let read_ptr point where program variable values should be queried to
3078 void* value_ptr = V.current_value.data() + j * s;
3079 void* read_ptr = read_buffer.empty() ? value_ptr : read_buffer.data();
3080 // switch over coordinate type to vary gl getter function
3081 switch (V.type_descr.coordinate_type) {
3084 if (kind == cgv::render::PVK_UNIFORM)
3085 glGetUniformiv(prog_id, V.program_location, (GLint*)(read_ptr));
3086 else
3088 break;
3090 if (kind == cgv::render::PVK_UNIFORM)
3091 glGetUniformuiv(prog_id, V.program_location, (GLuint*)(read_ptr));
3092 else
3094 break;
3096 if (kind == cgv::render::PVK_UNIFORM)
3097 glGetUniformfv(prog_id, V.program_location, (GLfloat*)(read_ptr));
3098 else
3100 break;
3102 if (kind == cgv::render::PVK_UNIFORM)
3103 glGetUniformdv(prog_id, V.program_location, (GLdouble*)(read_ptr));
3104 else
3106 break;
3107 }
3108 // in case we copied to read buffer, copy used value[s] to value buffer
3109 if (read_ptr != value_ptr)
3110 std::copy((const char*)read_ptr, (const char*)read_ptr + s, (char*)value_ptr);
3111 }
3112 // add inspected variable to list
3113 Vs.push_back(V);
3114 }
3115 // recover previously used program
3116 if (old_prog_id != prog_id)
3118}
3119
3120
3121int gl_context::get_uniform_location(const shader_program_base& spb, const std::string& name) const
3122{
3123 return glGetUniformLocation(get_gl_id(spb.handle), name.c_str());
3124}
3125
3126std::string value_type_index_to_string(type_descriptor td)
3127{
3128 std::string res = cgv::type::info::get_type_name(td.coordinate_type);
3129 switch (td.element_type) {
3130 case ET_VECTOR:
3131 res = std::string("vector<") + res + "," + cgv::utils::to_string(td.nr_rows) + ">";
3132 break;
3133 case ET_MATRIX:
3134 res = std::string("matrix<") + res + "," + cgv::utils::to_string(td.nr_rows) + "," + cgv::utils::to_string(td.nr_columns) + ">";
3135 if (td.is_row_major)
3136 res += "^T";
3137 default:
3138 break;
3139 }
3140 if (td.is_array)
3141 res += "[]";
3142 return res;
3143}
3144
3145bool gl_context::set_uniform_void(shader_program_base& spb, int loc, type_descriptor value_type, const void* value_ptr) const
3146{
3147 if (value_type.is_array) {
3148 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") array type not supported, please use set_uniform_array instead.", &spb);
3149 return false;
3150 }
3151 if (!spb.handle) {
3152 error("gl_context::set_uniform_void() called on not created program", &spb);
3153 return false;
3154 }
3155 bool not_current = shader_program_stack.empty() || shader_program_stack.top() != &spb;
3156 if (not_current)
3157 glUseProgram(get_gl_id(spb.handle));
3158 bool res = true;
3159 switch (value_type.element_type) {
3160 case ET_VALUE:
3161 switch (value_type.coordinate_type) {
3162 case TI_BOOL: glUniform1i(loc, *reinterpret_cast<const bool*>(value_ptr) ? 1 : 0); break;
3163 case TI_UINT8: glUniform1ui(loc, *reinterpret_cast<const uint8_type*>(value_ptr)); break;
3164 case TI_UINT16: glUniform1ui(loc, *reinterpret_cast<const uint16_type*>(value_ptr)); break;
3165 case TI_UINT32: glUniform1ui(loc, *reinterpret_cast<const uint32_type*>(value_ptr)); break;
3166 case TI_INT8: glUniform1i(loc, *reinterpret_cast<const int8_type*>(value_ptr)); break;
3167 case TI_INT16: glUniform1i(loc, *reinterpret_cast<const int16_type*>(value_ptr)); break;
3168 case TI_INT32: glUniform1i(loc, *reinterpret_cast<const int32_type*>(value_ptr)); break;
3169 case TI_FLT32: glUniform1f(loc, *reinterpret_cast<const flt32_type*>(value_ptr)); break;
3170 case TI_FLT64: glUniform1d(loc, *reinterpret_cast<const flt64_type*>(value_ptr)); break;
3171 default:
3172 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3173 res = false; break;
3174 }
3175 break;
3176 case ET_VECTOR:
3177 switch (value_type.nr_rows) {
3178 case 2:
3179 switch (value_type.coordinate_type) {
3180 case TI_BOOL: glUniform2i(loc, reinterpret_cast<const bool*>(value_ptr)[0] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[1] ? 1 : 0); break;
3181 case TI_UINT8: glUniform2ui(loc, reinterpret_cast<const uint8_type*> (value_ptr)[0], reinterpret_cast<const uint8_type*> (value_ptr)[1]); break;
3182 case TI_UINT16: glUniform2ui(loc, reinterpret_cast<const uint16_type*>(value_ptr)[0], reinterpret_cast<const uint16_type*>(value_ptr)[1]); break;
3183 case TI_UINT32: glUniform2ui(loc, reinterpret_cast<const uint32_type*>(value_ptr)[0], reinterpret_cast<const uint32_type*>(value_ptr)[1]); break;
3184 case TI_INT8: glUniform2i(loc, reinterpret_cast<const int8_type*> (value_ptr)[0], reinterpret_cast<const int8_type*> (value_ptr)[1]); break;
3185 case TI_INT16: glUniform2i(loc, reinterpret_cast<const int16_type*> (value_ptr)[0], reinterpret_cast<const int16_type*> (value_ptr)[1]); break;
3186 case TI_INT32: glUniform2i(loc, reinterpret_cast<const int32_type*> (value_ptr)[0], reinterpret_cast<const int32_type*> (value_ptr)[1]); break;
3187 case TI_FLT32: glUniform2f(loc, reinterpret_cast<const flt32_type*> (value_ptr)[0], reinterpret_cast<const flt32_type*> (value_ptr)[1]); break;
3188 case TI_FLT64: glUniform2d(loc, reinterpret_cast<const flt64_type*> (value_ptr)[0], reinterpret_cast<const flt64_type*> (value_ptr)[1]); break;
3189 default:
3190 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3191 res = false; break;
3192 }
3193 break;
3194 case 3:
3195 switch (value_type.coordinate_type) {
3196 case TI_BOOL: glUniform3i(loc, reinterpret_cast<const bool*>(value_ptr)[0] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[1] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[2] ? 1 : 0); break;
3197 case TI_UINT8: glUniform3ui(loc, reinterpret_cast<const uint8_type*> (value_ptr)[0], reinterpret_cast<const uint8_type*> (value_ptr)[1], reinterpret_cast<const uint8_type*> (value_ptr)[2]); break;
3198 case TI_UINT16: glUniform3ui(loc, reinterpret_cast<const uint16_type*>(value_ptr)[0], reinterpret_cast<const uint16_type*>(value_ptr)[1], reinterpret_cast<const uint16_type*>(value_ptr)[2]); break;
3199 case TI_UINT32: glUniform3ui(loc, reinterpret_cast<const uint32_type*>(value_ptr)[0], reinterpret_cast<const uint32_type*>(value_ptr)[1], reinterpret_cast<const uint32_type*>(value_ptr)[2]); break;
3200 case TI_INT8: glUniform3i(loc, reinterpret_cast<const int8_type*> (value_ptr)[0], reinterpret_cast<const int8_type*> (value_ptr)[1], reinterpret_cast<const int8_type*> (value_ptr)[2]); break;
3201 case TI_INT16: glUniform3i(loc, reinterpret_cast<const int16_type*> (value_ptr)[0], reinterpret_cast<const int16_type*> (value_ptr)[1], reinterpret_cast<const int16_type*> (value_ptr)[2]); break;
3202 case TI_INT32: glUniform3i(loc, reinterpret_cast<const int32_type*> (value_ptr)[0], reinterpret_cast<const int32_type*> (value_ptr)[1], reinterpret_cast<const int32_type*> (value_ptr)[2]); break;
3203 case TI_FLT32: glUniform3f(loc, reinterpret_cast<const flt32_type*> (value_ptr)[0], reinterpret_cast<const flt32_type*> (value_ptr)[1], reinterpret_cast<const flt32_type*> (value_ptr)[2]); break;
3204 case TI_FLT64: glUniform3d(loc, reinterpret_cast<const flt64_type*> (value_ptr)[0], reinterpret_cast<const flt64_type*> (value_ptr)[1], reinterpret_cast<const flt64_type*> (value_ptr)[2]); break;
3205 default:
3206 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3207 res = false; break;
3208 }
3209 break;
3210 case 4:
3211 switch (value_type.coordinate_type) {
3212 case TI_BOOL: glUniform4i(loc, reinterpret_cast<const bool*>(value_ptr)[0] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[1] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[2] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[3] ? 1 : 0); break;
3213 case TI_UINT8: glUniform4ui(loc, reinterpret_cast<const uint8_type*> (value_ptr)[0], reinterpret_cast<const uint8_type*> (value_ptr)[1], reinterpret_cast<const uint8_type*> (value_ptr)[2], reinterpret_cast<const uint8_type*> (value_ptr)[3]); break;
3214 case TI_UINT16: glUniform4ui(loc, reinterpret_cast<const uint16_type*>(value_ptr)[0], reinterpret_cast<const uint16_type*>(value_ptr)[1], reinterpret_cast<const uint16_type*>(value_ptr)[2], reinterpret_cast<const uint16_type*>(value_ptr)[3]); break;
3215 case TI_UINT32: glUniform4ui(loc, reinterpret_cast<const uint32_type*>(value_ptr)[0], reinterpret_cast<const uint32_type*>(value_ptr)[1], reinterpret_cast<const uint32_type*>(value_ptr)[2], reinterpret_cast<const uint32_type*>(value_ptr)[3]); break;
3216 case TI_INT8: glUniform4i(loc, reinterpret_cast<const int8_type*> (value_ptr)[0], reinterpret_cast<const int8_type*> (value_ptr)[1], reinterpret_cast<const int8_type*> (value_ptr)[2], reinterpret_cast<const int8_type*> (value_ptr)[3]); break;
3217 case TI_INT16: glUniform4i(loc, reinterpret_cast<const int16_type*> (value_ptr)[0], reinterpret_cast<const int16_type*> (value_ptr)[1], reinterpret_cast<const int16_type*> (value_ptr)[2], reinterpret_cast<const int16_type*> (value_ptr)[3]); break;
3218 case TI_INT32: glUniform4i(loc, reinterpret_cast<const int32_type*> (value_ptr)[0], reinterpret_cast<const int32_type*> (value_ptr)[1], reinterpret_cast<const int32_type*> (value_ptr)[2], reinterpret_cast<const int32_type*> (value_ptr)[3]); break;
3219 case TI_FLT32: glUniform4f(loc, reinterpret_cast<const flt32_type*> (value_ptr)[0], reinterpret_cast<const flt32_type*> (value_ptr)[1], reinterpret_cast<const flt32_type*> (value_ptr)[2], reinterpret_cast<const flt32_type*> (value_ptr)[3]); break;
3220 case TI_FLT64: glUniform4d(loc, reinterpret_cast<const flt64_type*> (value_ptr)[0], reinterpret_cast<const flt64_type*> (value_ptr)[1], reinterpret_cast<const flt64_type*> (value_ptr)[2], reinterpret_cast<const flt64_type*> (value_ptr)[3]); break;
3221 default:
3222 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3223 res = false; break;
3224 }
3225 break;
3226 }
3227 break;
3228 case ET_MATRIX:
3229 switch (value_type.coordinate_type) {
3230 case TI_FLT32:
3231 switch (value_type.nr_rows) {
3232 case 2:
3233 switch (value_type.nr_columns) {
3234 case 2: glUniformMatrix2fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3235 case 3: glUniformMatrix2x3fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3236 case 4: glUniformMatrix2x4fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3237 default:
3238 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3239 res = false; break;
3240 }
3241 break;
3242 case 3:
3243 switch (value_type.nr_columns) {
3244 case 2: glUniformMatrix3x2fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3245 case 3: glUniformMatrix3fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3246 case 4: glUniformMatrix3x4fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3247 default:
3248 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3249 res = false; break;
3250 }
3251 break;
3252 case 4:
3253 switch (value_type.nr_columns) {
3254 case 2: glUniformMatrix4x2fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3255 case 3: glUniformMatrix4x3fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3256 case 4: glUniformMatrix4fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3257 default:
3258 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3259 res = false; break;
3260 }
3261 break;
3262 default:
3263 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of rows outside [2,..,4].", &spb);
3264 res = false; break;
3265 }
3266 break;
3267 case TI_FLT64:
3268 switch (value_type.nr_rows) {
3269 case 2:
3270 switch (value_type.nr_columns) {
3271 case 2: glUniformMatrix2dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3272 case 3: glUniformMatrix2x3dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3273 case 4: glUniformMatrix2x4dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3274 default:
3275 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3276 res = false; break;
3277 }
3278 break;
3279 case 3:
3280 switch (value_type.nr_columns) {
3281 case 2: glUniformMatrix3x2dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3282 case 3: glUniformMatrix3dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3283 case 4: glUniformMatrix3x4dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3284 default:
3285 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3286 res = false; break;
3287 }
3288 break;
3289 case 4:
3290 switch (value_type.nr_columns) {
3291 case 2: glUniformMatrix4x2dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3292 case 3: glUniformMatrix4x3dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3293 case 4: glUniformMatrix4dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3294 default:
3295 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3296 res = false; break;
3297 }
3298 break;
3299 default:
3300 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of rows outside [2,..,4].", &spb);
3301 res = false; break;
3302 }
3303 break;
3304 default:
3305 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") non float coordinate type not supported.", &spb);
3306 res = false; break;
3307 }
3308 break;
3309 }
3310 if (not_current)
3311 glUseProgram(shader_program_stack.empty() ? 0 : get_gl_id(shader_program_stack.top()->handle));
3312
3313 if (check_gl_error("gl_context::set_uniform_void()", &spb))
3314 res = false;
3315 return res;
3316}
3317
3318bool gl_context::set_uniform_array_void(shader_program_base& spb, int loc, type_descriptor value_type, const void* value_ptr, size_t nr_elements) const
3319{
3320 if (!value_type.is_array) {
3321 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") non array type not allowed.", &spb);
3322 return false;
3323 }
3324 if (!spb.handle) {
3325 error("gl_context::set_uniform_array_void() called on not created program", &spb);
3326 return false;
3327 }
3328 bool not_current = shader_program_stack.empty() || shader_program_stack.top() != &spb;
3329 if (not_current)
3330 glUseProgram(get_gl_id(spb.handle));
3331 bool res = true;
3332 switch (value_type.coordinate_type) {
3333 case TI_INT32:
3334 switch (value_type.element_type) {
3335 case ET_VALUE:
3336 glUniform1iv(loc, GLsizei(nr_elements), reinterpret_cast<const int32_type*>(value_ptr));
3337 break;
3338 case ET_VECTOR:
3339 switch (value_type.nr_rows) {
3340 case 2: glUniform2iv(loc, GLsizei(nr_elements), reinterpret_cast<const int32_type*>(value_ptr)); break;
3341 case 3: glUniform3iv(loc, GLsizei(nr_elements), reinterpret_cast<const int32_type*>(value_ptr)); break;
3342 case 4: glUniform4iv(loc, GLsizei(nr_elements), reinterpret_cast<const int32_type*>(value_ptr)); break;
3343 default:
3344 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") vector dimension outside [2,..4].", &spb);
3345 res = false;
3346 break;
3347 }
3348 break;
3349 case ET_MATRIX:
3350 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") type not supported.", &spb);
3351 res = false;
3352 break;
3353 }
3354 break;
3355 case TI_UINT32:
3356 switch (value_type.element_type) {
3357 case ET_VALUE:
3358 glUniform1uiv(loc, GLsizei(nr_elements), reinterpret_cast<const uint32_type*>(value_ptr));
3359 break;
3360 case ET_VECTOR:
3361 switch (value_type.nr_rows) {
3362 case 2: glUniform2uiv(loc, GLsizei(nr_elements), reinterpret_cast<const uint32_type*>(value_ptr)); break;
3363 case 3: glUniform3uiv(loc, GLsizei(nr_elements), reinterpret_cast<const uint32_type*>(value_ptr)); break;
3364 case 4: glUniform4uiv(loc, GLsizei(nr_elements), reinterpret_cast<const uint32_type*>(value_ptr)); break;
3365 default:
3366 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") vector dimension outside [2,..4].", &spb);
3367 res = false;
3368 break;
3369 }
3370 break;
3371 case ET_MATRIX:
3372 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") type not supported.", &spb);
3373 res = false;
3374 break;
3375 }
3376 break;
3377 case TI_FLT32:
3378 switch (value_type.element_type) {
3379 case ET_VALUE:
3380 glUniform1fv(loc, GLsizei(nr_elements), reinterpret_cast<const flt32_type*>(value_ptr));
3381 break;
3382 case ET_VECTOR:
3383 switch (value_type.nr_rows) {
3384 case 2: glUniform2fv(loc, GLsizei(nr_elements), reinterpret_cast<const flt32_type*>(value_ptr)); break;
3385 case 3: glUniform3fv(loc, GLsizei(nr_elements), reinterpret_cast<const flt32_type*>(value_ptr)); break;
3386 case 4: glUniform4fv(loc, GLsizei(nr_elements), reinterpret_cast<const flt32_type*>(value_ptr)); break;
3387 default:
3388 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") vector dimension outside [2,..4].", &spb);
3389 res = false;
3390 break;
3391 }
3392 break;
3393 case ET_MATRIX:
3394 switch (value_type.nr_rows) {
3395 case 2:
3396 switch (value_type.nr_columns) {
3397 case 2: glUniformMatrix2fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3398 case 3: glUniformMatrix2x3fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3399 case 4: glUniformMatrix2x4fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3400 default:
3401 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..4].", &spb);
3402 res = false;
3403 break;
3404 }
3405 break;
3406 case 3:
3407 switch (value_type.nr_columns) {
3408 case 2: glUniformMatrix3x2fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3409 case 3: glUniformMatrix3fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3410 case 4: glUniformMatrix3x4fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3411 default:
3412 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..4].", &spb);
3413 res = false;
3414 break;
3415 }
3416 break;
3417 case 4:
3418 switch (value_type.nr_columns) {
3419 case 2: glUniformMatrix4x2fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3420 case 3: glUniformMatrix4x3fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3421 case 4: glUniformMatrix4fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3422 default:
3423 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..4].", &spb);
3424 res = false;
3425 break;
3426 }
3427 break;
3428 default:
3429 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") matrix number of rows outside [2,..4].", &spb);
3430 res = false;
3431 break;
3432 }
3433 break;
3434 }
3435 break;
3436 default:
3437 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type (only int32, uint32, and flt32 supported).", &spb);
3438 res = false;
3439 break;
3440 }
3441 if (check_gl_error("gl_context::set_uniform_array_void()", &spb))
3442 res = false;
3443
3444 if (not_current)
3445 glUseProgram(shader_program_stack.empty() ? 0 : get_gl_id(shader_program_stack.top()->handle));
3446
3447 return res;
3448}
3449
3450int gl_context::get_attribute_location(const shader_program_base& spb, const std::string& name) const
3451{
3452 GLint loc = glGetAttribLocation(get_gl_id(spb.handle), name.c_str());
3453 return loc;
3454}
3455
3456bool gl_context::set_attribute_void(shader_program_base& spb, int loc, type_descriptor value_type, const void* value_ptr) const
3457{
3458 if (!spb.handle) {
3459 error("gl_context::set_attribute_void() called on not created program", &spb);
3460 return false;
3461 }
3462 bool not_current = shader_program_stack.empty() || shader_program_stack.top() != &spb;
3463 if (not_current)
3464 glUseProgram(get_gl_id(spb.handle));
3465 bool res = true;
3466 switch (value_type.element_type) {
3467 case ET_VALUE:
3468 switch (value_type.coordinate_type) {
3469 case TI_BOOL: glVertexAttrib1s(loc, *reinterpret_cast<const bool*>(value_ptr) ? 1 : 0); break;
3470 case TI_INT8: glVertexAttrib1s(loc, *reinterpret_cast<const int8_type*>(value_ptr)); break;
3471 case TI_INT16: glVertexAttrib1s(loc, *reinterpret_cast<const int16_type*>(value_ptr)); break;
3472 case TI_INT32: glVertexAttribI1i(loc, *reinterpret_cast<const int32_type*>(value_ptr)); break;
3473 case TI_UINT8: glVertexAttrib1s(loc, *reinterpret_cast<const uint8_type*>(value_ptr)); break;
3474 case TI_UINT16: glVertexAttribI1ui(loc, *reinterpret_cast<const uint16_type*>(value_ptr)); break;
3475 case TI_UINT32: glVertexAttribI1ui(loc, *reinterpret_cast<const uint32_type*>(value_ptr)); break;
3476 case TI_FLT32: glVertexAttrib1f(loc, *reinterpret_cast<const flt32_type*>(value_ptr)); break;
3477 case TI_FLT64: glVertexAttrib1d(loc, *reinterpret_cast<const flt64_type*>(value_ptr)); break;
3478 default:
3479 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") type not supported!", &spb);
3480 res = false;
3481 break;
3482 }
3483 break;
3484 case ET_VECTOR:
3485 switch (value_type.nr_rows) {
3486 case 2:
3487 switch (value_type.coordinate_type) {
3488 case TI_BOOL: glVertexAttrib2s(loc, reinterpret_cast<const bool*>(value_ptr)[0] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[1] ? 1 : 0); break;
3489 case TI_UINT8: glVertexAttrib2s(loc, reinterpret_cast<const uint8_type*> (value_ptr)[0], reinterpret_cast<const uint8_type*> (value_ptr)[1]); break;
3490 case TI_UINT16: glVertexAttribI2ui(loc, reinterpret_cast<const uint16_type*>(value_ptr)[0], reinterpret_cast<const uint16_type*>(value_ptr)[1]); break;
3491 case TI_UINT32: glVertexAttribI2ui(loc, reinterpret_cast<const uint32_type*>(value_ptr)[0], reinterpret_cast<const uint32_type*>(value_ptr)[1]); break;
3492 case TI_INT8: glVertexAttrib2s(loc, reinterpret_cast<const int8_type*> (value_ptr)[0], reinterpret_cast<const int8_type*> (value_ptr)[1]); break;
3493 case TI_INT16: glVertexAttrib2s(loc, reinterpret_cast<const int16_type*> (value_ptr)[0], reinterpret_cast<const int16_type*> (value_ptr)[1]); break;
3494 case TI_INT32: glVertexAttribI2i(loc, reinterpret_cast<const int32_type*> (value_ptr)[0], reinterpret_cast<const int32_type*> (value_ptr)[1]); break;
3495 case TI_FLT32: glVertexAttrib2f(loc, reinterpret_cast<const flt32_type*> (value_ptr)[0], reinterpret_cast<const flt32_type*> (value_ptr)[1]); break;
3496 case TI_FLT64: glVertexAttrib2d(loc, reinterpret_cast<const flt64_type*> (value_ptr)[0], reinterpret_cast<const flt64_type*> (value_ptr)[1]); break;
3497 default:
3498 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3499 res = false;
3500 break;
3501 }
3502 break;
3503 case 3:
3504 switch (value_type.coordinate_type) {
3505 case TI_BOOL: glVertexAttrib3s (loc, reinterpret_cast<const bool*>(value_ptr)[0] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[1] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[2] ? 1 : 0); break;
3506 case TI_UINT8: glVertexAttrib3s (loc, reinterpret_cast<const uint8_type*> (value_ptr)[0], reinterpret_cast<const uint8_type*> (value_ptr)[1], reinterpret_cast<const uint8_type*> (value_ptr)[2]); break;
3507 case TI_UINT16: glVertexAttribI3ui(loc, reinterpret_cast<const uint16_type*>(value_ptr)[0], reinterpret_cast<const uint16_type*>(value_ptr)[1], reinterpret_cast<const uint16_type*>(value_ptr)[2]); break;
3508 case TI_UINT32: glVertexAttribI3ui(loc, reinterpret_cast<const uint32_type*>(value_ptr)[0], reinterpret_cast<const uint32_type*>(value_ptr)[1], reinterpret_cast<const uint32_type*>(value_ptr)[2]); break;
3509 case TI_INT8: glVertexAttrib3s (loc, reinterpret_cast<const int8_type*> (value_ptr)[0], reinterpret_cast<const int8_type*> (value_ptr)[1], reinterpret_cast<const int8_type*> (value_ptr)[2]); break;
3510 case TI_INT16: glVertexAttrib3s (loc, reinterpret_cast<const int16_type*> (value_ptr)[0], reinterpret_cast<const int16_type*> (value_ptr)[1], reinterpret_cast<const int16_type*> (value_ptr)[2]); break;
3511 case TI_INT32: glVertexAttribI3i (loc, reinterpret_cast<const int32_type*> (value_ptr)[0], reinterpret_cast<const int32_type*> (value_ptr)[1], reinterpret_cast<const int32_type*> (value_ptr)[2]); break;
3512 case TI_FLT32: glVertexAttrib3f (loc, reinterpret_cast<const flt32_type*> (value_ptr)[0], reinterpret_cast<const flt32_type*> (value_ptr)[1], reinterpret_cast<const flt32_type*> (value_ptr)[2]); break;
3513 case TI_FLT64: glVertexAttrib3d (loc, reinterpret_cast<const flt64_type*> (value_ptr)[0], reinterpret_cast<const flt64_type*> (value_ptr)[1], reinterpret_cast<const flt64_type*> (value_ptr)[2]); break;
3514 default:
3515 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3516 res = false; break;
3517 }
3518 break;
3519 case 4:
3520 switch (value_type.coordinate_type) {
3521 case TI_BOOL: glVertexAttrib4s (loc, reinterpret_cast<const bool*>(value_ptr)[0] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[1] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[2] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[3] ? 1 : 0); break;
3522 case TI_UINT8: glVertexAttrib4s (loc, reinterpret_cast<const uint8_type*> (value_ptr)[0], reinterpret_cast<const uint8_type*> (value_ptr)[1], reinterpret_cast<const uint8_type*> (value_ptr)[2], reinterpret_cast<const uint8_type*> (value_ptr)[3]); break;
3523 case TI_UINT16: glVertexAttribI4ui(loc, reinterpret_cast<const uint16_type*>(value_ptr)[0], reinterpret_cast<const uint16_type*>(value_ptr)[1], reinterpret_cast<const uint16_type*>(value_ptr)[2], reinterpret_cast<const uint16_type*>(value_ptr)[3]); break;
3524 case TI_UINT32: glVertexAttribI4ui(loc, reinterpret_cast<const uint32_type*>(value_ptr)[0], reinterpret_cast<const uint32_type*>(value_ptr)[1], reinterpret_cast<const uint32_type*>(value_ptr)[2], reinterpret_cast<const uint32_type*>(value_ptr)[3]); break;
3525 case TI_INT8: glVertexAttrib4s (loc, reinterpret_cast<const int8_type*> (value_ptr)[0], reinterpret_cast<const int8_type*> (value_ptr)[1], reinterpret_cast<const int8_type*> (value_ptr)[2], reinterpret_cast<const int8_type*> (value_ptr)[3]); break;
3526 case TI_INT16: glVertexAttrib4s (loc, reinterpret_cast<const int16_type*> (value_ptr)[0], reinterpret_cast<const int16_type*> (value_ptr)[1], reinterpret_cast<const int16_type*> (value_ptr)[2], reinterpret_cast<const int16_type*> (value_ptr)[3]); break;
3527 case TI_INT32: glVertexAttribI4i (loc, reinterpret_cast<const int32_type*> (value_ptr)[0], reinterpret_cast<const int32_type*> (value_ptr)[1], reinterpret_cast<const int32_type*> (value_ptr)[2], reinterpret_cast<const int32_type*> (value_ptr)[3]); break;
3528 case TI_FLT32: glVertexAttrib4f (loc, reinterpret_cast<const flt32_type*> (value_ptr)[0], reinterpret_cast<const flt32_type*> (value_ptr)[1], reinterpret_cast<const flt32_type*> (value_ptr)[2], reinterpret_cast<const flt32_type*> (value_ptr)[3]); break;
3529 case TI_FLT64: glVertexAttrib4d (loc, reinterpret_cast<const flt64_type*> (value_ptr)[0], reinterpret_cast<const flt64_type*> (value_ptr)[1], reinterpret_cast<const flt64_type*> (value_ptr)[2], reinterpret_cast<const flt64_type*> (value_ptr)[3]); break;
3530 default:
3531 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3532 res = false;
3533 break;
3534 }
3535 break;
3536 default:
3537 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") vector dimension outside [2..4]", &spb);
3538 res = false;
3539 break;
3540 }
3541 break;
3542 case ET_MATRIX:
3543 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") matrix type not supported!", &spb);
3544 res = false;
3545 break;
3546 }
3547 if (not_current)
3548 glUseProgram(shader_program_stack.empty() ? 0 : get_gl_id(shader_program_stack.top()->handle));
3549
3550 if (check_gl_error("gl_context::set_uniform_array_void()", &spb))
3551 res = false;
3552 return res;
3553}
3554
3555bool gl_context::attribute_array_binding_create(attribute_array_binding_base& aab) const
3556{
3557 if (!GLEW_VERSION_3_0) {
3558 error("gl_context::attribute_array_binding_create() array attribute bindings not supported", &aab);
3559 return false;
3560 }
3561 GLuint a_id;
3563 if (a_id == -1) {
3564 error(std::string("gl_context::attribute_array_binding_create(): ") + gl_error(), &aab);
3565 return false;
3566 }
3567 aab.ctx_ptr = this;
3568 aab.handle = get_handle(a_id);
3569 return true;
3570}
3571
3572bool gl_context::attribute_array_binding_destruct(attribute_array_binding_base& aab)
3573{
3574 if (&aab == attribute_array_binding_stack.top())
3576 if (!context::attribute_array_binding_destruct(aab))
3577 return false;
3578 if (!aab.handle) {
3579 error("gl_context::attribute_array_binding_destruct(): called on not created attribute array binding", &aab);
3580 return false;
3581 }
3582 GLuint a_id = get_gl_id(aab.handle);
3584 aab.handle = 0;
3585 aab.ctx_ptr = 0;
3586 return !check_gl_error("gl_context::attribute_array_binding_destruct");
3587}
3588
3589bool gl_context::attribute_array_binding_enable(attribute_array_binding_base& aab)
3590{
3591 if (!context::attribute_array_binding_enable(aab))
3592 return false;
3593 glBindVertexArray(get_gl_id(aab.handle));
3594 return !check_gl_error("gl_context::attribute_array_binding_enable");
3595}
3596
3597bool gl_context::attribute_array_binding_disable(attribute_array_binding_base& aab)
3598{
3599 if (!context::attribute_array_binding_disable(aab))
3600 return false;
3603 else
3604 glBindVertexArray(get_gl_id(attribute_array_binding_stack.top()->handle));
3605 return true;
3606}
3607
3608bool gl_context::set_element_array(attribute_array_binding_base* aab, const vertex_buffer_base* vbb) const
3609{
3610 if (!vbb) {
3611 error("gl_context::set_element_array(): called without a vertex buffer object", aab);
3612 return false;
3613 }
3614 if (!vbb->handle) {
3615 error("gl_context::set_element_array(): called with not created vertex buffer object", vbb);
3616 return false;
3617 }
3618 if (vbb->type != VBT_INDICES) {
3619 std::cout << "gl_context::set_element_array() : called on vertex buffer object that is not of type VBT_INDICES" << std::endl;
3620// error("gl_context::set_element_array(): called on vertex buffer object that is not of type VBT_INDICES", vbb);
3621// return false;
3622 }
3623 if (aab) {
3624 if (!aab->handle) {
3625 error("gl_context::set_element_array(): called on not created attribute array binding", aab);
3626 return false;
3627 }
3628 }
3629 // enable vertex array
3631 if (aab && not_current)
3632 glBindVertexArray(get_gl_id(aab->handle));
3633
3634 // bind buffer to element array
3635 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, get_gl_id(vbb->handle));
3636
3637 if (aab && not_current)
3639
3640 return !check_gl_error("gl_context::set_element_array_void()", aab);
3641}
3642
3643
3644bool gl_context::set_attribute_array_void(attribute_array_binding_base* aab, int loc, type_descriptor value_type, const vertex_buffer_base* vbb, const void* ptr, size_t nr_elements, unsigned stride) const
3645{
3646 if (value_type == ET_MATRIX) {
3647 error("gl_context::set_attribute_array_void(): called with matrix elements not supported", aab);
3648 return false;
3649 }
3650 if (vbb) {
3651 if (!vbb->handle) {
3652 error("gl_context::set_attribute_array_void(): called with not created vertex buffer object", vbb);
3653 return false;
3654 }
3655 }
3656 if (aab) {
3657 if (!aab->handle) {
3658 error("gl_context::set_attribute_array_void(): called on not created attribute array binding", aab);
3659 return false;
3660 }
3661 }
3662
3664 if (aab && not_current)
3665 glBindVertexArray(get_gl_id(aab->handle));
3666
3667 if (vbb)
3668 glBindBuffer(GL_ARRAY_BUFFER, get_gl_id(vbb->handle));
3669
3670 bool res = true;
3671 unsigned n = value_type.element_type == ET_VALUE ? 1 : value_type.nr_rows;
3672 switch (value_type.coordinate_type) {
3673 case TI_INT8: value_type.normalize ? glVertexAttribPointer(loc, n, GL_BYTE, value_type.normalize, stride, ptr) : glVertexAttribIPointer(loc, n, GL_BYTE, stride, ptr); break;
3674 case TI_INT16: value_type.normalize ? glVertexAttribPointer(loc, n, GL_SHORT, value_type.normalize, stride, ptr) : glVertexAttribIPointer(loc, n, GL_SHORT, stride, ptr); break;
3675 case TI_INT32: value_type.normalize ? glVertexAttribPointer(loc, n, GL_INT, value_type.normalize, stride, ptr) : glVertexAttribIPointer(loc, n, GL_INT, stride, ptr); break;
3676 case TI_UINT8: value_type.normalize ? glVertexAttribPointer(loc, n, GL_UNSIGNED_BYTE, value_type.normalize, stride, ptr) : glVertexAttribIPointer(loc, n, GL_UNSIGNED_BYTE, stride, ptr); break;
3677 case TI_UINT16: value_type.normalize ? glVertexAttribPointer(loc, n, GL_UNSIGNED_SHORT, value_type.normalize, stride, ptr) : glVertexAttribIPointer(loc, n, GL_UNSIGNED_SHORT, stride, ptr); break;
3678 case TI_UINT32: value_type.normalize ? glVertexAttribPointer(loc, n, GL_UNSIGNED_INT, value_type.normalize, stride, ptr) : glVertexAttribIPointer(loc, n, GL_UNSIGNED_INT, stride, ptr); break;
3679 case TI_FLT32: glVertexAttribPointer(loc, n, GL_FLOAT, value_type.normalize, stride, ptr); break;
3680 case TI_FLT64:
3681 if (GLEW_VERSION_4_1)
3682 glVertexAttribLPointer(loc, n, GL_DOUBLE, stride, ptr);
3683 else {
3684 error("gl_context::set_attribute_array_void(): called with coordinates of type double only supported starting with OpenGL 4.1", aab);
3685 res = false;
3686 }
3687 break;
3688 default:
3689 error("gl_context::set_attribute_array_void(): called with unsupported coordinate type", aab);
3690 res = false;
3691 }
3692
3693 if (res)
3695
3696 if (vbb)
3698
3699 if (aab && not_current)
3701
3702
3703 return res && !check_gl_error("gl_context::set_attribute_array_void()", aab);
3704}
3705
3706bool gl_context::enable_attribute_array(attribute_array_binding_base* aab, int loc, bool do_enable) const
3707{
3709 if (aab) {
3710 if (!aab->handle) {
3711 error("gl_context::enable_attribute_array(): called on not created attribute array binding", aab);
3712 return false;
3713 }
3714 if (not_current)
3715 glBindVertexArray(get_gl_id(aab->handle));
3716 }
3717
3718 if (do_enable)
3720 else
3722
3723 if (aab && not_current)
3725
3726 return !check_gl_error("gl_context::enable_attribute_array()");
3727}
3728
3729bool gl_context::is_attribute_array_enabled(const attribute_array_binding_base* aab, int loc) const
3730{
3732 if (aab) {
3733 if (!aab->handle) {
3734 error("gl_context::is_attribute_array_enabled(): called on not created attribute array binding", aab);
3735 return false;
3736 }
3737 if (not_current)
3738 glBindVertexArray(get_gl_id(aab->handle));
3739 }
3740
3741 GLint res;
3743
3744 if (aab && not_current)
3746
3747 return res == GL_TRUE;
3748}
3749
3750GLenum buffer_target(VertexBufferType vbt)
3751{
3752 static GLenum buffer_targets[] = {
3761 };
3762 return buffer_targets[vbt];
3763}
3764
3765GLenum buffer_usage(VertexBufferUsage vbu)
3766{
3767 static GLenum buffer_usages[] = {
3777 };
3778 return buffer_usages[vbu];
3779}
3780
3781bool gl_context::vertex_buffer_bind(const vertex_buffer_base& vbb, VertexBufferType _type, unsigned _idx) const
3782{
3783 if (_idx == unsigned(-1))
3784 glBindBuffer(buffer_target(_type), get_gl_id(vbb.handle));
3785 else
3786 glBindBufferBase(buffer_target(_type), _idx, get_gl_id(vbb.handle));
3787 return !check_gl_error("gl_context::vertex_buffer_bind", &vbb);
3788}
3789
3790bool gl_context::vertex_buffer_unbind(const vertex_buffer_base& vbb, VertexBufferType _type, unsigned _idx) const {
3791 if(_idx == unsigned(-1))
3792 glBindBuffer(buffer_target(_type), 0);
3793 else
3794 glBindBufferBase(buffer_target(_type), _idx, 0);
3795 return !check_gl_error("gl_context::vertex_buffer_unbind", &vbb);
3796}
3797
3798bool gl_context::vertex_buffer_create(vertex_buffer_base& vbb, const void* array_ptr, size_t size_in_bytes) const
3799{
3800 if (!GLEW_VERSION_2_0) {
3801 error("gl_context::vertex_buffer_create() vertex buffer objects not supported", &vbb);
3802 return false;
3803 }
3804 GLuint b_id;
3805 glGenBuffers(1, &b_id);
3806 if (b_id == -1) {
3807 error(std::string("gl_context::vertex_buffer_create(): ") + gl_error(), &vbb);
3808 return false;
3809 }
3810 vbb.handle = get_handle(b_id);
3811 glBindBuffer(buffer_target(vbb.type), b_id);
3812 glBufferData(buffer_target(vbb.type), size_in_bytes, array_ptr, buffer_usage(vbb.usage));
3813 glBindBuffer(buffer_target(vbb.type), 0);
3814 return !check_gl_error("gl_context::vertex_buffer_create", &vbb);
3815}
3816
3817bool gl_context::vertex_buffer_resize(vertex_buffer_base& vbb, const void* array_ptr, size_t size_in_bytes) const {
3818 if(!vbb.handle) {
3819 error("gl_context::vertex_buffer_resize() vertex buffer object must be created before", &vbb);
3820 return false;
3821 }
3822 GLuint b_id = get_gl_id(vbb.handle);
3823 glBindBuffer(buffer_target(vbb.type), b_id);
3824 glBufferData(buffer_target(vbb.type), size_in_bytes, array_ptr, buffer_usage(vbb.usage));
3825 glBindBuffer(buffer_target(vbb.type), 0);
3826 return !check_gl_error("gl_context::vertex_buffer_resize", &vbb);
3827}
3828
3829bool gl_context::vertex_buffer_clear(vertex_buffer_base& vbb, size_t offset, size_t size_in_bytes) const
3830{
3831 if (!vbb.handle) {
3832 error("gl_context::vertex_buffer_clear() vertex buffer object must be created before", &vbb);
3833 return false;
3834 }
3835 GLuint b_id = get_gl_id(vbb.handle);
3836 glBindBuffer(buffer_target(vbb.type), b_id);
3837 glClearBufferSubData(buffer_target(vbb.type), GL_R8, offset, size_in_bytes, GL_RED, GL_UNSIGNED_BYTE, NULL);
3838 glBindBuffer(buffer_target(vbb.type), 0);
3839 return !check_gl_error("gl_context::vertex_buffer_clear", &vbb);
3840}
3841
3842bool gl_context::vertex_buffer_replace(vertex_buffer_base& vbb, size_t offset, size_t size_in_bytes, const void* array_ptr) const
3843{
3844 if (!vbb.handle) {
3845 error("gl_context::vertex_buffer_replace() vertex buffer object must be created before", &vbb);
3846 return false;
3847 }
3848 GLuint b_id = get_gl_id(vbb.handle);
3849 glBindBuffer(buffer_target(vbb.type), b_id);
3850 glBufferSubData(buffer_target(vbb.type), offset, size_in_bytes, array_ptr);
3851 glBindBuffer(buffer_target(vbb.type), 0);
3852 return !check_gl_error("gl_context::vertex_buffer_replace", &vbb);
3853}
3854
3855bool gl_context::vertex_buffer_copy(const vertex_buffer_base& src, size_t src_offset, vertex_buffer_base& target, size_t target_offset, size_t size_in_bytes) const
3856{
3857 if (!src.handle || !target.handle) {
3858 error("gl_context::vertex_buffer_copy() source and destination vertex buffer objects must have been created before", &src);
3859 return false;
3860 }
3861 GLuint b_id = get_gl_id(src.handle);
3862 glBindBuffer(GL_COPY_READ_BUFFER, get_gl_id(src.handle));
3863 glBindBuffer(GL_COPY_WRITE_BUFFER, get_gl_id(target.handle));
3867 return !check_gl_error("gl_context::vertex_buffer_copy", &src);
3868
3869}
3870
3871bool gl_context::vertex_buffer_copy_back(const vertex_buffer_base& vbb, size_t offset, size_t size_in_bytes, void* array_ptr) const
3872{
3873 if (!vbb.handle) {
3874 error("gl_context::vertex_buffer_copy_back() vertex buffer object must be created", &vbb);
3875 return false;
3876 }
3877 GLuint b_id = get_gl_id(vbb.handle);
3879 switch (vbb.type) {
3888 }
3890 glGetBufferSubData(bind_point, offset, size_in_bytes, array_ptr);
3892 return !check_gl_error("gl_context::vertex_buffer_copy_back", &vbb);
3893}
3894
3895bool gl_context::vertex_buffer_destruct(vertex_buffer_base& vbb) const
3896{
3897 if (vbb.handle) {
3898 GLuint b_id = get_gl_id(vbb.handle);
3899 glDeleteBuffers(1, &b_id);
3900 vbb.handle = 0;
3901 vbb.ctx_ptr = 0;
3902 return !check_gl_error("gl_context::vertex_buffer_destruct");
3903 }
3904 else {
3905 error("gl_context::vertex_buffer_destruct(): called on not created vertex buffer", &vbb);
3906 return false;
3907 }
3908}
3909
3910
3911 }
3912 }
3913}
virtual void stream_stats(std::ostream &)
overload to show the content of this object
Definition base.cxx:24
The group class is a node with children.
Definition group.h:20
complete implementation of method actions that only call one method when entering a node
Definition action.h:113
interface of a handler for traverse callbacks
Definition traverser.h:77
class used to traverse a tree structure
Definition traverser.h:102
bool traverse(base_ptr start, traverse_callback_handler *tch=0)
traverse a tree starting at given node according to set strategy, order and dest and previously comin...
the component format inherits the information of a packing_info and adds information on the component...
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
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
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 component_format & get_component_format() const
return the component_format info by simple conversion of the this pointer
void manage_format(bool enable=true)
whether to manage the data format pointer
Definition data_view.cxx:59
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
~data_view()
destruct view and delete data pointer if it is owned by the view
void reflect_horizontally()
reflect 2D data view at horizontal axis
unsigned int get_component_alignment() const
return the component alignment in bits in the packed case and in bytes in the unpacked case
bool empty() const
check if pointer is not yet set
Definition ref_ptr.h:230
virtual void stream_help(std::ostream &os)=0
overload to stream help information to the given output stream
matrix of fixed size dimensions
Definition fmat.h:23
A matrix type (full column major storage) The matrix can be loaded directly into OpenGL without need ...
Definition mat.h:208
>simple class to hold the properties of a light source
the image writer chooses a specific writer automatically based on the extension of the given file nam...
static const std::string & get_supported_extensions(char sep=';')
return a string with a list of supported extensions, where the list entries are separated with the pa...
the attribute_array_binding allows to define vertex attributes (i.e.
bool enable(context &ctx)
enable whole the attribute array binding object
static bool enable_global_array(const context &ctx, int loc)
enable attribute array of given location
bool create(const context &ctx)
create the attribute array binding object
bool disable(context &ctx)
disable whole attribute array binding object
static bool disable_global_array(const context &ctx, int loc)
disable attribute array of given location
bool enable_array(const context &ctx, int loc)
enable array for vertex attribute at location loc
bool disable_array(const context &ctx, int loc)
disable array for attribute at location loc
bool set_attribute_array(const context &ctx, int loc, const T &array)
set vertex attribute location to given array and enable array
virtual void set_blend_func(BlendFunction src_factor, BlendFunction dst_factor)
set the blend function
Definition context.cxx:1858
virtual std::ostream & output_stream()
returns an output stream whose output is printed at the current cursor location, which is managed by ...
Definition context.cxx:1013
virtual void mul_modelview_matrix(const dmat4 &MV)
multiply given matrix from right to current modelview matrix
Definition context.cxx:1933
virtual void set_depth_range(const dvec2 &depth_range=dvec2(0, 1), int array_index=-1)
set the current depth range or one of the depth ranges in the window transformation array
Definition context.cxx:2033
virtual bool in_render_process() const =0
return whether the context is currently in process of rendering
virtual bool is_created() const =0
return whether the context is created
shader_program_base * get_current_program() const
check for current program, prepare it for rendering and return pointer to it
Definition context.cxx:537
virtual void error(const std::string &message, const render_component *rc=0) const
error handling
Definition context.cxx:307
void set_current_view(shader_program &prog, bool modelview_deps=true, bool projection_deps=true) const
set the shader program view matrices to the currently enabled view matrices
Definition context.cxx:673
float current_font_size
store current font size
Definition context.h:837
bool enable_vsync
whether vsync should be enabled
Definition context.h:742
virtual void set_buffer_mask(BufferMask mask)
set the buffer mask for depth and color buffers
Definition context.cxx:1902
virtual bool is_current() const =0
return whether the context is current
bool auto_set_lights_in_current_shader_program
whether to automatically set lights in current shader program, defaults to true
Definition context.h:730
virtual void set_blend_func_separate(BlendFunction src_color_factor, BlendFunction dst_color_factor, BlendFunction src_alpha_factor, BlendFunction dst_alpha_factor)
set the blend function separately for color and alpha
Definition context.cxx:1866
virtual void on_lights_changed()
helper function to send light update events
Definition context.cxx:729
void push_depth_test_state()
push a copy of the current depth test state onto the stack saved attributes: depth test enablement,...
Definition context.cxx:1794
std::stack< shader_program_base * > shader_program_stack
stack of currently enabled shader programs
Definition context.h:775
bool is_light_source_enabled(void *handle)
check whether light source is enabled
Definition context.cxx:773
virtual void disable_depth_test()
disable the depth test
Definition context.cxx:1820
int get_bg_stencil() const
return the current stencil value for clearing the background
Definition context.cxx:463
virtual unsigned int get_width() const =0
return the width of the window
bool disable_light_source(void *handle)
disable a given light source and return whether there existed a light source with given handle
Definition context.cxx:797
void pop_depth_test_state()
pop the top of the current depth test state from the stack
Definition context.cxx:1798
void tesselate_unit_sphere(int resolution=25, bool flip_normals=false, bool edges=false)
tesselate a sphere of radius 1
Definition context.cxx:1444
virtual RenderPassFlags get_render_pass_flags() const
return the current render pass flags
Definition context.cxx:855
void tesselate_unit_cylinder(int resolution=25, bool flip_normals=false, bool edges=false)
tesselate a cylinder of radius 1
Definition context.cxx:1352
virtual void set_bg_color(vec4 rgba)
set a user defined background color
Definition context.cxx:390
virtual void set_depth_test_state(DepthTestState state)
set the depth test state
Definition context.cxx:1807
size_t get_nr_enabled_light_sources() const
return the number of light sources
Definition context.cxx:762
virtual unsigned int get_height() const =0
return the height of the window
virtual void disable_blending()
disable blending
Definition context.cxx:1885
BufferMask get_buffer_mask() const
return the current buffer mask
Definition context.cxx:1898
void push_cull_state()
push a copy of the current culling state onto the stack saved attributes: cull face enablement,...
Definition context.cxx:1824
virtual void enable_font_face(media::font::font_face_ptr font_face, float font_size)
enable the given font face with the given size in pixels
Definition context.cxx:1018
std::stack< dmat4 > modelview_matrix_stack
keep two matrix stacks for model view and projection matrices
Definition context.h:769
virtual void pop_window_transformation_array()
restore previous viewport and depth range arrays defining the window transformations
Definition context.cxx:2000
virtual void set_color_mask(bvec4 flags)
set the color buffer mask
Definition context.cxx:1919
virtual void set_material(const cgv::media::illum::surface_material &mat)
set the current material
Definition context.cxx:1757
DepthTestState get_depth_test_state() const
return the current depth test state
Definition context.cxx:1803
bool auto_set_material_in_current_shader_program
whether to automatically set material in current shader program, defaults to true
Definition context.h:732
void set_current_lights(shader_program &prog) const
set the shader program lights to the currently enabled lights
Definition context.cxx:714
bool enable_light_source(void *handle)
enable a given light source and return whether there existed a light source with given handle
Definition context.cxx:782
void tesselate_unit_disk(int resolution=25, bool flip_normals=false, bool edges=false)
tesselate a circular disk of radius 1
Definition context.cxx:1276
virtual void enable_depth_test()
enable the depth test
Definition context.cxx:1816
bool support_compatibility_mode
whether to support view and lighting management of compatibility mode, defaults to true
Definition context.h:736
void set_current_gamma(shader_program &prog) const
set the shader program gamma values
Definition context.cxx:1680
vec4 get_bg_color() const
return the current color value for clearing the background
Definition context.cxx:399
void pop_projection_matrix()
see push_P for an explanation
Definition context.cxx:1950
std::stack< attribute_array_binding_base * > attribute_array_binding_stack
stack of currently enabled attribute array binding
Definition context.h:787
BlendState get_blend_state() const
return the current blend state
Definition context.cxx:1850
virtual void set_cull_state(CullingMode culling_mode)
set the culling state
Definition context.cxx:1837
virtual void set_depth_func(CompareFunction func)
set the depth test function
Definition context.cxx:1811
void set_light_source(void *handle, const cgv::media::illum::light_source &light, bool place_now=true)
set light source newly
Definition context.cxx:660
void push_projection_matrix()
same as push_V but for the projection matrix - a different matrix stack is used.
Definition context.cxx:1945
bool current_material_is_textured
store flag to tell whether current material is textured
Definition context.h:815
virtual void set_projection_matrix(const dmat4 &P)
set the current projection matrix, which transforms from eye to clip space
Definition context.cxx:1978
rgba current_color
current color value
Definition context.h:744
static const unsigned nr_default_light_sources
number of default light sources
Definition context.h:805
cgv::media::illum::light_source default_light_source[nr_default_light_sources]
default light sources
Definition context.h:807
virtual void set_cursor(int x, int y)
flush the output_stream and set a new cursor position given in opengl coordinates with (0,...
Definition context.cxx:2083
virtual void set_bg_stencil(int s)
set a user defined background stencil value
Definition context.cxx:459
virtual void set_bg_accum_color(vec4 rgba)
set a user defined background color for the accumulation buffer
Definition context.cxx:476
cgv::media::illum::surface_material default_material
store a default material
Definition context.h:811
float get_bg_depth() const
return the current depth value for clearing the background
Definition context.cxx:446
virtual void set_textured_material(const textured_material &mat)
set the current material
Definition context.cxx:1776
std::stack< std::vector< window_transformation > > window_transformation_stack
keep stack of window transformations
Definition context.h:771
vec4 get_bg_accum_color() const
return the current color value for clearing the accumulation buffer
Definition context.cxx:484
const cgv::media::illum::light_source & get_light_source(void *handle) const
read access to light source
Definition context.cxx:645
virtual bool make_current() const =0
make the current context current if possible
bool draw_in_compatibility_mode
whether to do all drawing in compatibility mode, only possible if support_compatibility_mode is true,...
Definition context.h:738
virtual void set_blend_state(BlendState state)
set the complete blend state
Definition context.cxx:1854
bool sRGB_framebuffer
whether to use opengl option to support sRGB framebuffer
Definition context.h:746
virtual RenderPassFlags get_default_render_pass_flags() const
return the default render pass flags
Definition context.cxx:863
virtual void set_bg_depth(float d)
set a user defined background depth value
Definition context.cxx:442
virtual void enable_blending()
enable blending
Definition context.cxx:1881
void set_current_material(shader_program &prog) const
set the shader program material to the currently enabled material
Definition context.cxx:702
void pop_cull_state()
pop the top of the current culling state from the stack
Definition context.cxx:1828
void pop_modelview_matrix()
see push_V for an explanation
Definition context.cxx:1939
void * default_light_source_handles[nr_default_light_sources]
handles of default light sources
Definition context.h:809
void push_modelview_matrix()
push the current viewing matrix onto a matrix stack for viewing matrices.
Definition context.cxx:1927
std::stack< frame_buffer_base * > frame_buffer_stack
stack of currently enabled frame buffers
Definition context.h:773
bool auto_set_view_in_current_shader_program
whether to automatically set viewing matrixes in current shader program, defaults to true
Definition context.h:728
void tesselate_unit_cone(int resolution=25, bool flip_normals=false, bool edges=false)
tesselate a cone of radius 1
Definition context.cxx:1308
CullingMode get_cull_state() const
return the current culling state
Definition context.cxx:1833
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:2026
const cgv::media::illum::surface_material * current_material_ptr
store pointer to current material
Definition context.h:813
virtual void set_modelview_matrix(const dmat4 &MV)
set the current modelview matrix, which transforms from world to eye space
Definition context.cxx:1961
void * get_enabled_light_source_handle(size_t i) const
access to handle of i-th light source
Definition context.cxx:768
cgv::media::font::font_face_ptr current_font_face
store current font
Definition context.h:839
virtual void set_depth_mask(bool flag)
set the depth buffer mask
Definition context.cxx:1910
bool auto_set_gamma_in_current_shader_program
whether to automatically set gamma in current shader program, defaults to true
Definition context.h:734
virtual void init_frame(context &)
this method is called in one pass over all drawables before the draw method
Definition drawable.cxx:108
virtual void resize(unsigned int w, unsigned int h)
callback to announce resizing of the output window
Definition drawable.cxx:104
virtual bool init(context &)
this method is called after creation or recreation of the context, return whether all necessary funct...
Definition drawable.cxx:99
base interface for framebuffer
Definition context.h:527
implementation of the context API for the OpenGL API excluding methods for font selection,...
Definition gl_context.h:44
media::font::font_face_ptr get_current_font_face() const override
overwrite function to return info font face in case no font is currently selected
void set_depth_func(CompareFunction func) override
set the depth test function
void push_pixel_coords() override
use this to push transformation matrices on the stack such that x and y coordinates correspond to win...
void set_depth_mask(bool flag) override
set the depth buffer mask
RenderAPI get_render_api() const override
return the used rendering API
bool frame_buffer_disable(frame_buffer_base &fbb) override
disable the framebuffer object
void tesselate_arrow(double length=1, double aspect=0.1, double rel_tip_radius=2.0, double tip_aspect=0.3, int res=25, bool edges=false) override
tesselate an arrow from the origin in z-direction
void set_color(const rgba &clr) override
set the current color
void set_buffer_mask(BufferMask mask) override
set the buffer mask for depth and color buffers
float info_font_size
font size to draw textual info
Definition gl_context.h:147
bool frame_buffer_is_complete(const frame_buffer_base &fbb) const override
check for completeness, if not complete, get the reason in last_error
void set_bg_color(vec4 rgba) override
set a user defined background color
void draw_light_source(const cgv::media::illum::light_source &l, float intensity_scale, float light_scale) override
draw a light source with an emissive material
void announce_external_viewport_change(ivec4 &cgv_viewport_storage) override
announce an external viewport change performed with rendering API to the cgv framework providing spac...
void enumerate_program_attributes(shader_program &prog, std::vector< std::string > &names, std::vector< int > *locations_ptr=0, std::vector< int > *sizes_ptr=0, std::vector< int > *types_ptr=0, bool show=false) const override
get list of program attributes
void enable_depth_test() override
enable the depth test
void pop_window_transformation_array() override
restore previous viewport and depth range arrays defining the window transformations
shader_program & ref_default_shader_program(bool texture_support=false) override
return a reference to a shader program used to render without illumination
bool prepare_attributes(std::vector< vec3 > &P, std::vector< vec3 > &N, std::vector< vec2 > &T, unsigned nr_vertices, const float *vertices, const float *normals, const float *tex_coords, const int *vertex_indices, const int *normal_indices, const int *tex_coord_indices, bool flip_normals) const
helper function to prepare attribute arrays
gl_context()
construct context and attach signals
cgv::media::font::font_face_ptr get_info_font_face() const
return info font face and ensure that it is created
void set_color_mask(bvec4 flags) override
set the color buffer mask
void recover_from_external_frame_buffer_change(void *cgv_fbo_storage) override
restore cgv frame buffer to the state before the external change
dmat4 get_modelview_matrix() const override
return homogeneous 4x4 viewing matrix, which transforms from world to eye space
void set_material(const cgv::media::illum::surface_material &mat) override
set the current material
void enable_blending() override
enable blending
void set_bg_stencil(int s) override
set a user defined background stencil value
void recover_from_external_viewport_change(const ivec4 &cgv_viewport_storage) override
restore cgv viewport to the state before the external change
void set_modelview_matrix(const dmat4 &V) override
set the current modelview matrix, which transforms from world to eye space
double get_window_z(int x_window, int y_window) const override
read the device z-coordinate from the z-buffer for the given device x- and y-coordinates
dmat4 get_projection_matrix() const override
return homogeneous 4x4 projection matrix, which transforms from eye to clip space
void enumerate_program_uniforms(shader_program &prog, std::vector< std::string > &names, std::vector< int > *locations_ptr=0, std::vector< int > *sizes_ptr=0, std::vector< int > *types_ptr=0, bool show=false) const override
get list of program uniforms
virtual bool read_frame_buffer(data::data_view &dv, unsigned int x=0, unsigned int y=0, FrameBufferType buffer_type=FB_BACK, cgv::type::info::TypeId type=type::info::TI_UINT8, data::ComponentFormat cf=data::CF_RGB, int w=-1, int h=-1) override
implement according to specification in context class
void enable_material(textured_material &mat) override
enable a material with textures
float get_info_font_size() const
return info font size
void set_bg_depth(float d) override
set a user defined background depth value
cgv::media::font::font_face_ptr info_font_face
font used to draw textual info
Definition gl_context.h:145
void clear_background(bool color_flag, bool depth_flag, bool stencil_flag=false, bool accum_flag=false) override
clear the buffer contents of the flagged buffers to the set background colors
shader_program & ref_surface_shader_program(bool texture_support=false) override
return a reference to the default shader program used to render surfaces
void set_depth_range(const dvec2 &depth_range=dvec2(0, 1), int array_index=-1) override
set the current depth range or one of the depth ranges in the window transformation array
void draw_strip_or_fan(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 is_fan, bool flip_normals) const override
tesselate with one face strip
void set_blend_state(BlendState state) override
set the complete blend state
bool configure_gl()
ensure that glew is initialized, define lighting mode, viewing pyramid and the rendering mode and ret...
bool release_attributes(const float *normals, const float *tex_coords, const int *normal_indices, const int *tex_coord_indices) const
helper function to disable attribute arrays
float get_current_font_size() const override
overwrite function to return info font size in case no font is currently selected
void set_cull_state(CullingMode culling_mode) override
set the culling state
void draw_edges_of_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 override
pass geometry of given faces to current shader program and generate draw calls to render lines for th...
void set_projection_matrix(const dmat4 &P) override
set the current projection matrix, which transforms from eye to clip space
unsigned get_max_window_transformation_array_size() const override
query the maximum number of supported window transformations, which is at least 1
void set_bg_accum_color(vec4 rgba) override
set a user defined background color for the accumulation buffer
void disable_blending() override
disable blending
void rotate_vector_to_target(const dvec3 &vector, const dvec3 &target)
helper function that multiplies a rotation to modelview matrix such that vector is rotated onto targe...
void set_blend_func(BlendFunction src_factor, BlendFunction dst_factor) override
set the blend function
void set_viewport(const ivec4 &viewport, int array_index=-1) override
set the current viewport or one of the viewports in the window transformation array
void pop_pixel_coords() override
pop previously changed transformation matrices
void disable_material(textured_material &mat) override
disable a material with textures
void on_lights_changed() override
helper function to send light update events
void disable_depth_test() override
disable the depth test
void set_blend_func_separate(BlendFunction src_color_factor, BlendFunction dst_color_factor, BlendFunction src_alpha_factor, BlendFunction dst_alpha_factor) override
set the blend function separately for color and alpha
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) const override
tesselate with independent faces
void set_depth_test_state(DepthTestState state) override
set the depth test state
void draw_edges_of_strip_or_fan(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 is_fan, bool flip_normals=false) const override
pass geometry of given strip or fan to current shader program and generate draw calls to render lines...
void announce_external_frame_buffer_change(void *&cgv_fbo_storage) override
announce an external frame buffer change performed with rendering API to the cgv framework providing ...
base interface for all render components
Definition context.h:355
a shader program combines several shader code fragments to a complete definition of the shading pipel...
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 set_attribute(const context &ctx, const std::string &name, const T &value)
set constant default value of a vertex attribute by attribute name, if name does not specify an attri...
base interface for a texture
Definition context.h:386
the texture class encapsulates all functionality independent of the rendering api.
Definition texture.h:15
void set_component_format(const component_format &cf)
change component format and clear internal format
Definition texture.cxx:61
class that extends obj_material with the management of textures
a vertex buffer is an unstructured memory block on the GPU.
bool create(const context &ctx, size_t size_in_bytes)
create empty vertex buffer of size size given in bytes
void destruct(const context &ctx)
destruct the render buffer
bool replace(const context &ctx, size_t buffer_offset_in_bytes, const T *array_ptr, size_t nr_elements)
replace part (starting at byte offset buffer_offset_in_bytes) or whole vertex buffer content from nr_...
the base namespace holds the base hierarchy, support for plugin registration and signals
Definition action.cxx:4
data::ref_ptr< group, true > group_ptr
ref counted pointer to a node
Definition group.h:14
ComponentFormat
define standard formats, which should be used to avoid wrong assignment of component names
@ CF_S
depth component
@ CF_RGB
color format with two components R and G
@ CF_D
color format with components B, G, R and A
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...
namespace that holds the abstract gui interface
Definition vr_calib.cxx:10
void message(const std::string &_message)
tell the user something with a message box
Definition dialog.cxx:14
namespace for font support
Definition font.cxx:6
font_ptr default_font(bool mono_space)
return platform dependend default font
Definition font.cxx:57
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...
void read_texture(cgv::data::data_view &data, unsigned level)
read back a texture into a data view with the glGetTexImage command
void gl_set_material(const cgv::media::illum::phong_material &mat, MaterialSide ms, float alpha)
enable a material without textures
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
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
void set_gl_format(texture &tex, GLuint gl_format, const std::string &component_format_description)
set a very specific texture format. This should be called after the texture is constructed and before...
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
std::vector< int > get_context_creation_attrib_list(cgv::render::context_config &cc)
construct a 0 terminated list of context creation attribute definitions
GLuint get_gl_format(const texture &tex)
return the texture format used for a given texture. If called before texture has been created,...
RenderAPI
enumeration of rendering APIs which can be queried from the context
Definition context.h:124
CullingMode
different culling modes
Definition context.h:197
BlendFunction
different blend functions
Definition context.h:204
AccessType
different access types
Definition context.h:320
TextureFilter
different texture filter
Definition context.h:243
TextureWrap
different texture wrap modes
Definition context.h:227
FrameBufferType
different frame buffer types which can be combined together with or
Definition context.h:544
MaterialSide
different sides of a material
Definition context.h:182
ProgramVariableKind
enumerates different kinds of shader program variables
Definition context.h:89
VertexBufferUsage
Provides vertex buffer usage hints as defined in OpenGL.
Definition context.h:483
ShaderType
different shader types
Definition context.h:541
PrimitiveType
different primitive types
Definition context.h:279
VertexBufferType
Provides vertex buffer types to allow implicit binding.
Definition context.h:470
@ VBT_VERTICES
The buffer contains vertices and will be bound to GL_ARRAY_BUFFER.
Definition context.h:472
@ VBT_TEXTURE
The buffer contains texture data and will be bound to GL_TEXTURE_BUFFER.
Definition context.h:474
@ VBT_INDICES
The buffer contains indices and will be bound to GL_ELEMENT_ARRAY_BUFFER.
Definition context.h:473
@ VBT_ATOMIC_COUNTER
The buffer contains atomic counter and will be bound to GL_ATOMIC_COUNTER_BUFFER.
Definition context.h:478
@ VBT_STORAGE
The buffer contains arbitrary data and will be bound to GL_SHADER_STORAGE_BUFFER.
Definition context.h:477
@ VBT_UNIFORM
The buffer contains uniforms and will be bound to GL_UNIFORM_BUFFER.
Definition context.h:475
@ VBT_INDIRECT
The buffer contains indirect draw commands and will be bound to GL_DRAW_INDIRECT_BUFFER.
Definition context.h:479
@ VBT_FEEDBACK
The buffer is used for transform&feedback and will be bound to GL_TRANSFORM_FEEDBACK_BUFFER.
Definition context.h:476
BufferTypeBits
Bits for the selection of different buffer types.
Definition context.h:517
TextureType
different texture types
Definition context.h:255
RenderPassFlags
available flags that can be queried from the context and set for a new render pass
Definition context.h:147
@ RPF_CLEAR_ACCUM
whether to clear the accumulation buffer
Definition context.h:162
@ RPF_SET_MODELVIEW
whether to set default modelview matrix
Definition context.h:150
@ RPF_SET_MATERIAL
whether to define default material
Definition context.h:154
@ RPF_SET_CLEAR_DEPTH
whether to set the clear color
Definition context.h:168
@ RPF_SET_LIGHTS
whether to define default lights
Definition context.h:153
@ RPF_CLEAR_COLOR
whether to clear the color buffer
Definition context.h:159
@ RPF_CLEAR_STENCIL
whether to clear the depth buffer
Definition context.h:161
@ RPF_SET_CLEAR_STENCIL
whether to set the clear color
Definition context.h:169
@ RPF_ENABLE_MATERIAL
whether to enable material
Definition context.h:156
@ RPF_DRAWABLES_INIT_FRAME
whether to call the init_frame method of the drawables
Definition context.h:165
@ RPF_CLEAR_DEPTH
whether to clear the depth buffer
Definition context.h:160
@ RPF_SET_STATE_FLAGS
whether to set depth buffer and culling flags
Definition context.h:166
@ RPF_SET_PROJECTION
whether to set default projection matrix
Definition context.h:149
@ RPF_SET_CLEAR_ACCUM
whether to set the accumulation buffer clear color
Definition context.h:170
@ RPF_SET_CLEAR_COLOR
whether to set the clear color
Definition context.h:167
@ RPF_SET_LIGHTS_ON
whether to turn on default lights
Definition context.h:155
CompareFunction
different comparison functions used for depth testing or texture comparisons
Definition context.h:308
namespace for templates that provide type information
Definition type_access.h:9
const char * get_type_name(TypeId tid)
function that returns the name of a type specified through TypeId
Definition type_id.cxx:117
TypeId
ids for the different types and type constructs
Definition type_id.h:12
@ TI_INT16
signed integer stored in 8 bits
Definition type_id.h:20
@ TI_INT8
boolean
Definition type_id.h:19
@ TI_INT32
signed integer stored in 16 bits
Definition type_id.h:21
@ TI_FLT32
floating point type stored in 16 bits
Definition type_id.h:28
@ TI_UINT32
unsigned integer stored in 16 bits
Definition type_id.h:25
@ TI_UINT8
signed integer stored in 64 bits
Definition type_id.h:23
@ TI_BOOL
void
Definition type_id.h:18
@ TI_UINT16
unsigned integer stored in 8 bits
Definition type_id.h:24
@ TI_FLT64
floating point type stored in 32 bits
Definition type_id.h:29
namespace for compile time type information
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
char to_upper(char c)
convert char to upper case
Definition scan.cxx:106
bool is_element(char c, const std::string &s)
check if char c arises in string s
Definition scan.cxx:373
this header is dependency free
Definition print.h:11
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< double, 3 > dvec3
declare type of 3d double precision floating point vectors
Definition fvec.h:678
cgv::math::fvec< uint32_t, 3 > uvec3
declare type of 3d 32 bit unsigned integer vectors
Definition fvec.h:704
cgv::math::fvec< int32_t, 4 > ivec4
declare type of 4d 32 bit integer vectors
Definition fvec.h:700
cgv::math::fmat< double, 4, 4 > dmat4
declare type of 4x4 matrices
Definition fmat.h:471
cgv::math::fvec< float, 3 > vec3
declare type of 3d single precision floating point vectors
Definition fvec.h:671
Helper functions to process strings.
Stores properties of a phong brdf material.
Stores properties of a surface material.
color_type diffuse_reflectance
diffuse reflectance of surface, defaults to 0.5,0.5,0.5
color_type emission
emissive color component, defaults to 0,0,0
color_type specular_reflectance
specular color used to modulate specular reflection component, should be 1,1,1
float transparency
modulation for transparency, defaults to 0
float roughness
surface roughness in the range [0,1] (1/2 trace of symmetric 2x2 matrix for anisotropic case where di...
float ambient_occlusion
scalar factor to down scale ambient light, defaults to 1
Represents a blend state used to configure fragment blending.
Definition context.h:694
bool enabled
whether blending is enabled
Definition context.h:696
BlendFunction dst_color
the destination color (rgb) factor
Definition context.h:700
BlendFunction dst_alpha
the destination alpha factor
Definition context.h:704
BlendFunction src_alpha
the source alpha factor
Definition context.h:702
BlendFunction src_color
the source color (rgb) factor
Definition context.h:698
Represents a buffer mask used to mask depth and color buffer outputs.
Definition context.h:709
Represents a depth test state used to configure depth testing.
Definition context.h:686
bool enabled
whether the depth test is enabled
Definition context.h:688
CompareFunction test_func
the function used to compare depth values
Definition context.h:690
configuration object used to define context parameters that need to be set already at creation time
Definition context.h:572
int version_minor
default: -1 ... minor version of maximum supported OpenGL version
Definition context.h:601
int version_major
default: -1 ... major version of maximum supported OpenGL version
Definition context.h:599
bool debug
default: false in release and true in debug version
Definition context.h:605
bool forward_compatible
default: false
Definition context.h:603
bool core_profile
default: true
Definition context.h:607
bool depth_buffer
default: true
Definition context.h:576
int max_compute_shared_memory_size
the maximum number that can be provided to the max_vertices output layout qualifier in a geometry sha...
Definition context.h:44
ivec3 max_compute_work_group_count
the number of invocations in a single local work group (i.e., the product of the three dimensions) th...
Definition context.h:46
int max_compute_work_group_invocations
total available storage size in bytes for all shared variables in a compute shader
Definition context.h:45
int max_geometry_shader_output_vertex_count
the maximum supported size for renderbuffers in any dimension
Definition context.h:43
ivec3 max_compute_work_group_size
the maximum number of work groups that may be dispatched to a compute shader; dimension index 0,...
Definition context.h:47
bool on_enter_children(group *)
called before the children of a group node g are processed, return whether these should be skipped....
bool on_leave_children(group *)
called when the children of a group node g have been left, return whether to terminate traversal
structure to store information on a shader program variable, i.e.
Definition context.h:98
compact type description of data that can be sent to the context; convertible to int
Definition context.h:59