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
43 const int CONTEXT_FLAGS = WGL_CONTEXT_FLAGS_ARB;
44 const int CONTEXT_FORWARD_COMPATIBLE_BIT = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
45 const int CONTEXT_DEBUG_BIT = WGL_CONTEXT_DEBUG_BIT_ARB;
46 const int CONTEXT_MAJOR_VERSION = WGL_CONTEXT_MAJOR_VERSION_ARB;
47 const int CONTEXT_MINOR_VERSION = WGL_CONTEXT_MINOR_VERSION_ARB;
48 const int CONTEXT_PROFILE_MASK = WGL_CONTEXT_PROFILE_MASK_ARB;
49 const int CONTEXT_CORE_PROFILE_BIT = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
50 const int CONTEXT_COMPATIBILITY_PROFILE_BIT = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
51#else
52 const int CONTEXT_FLAGS = GLX_CONTEXT_FLAGS_ARB;
53 const int CONTEXT_FORWARD_COMPATIBLE_BIT = GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
54 const int CONTEXT_DEBUG_BIT = GLX_CONTEXT_DEBUG_BIT_ARB;
55 const int CONTEXT_MAJOR_VERSION = GLX_CONTEXT_MAJOR_VERSION_ARB;
56 const int CONTEXT_MINOR_VERSION = GLX_CONTEXT_MINOR_VERSION_ARB;
57 const int CONTEXT_PROFILE_MASK = GLX_CONTEXT_PROFILE_MASK_ARB;
58 const int CONTEXT_CORE_PROFILE_BIT = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
59 const int CONTEXT_COMPATIBILITY_PROFILE_BIT = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
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) {
74 attrib_list.push_back(CONTEXT_MAJOR_VERSION);
75 attrib_list.push_back(cc.version_major);
76 }
77 if (cc.version_minor >= 0) {
78 attrib_list.push_back(CONTEXT_MINOR_VERSION);
79 attrib_list.push_back(cc.version_minor);
80 }
81 if (version > 31) {
82 attrib_list.push_back(CONTEXT_PROFILE_MASK);
83 attrib_list.push_back(
84 cc.core_profile ? CONTEXT_CORE_PROFILE_BIT : CONTEXT_COMPATIBILITY_PROFILE_BIT);
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),
94 GL_POINTS,
95 GL_LINES,
96 GL_LINES_ADJACENCY,
97 GL_LINE_STRIP,
98 GL_LINE_STRIP_ADJACENCY,
99 GL_LINE_LOOP,
100 GL_TRIANGLES,
101 GL_TRIANGLES_ADJACENCY,
102 GL_TRIANGLE_STRIP,
103 GL_TRIANGLE_STRIP_ADJACENCY,
104 GL_TRIANGLE_FAN,
105 GL_QUADS,
106 GL_QUAD_STRIP,
107 GL_POLYGON,
108 GL_PATCHES
109 };
110 return gl_primitive_type[primitive_type];
111}
112
113GLenum map_to_gl(MaterialSide material_side)
114{
115 static const GLenum gl_material_side[] = {
116 GLenum(0),
117 GL_FRONT,
118 GL_BACK,
119 GL_FRONT_AND_BACK
120 };
121 return gl_material_side[material_side];
122}
123
124GLenum map_to_gl(AccessType access_type)
125{
126 static const GLenum gl_access_type[] = {
127 GL_READ_ONLY,
128 GL_WRITE_ONLY,
129 GL_READ_WRITE
130 };
131 return gl_access_type[access_type];
132}
133
134GLenum map_to_gl(BlendFunction blend_function)
135{
136 static const GLenum gl_blend_func[] = {
137 GL_ZERO,
138 GL_ONE,
139 GL_SRC_COLOR,
140 GL_ONE_MINUS_SRC_COLOR,
141 GL_DST_COLOR,
142 GL_ONE_MINUS_DST_COLOR,
143 GL_SRC_ALPHA,
144 GL_ONE_MINUS_SRC_ALPHA,
145 GL_DST_ALPHA,
146 GL_ONE_MINUS_DST_ALPHA,
147 GL_CONSTANT_COLOR,
148 GL_ONE_MINUS_CONSTANT_COLOR,
149 GL_CONSTANT_ALPHA,
150 GL_ONE_MINUS_CONSTANT_ALPHA,
151 GL_SRC_ALPHA_SATURATE,
152 GL_SRC1_COLOR,
153 GL_ONE_MINUS_SRC1_COLOR,
154 GL_SRC1_ALPHA,
155 GL_ONE_MINUS_SRC1_ALPHA
156 };
157 return gl_blend_func[blend_function];
158}
159
160GLenum map_to_gl(CompareFunction compare_func)
161{
162 static const GLenum gl_compare_func[] = {
163 GL_LEQUAL,
164 GL_GEQUAL,
165 GL_LESS,
166 GL_GREATER,
167 GL_EQUAL,
168 GL_NOTEQUAL,
169 GL_ALWAYS,
170 GL_NEVER
171 };
172 return gl_compare_func[compare_func];
173}
174
175static const GLenum gl_depth_format_ids[] =
176{
177 GL_DEPTH_COMPONENT,
178 GL_DEPTH_COMPONENT16,
179 GL_DEPTH_COMPONENT24,
180 GL_DEPTH_COMPONENT32
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
205GLenum get_tex_dim(TextureType texture_type)
206{
207 static const GLenum gl_texture_type[] = {
208 GLenum(0),
209 GL_TEXTURE_1D,
210 GL_TEXTURE_2D,
211 GL_TEXTURE_3D,
212 GL_TEXTURE_1D_ARRAY,
213 GL_TEXTURE_2D_ARRAY,
214 GL_TEXTURE_CUBE_MAP,
215 GL_TEXTURE_2D_MULTISAMPLE,
216 GL_TEXTURE_2D_MULTISAMPLE_ARRAY
217 };
218 return gl_texture_type[texture_type];
219}
220
221GLenum get_tex_bind(TextureType texture_type)
222{
223 static const GLenum gl_tex_binding[] = {
224 GLenum(0),
225 GL_TEXTURE_BINDING_1D,
226 GL_TEXTURE_BINDING_2D,
227 GL_TEXTURE_BINDING_3D,
228 GL_TEXTURE_BINDING_1D_ARRAY,
229 GL_TEXTURE_BINDING_2D_ARRAY,
230 GL_TEXTURE_BINDING_CUBE_MAP,
231 GL_TEXTURE_BUFFER,
232 GL_TEXTURE_BINDING_2D_MULTISAMPLE,
233 GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY
234 };
235 return gl_tex_binding[texture_type];
236}
237
238GLenum map_to_gl(TextureWrap texture_wrap)
239{
240 static const GLenum gl_texture_wrap[] = {
241 GL_REPEAT,
242 GL_CLAMP,
243 GL_CLAMP_TO_EDGE,
244 GL_CLAMP_TO_BORDER,
245 GL_MIRROR_CLAMP_EXT,
246 GL_MIRROR_CLAMP_TO_EDGE_EXT,
247 GL_MIRROR_CLAMP_TO_BORDER_EXT,
248 GL_MIRRORED_REPEAT
249 };
250 return gl_texture_wrap[texture_wrap];
251}
252
253GLenum map_to_gl(TextureFilter filter_type)
254{
255 static const GLenum gl_texture_filter[] = {
256 GL_NEAREST,
257 GL_LINEAR,
258 GL_NEAREST_MIPMAP_NEAREST,
259 GL_LINEAR_MIPMAP_NEAREST,
260 GL_NEAREST_MIPMAP_LINEAR,
261 GL_LINEAR_MIPMAP_LINEAR,
262 GL_LINEAR_MIPMAP_LINEAR
263 };
264 return gl_texture_filter[filter_type];
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
289void set_gl_format(texture& tex, GLuint gl_format, const std::string& component_format_description)
290{
291 tex.set_component_format(component_format_description);
292 (GLuint&)tex.internal_format = gl_format;
293}
294
296GLuint get_gl_format(const texture& tex)
297{
298 if (tex.internal_format)
299 return (const GLuint&)tex.internal_format;
301 GLuint gl_format = find_best_texture_format(tex, &best_cf);
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}
330
332{
333 if (info_font_face.empty()) {
334 font_ptr info_font = default_font(true);
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{
413 if (severity == GL_DEBUG_SEVERITY_NOTIFICATION)
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 }
428 const GLubyte* version_string = glGetString(GL_VERSION);
429 version_major = version_string[0] - '0';
430 version_minor = version_string[2] - '0';
431 if (version_major >= 3) {
432 GLint context_flags;
433 glGetIntegerv(GL_CONTEXT_FLAGS, &context_flags);
434 // weird behavior under windows or just nvidia or just my laptop (Stefan)??
435 debug = (context_flags & GL_CONTEXT_FLAG_DEBUG_BIT) != 0;
436 forward_compatible = (context_flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) != 0;
437 }
438 else {
439 debug = false;
440 forward_compatible = false;
441 }
442 int version = 10 * version_major + version_minor;
443 if (version >= 32) {
444 GLint context_profile;
445 glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &context_profile);
446#ifdef _DEBUG
447 if (context_profile != 0) {
448 if (core_profile != ((context_profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) == 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;
462 const GLubyte* vendor_c_string = glGetString(GL_VENDOR);
463 std::string vendor_string(reinterpret_cast<const char*>(vendor_c_string));
464 vendor_string = cgv::utils::to_upper(vendor_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);
475 glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &gpu_capabilities.max_geometry_shader_output_vertex_count);
476 glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gpu_capabilities.max_geometry_shader_output_component_count);
477 glGetIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &gpu_capabilities.max_geometry_shader_total_output_component_count);
478 glGetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &gpu_capabilities.max_compute_shared_memory_size);
479 glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &gpu_capabilities.max_compute_work_group_invocations);
480 for(unsigned i = 0; i < 3; ++i)
481 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, static_cast<GLuint>(i), &gpu_capabilities.max_compute_work_group_count[i]);
482 for(unsigned i = 0; i < 3; ++i)
483 glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, static_cast<GLuint>(i), &gpu_capabilities.max_compute_work_group_size[i]);
484
485#ifdef _DEBUG
486 std::cout << "OpenGL version " << version_major << "." << version_minor << (core_profile?" (core)":" (compatibility)") << (debug?" (debug)":"") << (forward_compatible?" (forward_compatible)":"") << std::endl;
487 const GLubyte* renderer_c_string = glGetString(GL_RENDERER);
488 const GLubyte* glslversion_c_string = glGetString(GL_SHADING_LANGUAGE_VERSION);
489 if (vendor_c_string)
490 std::cout << " vendor : " << vendor_c_string << std::endl;
491 if (renderer_c_string)
492 std::cout << " renderer : " << renderer_c_string << std::endl;
493 if (glslversion_c_string)
494 std::cout << " glslversion: " << glslversion_c_string << std::endl;
495#endif
496 if (debug) {
497 glEnable(GL_DEBUG_OUTPUT);
498 if (version >= 43) {
499 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
500 if (!check_gl_error("gl_context::configure() debug output"))
501 glDebugMessageCallback(debug_callback, this);
502 }
503 }
504 // use the eye location to compute the specular lighting
505 if (!core_profile) {
506 glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
507 // this makes opengl normalize all surface normals before lighting calculations,
508 // which is essential when using scaling to deform tesselated primities
509 glEnable(GL_NORMALIZE);
510
511 // should be initialized by the driver, but better be safe than risk errors later
512 glMatrixMode(GL_MODELVIEW);
513 }
515// if (check_gl_error("gl_context::configure_gl before init of children"))
516// return false;
517
518 group_ptr grp(dynamic_cast<group*>(this));
520 for (unsigned i = 0; i<grp->get_nr_children(); ++i)
521 traverser(sma, "nc").traverse(grp->get_child(i));
522
523// if (check_gl_error("gl_context::configure_gl after init of children."))
524// return false;
525
526 return true;
527}
528
529void gl_context::resize_gl()
530{
531 group_ptr grp(dynamic_cast<group*>(this));
533 if (grp) {
535 traverser(sma).traverse(grp);
536 }
537}
538
540 glClearColor(rgba[0], rgba[1], rgba[2], rgba[3]);
542}
543
545 glClearDepth(d);
547}
548
550 glClearStencil(s);
552}
553
555 if(!core_profile)
556 glClearAccum(rgba[0], rgba[1], rgba[2], rgba[3]);
558}
559
560void gl_context::clear_background(bool color_flag, bool depth_flag, bool stencil_flag, bool accum_flag) {
561 GLenum bits = 0;
562 if(color_flag)
563 bits |= GL_COLOR_BUFFER_BIT;
564 if(depth_flag)
565 bits |= GL_DEPTH_BUFFER_BIT;
566 if(stencil_flag)
567 bits |= GL_STENCIL_BUFFER_BIT;
568 if(accum_flag && !core_profile)
569 bits |= GL_ACCUM_BUFFER_BIT;
570 if(bits)
571 glClear(bits);
572}
573
576{
577 if (current_font_size == 0)
578 return get_info_font_size();
579 return current_font_size;
580}
581
588
589void gl_context::init_render_pass()
590{
591#ifdef WIN32
592 wglSwapIntervalEXT(enable_vsync ? 1 : 0);
593#else
594 glXSwapIntervalEXT(glXGetCurrentDisplay(), glXGetCurrentDrawable(), enable_vsync ? 1 : 0);
595#endif
597 glEnable(GL_FRAMEBUFFER_SRGB);
598 else
599 glDisable(GL_FRAMEBUFFER_SRGB);
600
601 static cgv::render::RenderPassFlags last_render_pass_flags = get_default_render_pass_flags();
602 cgv::render::RenderPassFlags current_render_pass_flags = get_render_pass_flags();
603 if (current_render_pass_flags & RPF_SET_LIGHTS) {
604 for (unsigned i = 0; i < nr_default_light_sources; ++i)
606
607 for (unsigned i = 0; i < nr_default_light_sources; ++i)
608 if (current_render_pass_flags & RPF_SET_LIGHTS_ON)
610 else
612 }
613 else if ((last_render_pass_flags & RPF_SET_LIGHTS) == 0) {
614 for (unsigned i = 0; i < nr_default_light_sources; ++i)
617 }
618 last_render_pass_flags = current_render_pass_flags;
619
622 }
624 // this mode allows to define the ambient and diffuse color of the surface material
625 // via the glColor commands
626 glEnable(GL_COLOR_MATERIAL);
627 }
629 // set some default settings
631 set_cull_state(CM_BACKFACE);
632 if (!core_profile)
633 glEnable(GL_NORMALIZE);
634 }
636 set_projection_matrix(cgv::math::perspective4<double>(45.0, (double)get_width()/get_height(),0.001,1000.0));
637
639 set_modelview_matrix(cgv::math::look_at4<double>(vec3(0,0,10), vec3(0,0,0), vec3(0,1,0)));
640
641 if (check_gl_error("gl_context::init_render_pass before init_frame"))
642 return;
643
644 group* grp = dynamic_cast<group*>(this);
646 single_method_action<drawable,void,cgv::render::context&> sma(*this, &drawable::init_frame, true, true);
647 traverser(sma).traverse(group_ptr(grp));
648 }
649
650 if (check_gl_error("gl_context::init_render_pass after init_frame"))
651 return;
652 // this defines the background color to which the frame buffer is set by glClear
655 // this defines the background depth buffer value set by glClear
658 // this defines the background depth buffer value set by glClear
661 // this defines the background color to which the accum buffer is set by glClear
669 );
670}
671
673void gl_context::finish_render_pass()
674{
675}
676
677struct format_callback_handler : public traverse_callback_handler
678{
679 std::ostream& os;
680 format_callback_handler(std::ostream& _os) : os(_os)
681 {
682 }
685 {
686 os << "\a";
687 return false;
688 }
689
691 {
692 os << "\b";
693 return false;
694 }
695
696};
697
698void gl_context::draw_textual_info()
699{
700 if (show_help || show_stats) {
701 rgba tmp = current_color;
704
707
708 set_cursor(20, get_height()-1-20);
709
710 vec4 bg = get_bg_color();
711 //if (bg_r + bg_g + bg_b < 1.5f)
712 if (bg[0] + bg[1] + bg[2] < 1.5f)
713 set_color(rgba(1, 1, 1, 1));
714 else
715 set_color(rgba(0, 0, 0, 1));
716
717 // traverse objects for show_stats callback
718 format_callback_handler fch(output_stream());
719 group_ptr grp(dynamic_cast<group*>(this));
720 if (grp && show_stats) {
722 traverser(sma, "nc").traverse(grp, &fch);
723 output_stream() << std::endl;
724 }
725 //if (bg_r + bg_g + bg_b < 1.5f)
726 if(bg[0] + bg[1] + bg[2] < 1.5f)
727 set_color(rgba(1, 1, 0, 1));
728 else
729 set_color(rgba(0.4f, 0.3f, 0, 1));
730
731 if (grp && show_help) {
732 // collect help from myself and all children
734 traverser(sma, "nc").traverse(grp, &fch);
735 output_stream().flush();
736 }
739 }
740}
741
742void gl_context::perform_screen_shot()
743{
744 glFlush();
745 data::data_view dv;
746 if (!read_frame_buffer(dv))
747 return;
748 std::string ext("bmp");
750 if (cgv::utils::is_element("png",exts))
751 ext = "png";
752 else if (cgv::utils::is_element("tif",exts))
753 ext = "tif";
754 cgv::media::image::image_writer wr(std::string("screen_shot.")+ext);
755 if (wr.is_format_supported(*dv.get_format()))
756 wr.write_image(dv);
757}
758
760void 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
761{
762 GLint count;
763 glGetProgramiv(get_gl_id(prog.handle), GL_ACTIVE_UNIFORMS, &count);
764 for (int i = 0; i < count; ++i) {
765 GLchar name[1000];
766 GLsizei length;
767 GLint size;
768 GLenum type;
769 glGetActiveUniform(get_gl_id(prog.handle), i, 1000, &length, &size, &type, name);
770 std::string name_str(name, length);
771 names.push_back(name_str);
772 if (sizes_ptr)
773 sizes_ptr->push_back(size);
774 if (types_ptr)
775 types_ptr->push_back(type);
776 int loc = glGetUniformLocation(get_gl_id(prog.handle), name_str.c_str());
777 if (locations_ptr)
778 locations_ptr->push_back(loc);
779 if (show)
780 std::cout << i << " at " << loc << " = " << name_str << ":" << type << "[" << size << "]" << std::endl;
781 }
782}
783
785void 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
786{
787 GLint count;
788 glGetProgramiv(get_gl_id(prog.handle), GL_ACTIVE_ATTRIBUTES, &count);
789 for (int i = 0; i < count; ++i) {
790 GLchar name[1000];
791 GLsizei length;
792 GLint size;
793 GLenum type;
794 glGetActiveAttrib(get_gl_id(prog.handle), i, 1000, &length, &size, &type, name);
795 std::string name_str(name, length);
796 names.push_back(name_str);
797 if (sizes_ptr)
798 sizes_ptr->push_back(size);
799 if (types_ptr)
800 types_ptr->push_back(type);
801 int loc = glGetAttribLocation(get_gl_id(prog.handle), name_str.c_str());
802 if (locations_ptr)
803 locations_ptr->push_back(loc);
804 if (show)
805 std::cout << i << " at " << loc << " = " << name_str << ":" << type << "[" << size << "]" << std::endl;
806 }
807}
808
811{
812 current_color = clr;
814 glColor4fv(&clr[0]);
815 }
816 if (shader_program_stack.empty())
817 return;
819 if (!prog.does_context_set_color())
820 return;
821 int clr_loc = prog.get_color_index();
822 if (clr_loc == -1)
823 return;
824 prog.set_attribute(*this, clr_loc, clr);
825}
826
829{
831 unsigned side = map_to_gl(MS_FRONT_AND_BACK);
832 float alpha = 1.0f - material.transparency;
833 gl_set_material_color(side, material.ambient_occlusion * material.diffuse_reflectance, alpha, GL_AMBIENT);
834 gl_set_material_color(side, material.diffuse_reflectance, alpha, GL_DIFFUSE);
835 gl_set_material_color(side, material.specular_reflectance, alpha, GL_SPECULAR);
836 gl_set_material_color(side, material.emission, alpha, GL_EMISSION);
837 glMaterialf(side, GL_SHININESS, 1.0f / (material.roughness + 1.0f / 128.0f));
838 }
839 context::set_material(material);
840}
841
844{
846 mat.enable_textures(*this);
847}
848
851{
852 mat.disable_textures(*this);
855}
856
857void gl_context::destruct_render_objects()
858{
859 for (unsigned i = 0; i < 4; ++i)
860 progs[i].destruct(*this);
861}
862
864shader_program& gl_context::ref_default_shader_program(bool texture_support)
865{
866 if (!texture_support) {
867 if (!progs[0].is_created()) {
868 if (!progs[0].build_program(*this, "default.glpr")) {
869 error("could not build default shader program from default.glpr");
870 exit(0);
871 }
872 progs[0].specify_standard_uniforms(true, false, false, true);
873 progs[0].specify_standard_vertex_attribute_names(*this, true, false, false);
874 progs[0].allow_context_to_set_color(true);
875 }
876 return progs[0];
877 }
878 if (!progs[1].is_created()) {
879 if (!progs[1].build_program(*this, "textured_default.glpr")) {
880 error("could not build default shader program with texture support from textured_default.glpr");
881 exit(0);
882 }
883 progs[1].set_uniform(*this, "texture", 0);
884 progs[1].specify_standard_uniforms(true, false, false, true);
885 progs[1].specify_standard_vertex_attribute_names(*this, true, false, true);
886 progs[1].allow_context_to_set_color(true);
887 }
888 return progs[1];
889}
890
892shader_program& gl_context::ref_surface_shader_program(bool texture_support)
893{
894 if (!texture_support) {
895 if (!progs[2].is_created()) {
896 if (!progs[2].build_program(*this, "default_surface.glpr")) {
897 error("could not build surface shader program from default_surface.glpr");
898 exit(0);
899 }
900 progs[2].specify_standard_uniforms(true, true, true, true);
901 progs[2].specify_standard_vertex_attribute_names(*this, true, true, false);
902 progs[2].allow_context_to_set_color(true);
903 }
904 return progs[2];
905 }
906 if (!progs[3].is_created()) {
907 if (!progs[3].build_program(*this, "textured_surface.glpr")) {
908 error("could not build surface shader program with texture support from textured_surface.glpr");
909 exit(0);
910 }
911 progs[3].specify_standard_uniforms(true, true, true, true);
912 progs[3].specify_standard_vertex_attribute_names(*this, true, true, true);
913 progs[3].allow_context_to_set_color(true);
914 }
915 return progs[3];
916}
917
919{
921 GLint max_nr_lights;
922 glGetIntegerv(GL_MAX_LIGHTS, &max_nr_lights);
923 for (GLint light_idx = 0; light_idx < max_nr_lights; ++light_idx) {
924 if (light_idx >= int(get_nr_enabled_light_sources())) {
925 glDisable(GL_LIGHT0 + light_idx);
926 continue;
927 }
928 GLfloat col[4] = { 1,1,1,1 };
930 *(rgb*)col = light.get_emission()*light.get_ambient_scale();
931 glLightfv(GL_LIGHT0 + light_idx, GL_AMBIENT, col);
932 *(rgb*)col = light.get_emission();
933 glLightfv(GL_LIGHT0 + light_idx, GL_DIFFUSE, col);
934 *(rgb*)col = light.get_emission();
935 glLightfv(GL_LIGHT0 + light_idx, GL_SPECULAR, col);
936
937 GLfloat pos[4] = { 0,0,0,light.get_type() == cgv::media::illum::LT_DIRECTIONAL ? 0.0f : 1.0f };
938 *(vec3*)pos = light.get_position();
939 glLightfv(GL_LIGHT0 + light_idx, GL_POSITION, pos);
940 if (light.get_type() != cgv::media::illum::LT_DIRECTIONAL) {
941 glLightf(GL_LIGHT0 + light_idx, GL_CONSTANT_ATTENUATION, light.get_constant_attenuation());
942 glLightf(GL_LIGHT0 + light_idx, GL_LINEAR_ATTENUATION, light.get_linear_attenuation());
943 glLightf(GL_LIGHT0 + light_idx, GL_QUADRATIC_ATTENUATION, light.get_quadratic_attenuation());
944 }
945 else {
946 glLightf(GL_LIGHT0 + light_idx, GL_CONSTANT_ATTENUATION, 1);
947 glLightf(GL_LIGHT0 + light_idx, GL_LINEAR_ATTENUATION, 0);
948 glLightf(GL_LIGHT0 + light_idx, GL_QUADRATIC_ATTENUATION, 0);
949 }
950 if (light.get_type() == cgv::media::illum::LT_SPOT) {
951 glLightf(GL_LIGHT0 + light_idx, GL_SPOT_CUTOFF, light.get_spot_cutoff());
952 glLightf(GL_LIGHT0 + light_idx, GL_SPOT_EXPONENT, light.get_spot_exponent());
953 glLightfv(GL_LIGHT0 + light_idx, GL_SPOT_DIRECTION, light.get_spot_direction().data());
954 }
955 else {
956 glLightf(GL_LIGHT0 + light_idx, GL_SPOT_CUTOFF, 180.0f);
957 glLightf(GL_LIGHT0 + light_idx, GL_SPOT_EXPONENT, 0.0f);
958 static float dir[3] = { 0,0,1 };
959 glLightfv(GL_LIGHT0 + light_idx, GL_SPOT_DIRECTION, dir);
960 }
961 glEnable(GL_LIGHT0 + light_idx);
962 }
963 }
965}
966
967void gl_context::tesselate_arrow(double length, double aspect, double rel_tip_radius, double tip_aspect, int res, bool edges)
968{
969 double cyl_radius = length*aspect;
970 double cone_radius = rel_tip_radius*cyl_radius;
971 double cone_length = cone_radius/tip_aspect;
972 double cyl_length = length - cone_length;
974 mul_modelview_matrix(cgv::math::scale4(cyl_radius,cyl_radius,0.5*cyl_length));
976 mul_modelview_matrix(cgv::math::rotate4(180.0,1.0,0.0,0.0));
977 tesselate_unit_disk(res, false, edges);
979
980 mul_modelview_matrix(cgv::math::translate4(0.0,0.0,1.0));
981 tesselate_unit_cylinder(res, false, edges);
982
983 mul_modelview_matrix(cgv::math::translate4(0.0, 0.0, 1.0));
984 mul_modelview_matrix(cgv::math::scale4(rel_tip_radius, rel_tip_radius, cone_length / cyl_length));
986 mul_modelview_matrix(cgv::math::rotate4(180.0, 1.0, 0.0, 0.0));
987 tesselate_unit_disk(res, false, edges);
989 mul_modelview_matrix(cgv::math::translate4(0.0, 0.0, 1.0));
990 tesselate_unit_cone(res, false, edges);
992}
993
995void gl_context::rotate_vector_to_target(const dvec3& vector, const dvec3& target)
996{
997 double angle;
998 dvec3 axis;
999 compute_rotation_axis_and_angle_from_vector_pair(vector, target, axis, angle);
1000 mul_modelview_matrix(cgv::math::rotate4<double>(180.0 / M_PI * angle, axis));
1001}
1002
1004void gl_context::tesselate_arrow(const dvec3& start, const dvec3& end, double aspect, double rel_tip_radius, double tip_aspect, int res, bool edges)
1005{
1006 if ((start - end).length() < 1e-8) {
1007 error("ignored tesselate arrow called with start and end closer then 1e-8");
1008 return;
1009 }
1011 mul_modelview_matrix(cgv::math::translate4<double>(start));
1012 rotate_vector_to_target(dvec3(0, 0, 1), end - start);
1013 tesselate_arrow((end-start).length(), aspect, rel_tip_radius, tip_aspect, res, edges);
1015}
1016
1017void gl_context::draw_light_source(const light_source& l, float i, float light_scale)
1018{
1019 set_color(i*l.get_emission());
1021 switch (l.get_type()) {
1022 case LT_DIRECTIONAL :
1023 mul_modelview_matrix(cgv::math::scale4<double>(light_scale, light_scale, light_scale));
1024 tesselate_arrow(vec3(0.0f), l.get_position(), 0.1f,2.0f,0.5f);
1025 break;
1026 case LT_POINT :
1028 cgv::math::translate4<double>(l.get_position())*
1029 cgv::math::scale4<double>(vec3(0.3f*light_scale)));
1031 break;
1032 case LT_SPOT :
1034 cgv::math::translate4<double>(l.get_position())*
1035 cgv::math::scale4<double>(vec3(light_scale))
1036 );
1037 rotate_vector_to_target(dvec3(0, 0, -1), l.get_spot_direction());
1038 {
1039 float t = tan(l.get_spot_cutoff()*(float)M_PI/180);
1040 if (l.get_spot_cutoff() > 45.0f)
1041 mul_modelview_matrix(cgv::math::scale4<double>(1, 1, 0.5f / t));
1042 else
1043 mul_modelview_matrix(cgv::math::scale4<double>(t, t, 0.5f));
1044 mul_modelview_matrix(cgv::math::translate4<double>(0, 0, -1));
1046 set_cull_state(CM_OFF);
1049 }
1050 }
1052}
1053
1055{
1056 if (frame_buffer_stack.empty()) {
1057 error("gl_context::announce_external_frame_buffer_change() called with empty frame buffer stack");
1058 return;
1059 }
1060 GLint fbo_id = 0;
1061 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fbo_id);
1062 fbo_handle = frame_buffer_stack.top()->handle;
1063 frame_buffer_stack.top()->handle = get_handle(fbo_id);
1064}
1065
1067{
1068 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(fbo_handle));
1069 if (frame_buffer_stack.empty())
1070 return;
1071 frame_buffer_stack.top()->handle = fbo_handle;
1072}
1073
1075{
1076 if (window_transformation_stack.empty()) {
1077 error("gl_context::announce_external_viewport_change() called with empty window transformation stack");
1078 return;
1079 }
1080 GLint vp[4];
1081 glGetIntegerv(GL_VIEWPORT, vp);
1082 cgv_viewport_storage = window_transformation_stack.top().front().viewport;
1083 window_transformation_stack.top().front().viewport = ivec4(vp[0], vp[1], vp[2], vp[3]);
1084}
1085
1087{
1088 glViewport(cgv_viewport_storage[0], cgv_viewport_storage[1], cgv_viewport_storage[2], cgv_viewport_storage[3]);
1089 if (window_transformation_stack.empty())
1090 return;
1091 window_transformation_stack.top().front().viewport = cgv_viewport_storage;
1092}
1093
1096{
1099
1100 GLint vp[4];
1101 glGetIntegerv(GL_VIEWPORT, vp);
1102
1104 // push projection matrix
1105 glMatrixMode(GL_PROJECTION);
1106 // set orthogonal projection
1107 glLoadIdentity();
1108 glOrtho(vp[0], vp[0]+vp[2], vp[1], vp[1]+vp[3], -1, 1);
1109 // push modelview matrix
1110 glMatrixMode(GL_MODELVIEW);
1111 // use identity for modelview
1112 glLoadIdentity();
1113 }
1114 set_modelview_matrix(cgv::math::identity4<double>());
1115 set_projection_matrix(cgv::math::ortho4<double>(vp[0], vp[0] + vp[2], vp[1], vp[1]+vp[3], -1, 1));
1116}
1117
1124
1127 unsigned int x, unsigned int y, FrameBufferType buffer_type,
1128 TypeId type, data::ComponentFormat cf, int w, int h)
1129{
1130 const cgv::data::data_format* df = dv.get_format();
1131 if (df) {
1132 w = int(df->get_width());
1133 h = int(df->get_height());
1134 type = df->get_component_type();
1136 if (w < 1 || h < 1) {
1137 error(std::string("read_frame_buffer: received invalid dimensions (") + cgv::utils::to_string(w) + "," + cgv::utils::to_string(h) + ")");
1138 return false;
1139 }
1140 }
1141 else {
1142 if (w < 1 || h < 1) {
1143 GLint vp[4];
1144 glGetIntegerv(GL_VIEWPORT,vp);
1145 w = w < 1 ? vp[2] : w;
1146 h = h < 1 ? vp[3] : h;
1147 }
1148 }
1149 GLuint gl_type = map_to_gl(type);
1150 if (gl_type == 0) {
1151 error(std::string("read_frame_buffer: could not make component type ")+cgv::type::info::get_type_name(df->get_component_type())+" to gl type");
1152 return false;
1153 }
1154 GLuint gl_format = GL_DEPTH_COMPONENT;
1155 if (cf != cgv::data::CF_D) {
1156 gl_format = GL_STENCIL_INDEX;
1157 if (cf != cgv::data::CF_S) {
1158 gl_format = map_to_gl(cf);
1159 if (gl_format == GL_RGB && cf != cgv::data::CF_RGB) {
1160 error(std::string("read_frame_buffer: could not match component format ") + cgv::utils::to_string(df->get_component_format()));
1161 return false;
1162 }
1163 }
1164 }
1165 GLenum gl_buffer = GL_BACK;
1166 if (buffer_type < FB_BACK)
1167 gl_buffer = GL_COLOR_ATTACHMENT0+buffer_type;
1168 else {
1169 switch (buffer_type) {
1170 case FB_FRONT : gl_buffer = GL_FRONT; break;
1171 case FB_BACK : gl_buffer = GL_BACK; break;
1172 case FB_FRONT_LEFT : gl_buffer = GL_FRONT_LEFT; break;
1173 case FB_FRONT_RIGHT : gl_buffer = GL_FRONT_RIGHT; break;
1174 case FB_BACK_LEFT : gl_buffer = GL_BACK_LEFT; break;
1175 case FB_BACK_RIGHT : gl_buffer = GL_BACK_RIGHT; break;
1176 default:
1177 error(std::string("invalid buffer type ")+cgv::utils::to_string(buffer_type));
1178 return false;
1179 }
1180 }
1181 // after all necessary information could be extracted, ensure that format
1182 // and data view are created
1183 if (!df) {
1184 df = new cgv::data::data_format(w,h,type,cf);
1185 dv.~data_view();
1186 new(&dv) data::data_view(df);
1187 dv.manage_format(true);
1188 }
1189 GLint old_buffer, old_pack;
1190 glGetIntegerv(GL_READ_BUFFER, &old_buffer);
1191 glGetIntegerv(GL_PACK_ALIGNMENT, &old_pack);
1192 glReadBuffer(gl_buffer);
1193 glPixelStorei(GL_PACK_ALIGNMENT, df->get_component_alignment());
1194 glReadPixels(x,y,w,h,gl_format,gl_type,dv.get_ptr<void>());
1195 glReadBuffer(old_buffer);
1196 glPixelStorei(GL_PACK_ALIGNMENT, old_pack);
1198 return true;
1199}
1200
1201
1202void render_vertex(int k, const float* vertices, const float* normals, const float* tex_coords,
1203 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices, bool flip_normals)
1204{
1205 if (normals && normal_indices) {
1206 if (flip_normals) {
1207 float n[3] = { -normals[3*normal_indices[k]],-normals[3*normal_indices[k]+1],-normals[3*normal_indices[k]+2] };
1208 glNormal3fv(n);
1209 }
1210 else
1211 glNormal3fv(normals+3*normal_indices[k]);
1212 }
1213 if (tex_coords && tex_coord_indices)
1214 glTexCoord2fv(tex_coords+2*tex_coord_indices[k]);
1215 glVertex3fv(vertices+3*vertex_indices[k]);
1216}
1217
1218attribute_array_binding*& get_aab_ptr()
1219{
1220 static attribute_array_binding* aab_ptr = 0;
1221 return aab_ptr;
1222}
1223
1224vertex_buffer*& get_vbo_ptr()
1225{
1226 static vertex_buffer* vbo_ptr = 0;
1227 return vbo_ptr;
1228}
1229
1230bool gl_context::release_attributes(const float* normals, const float* tex_coords, const int* normal_indices, const int* tex_coord_indices) const
1231{
1232 shader_program* prog_ptr = static_cast<shader_program*>(get_current_program());
1233 if (!prog_ptr || prog_ptr->get_position_index() == -1)
1234 return false;
1235
1236 attribute_array_binding*& aab_ptr = get_aab_ptr();
1237 if (!aab_ptr) {
1238 attribute_array_binding::disable_global_array(*this, prog_ptr->get_position_index());
1239 if (prog_ptr->get_normal_index() != -1 && normals && normal_indices)
1240 attribute_array_binding::disable_global_array(*this, prog_ptr->get_normal_index());
1241 if (prog_ptr->get_texcoord_index() != -1 && tex_coords && tex_coord_indices)
1242 attribute_array_binding::disable_global_array(*this, prog_ptr->get_texcoord_index());
1243 }
1244 else {
1245 aab_ptr->disable(const_cast<gl_context&>(*this));
1246 aab_ptr->disable_array(*this, prog_ptr->get_position_index());
1247 if (prog_ptr->get_normal_index() != -1 && normals && normal_indices)
1248 aab_ptr->disable_global_array(*this, prog_ptr->get_normal_index());
1249 if (prog_ptr->get_texcoord_index() != -1 && tex_coords && tex_coord_indices)
1250 aab_ptr->disable_global_array(*this, prog_ptr->get_texcoord_index());
1251 vertex_buffer*& vbo_ptr = get_vbo_ptr();
1252 vbo_ptr->destruct(*this);
1253 delete vbo_ptr;
1254 vbo_ptr = 0;
1255 }
1256 return true;
1257}
1258
1259bool gl_context::prepare_attributes(std::vector<vec3>& P, std::vector<vec3>& N, std::vector<vec2>& T, unsigned nr_vertices,
1260 const float* vertices, const float* normals, const float* tex_coords,
1261 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices, bool flip_normals) const
1262{
1263 unsigned i;
1264 shader_program* prog_ptr = static_cast<shader_program*>(get_current_program());
1265 if (!prog_ptr || prog_ptr->get_position_index() == -1)
1266 return false;
1267 P.resize(nr_vertices);
1268 for (i = 0; i < nr_vertices; ++i)
1269 P[i] = *reinterpret_cast<const vec3*>(vertices + 3 * vertex_indices[i]);
1270
1271 if (prog_ptr->get_normal_index() != -1 && normals && normal_indices) {
1272 N.resize(nr_vertices);
1273 for (i = 0; i < nr_vertices; ++i) {
1274 N[i] = *reinterpret_cast<const vec3*>(normals + 3 * normal_indices[i]);
1275 if (flip_normals)
1276 N[i] = -N[i];
1277 }
1278 }
1279 if (prog_ptr->get_texcoord_index() != -1 && tex_coords && tex_coord_indices) {
1280 T.resize(nr_vertices);
1281 for (i = 0; i < nr_vertices; ++i)
1282 T[i] = *reinterpret_cast<const vec2*>(tex_coords + 2 * tex_coord_indices[i]);
1283 }
1284
1285 attribute_array_binding*& aab_ptr = get_aab_ptr();
1286 if (core_profile && !aab_ptr) {
1287 aab_ptr = new attribute_array_binding();
1288 aab_ptr->create(*this);
1289 }
1290 if (!aab_ptr) {
1291 attribute_array_binding::set_global_attribute_array<>(*this, prog_ptr->get_position_index(), P);
1292 attribute_array_binding::enable_global_array(*this, prog_ptr->get_position_index());
1293 if (prog_ptr->get_normal_index() != -1) {
1294 if (normals && normal_indices) {
1295 attribute_array_binding::set_global_attribute_array<>(*this, prog_ptr->get_normal_index(), N);
1296 attribute_array_binding::enable_global_array(*this, prog_ptr->get_normal_index());
1297 }
1298 else
1299 attribute_array_binding::disable_global_array(*this, prog_ptr->get_normal_index());
1300 }
1301 if (prog_ptr->get_texcoord_index() != -1) {
1302 if (tex_coords && tex_coord_indices) {
1303 attribute_array_binding::set_global_attribute_array<>(*this, prog_ptr->get_texcoord_index(), T);
1304 attribute_array_binding::enable_global_array(*this, prog_ptr->get_texcoord_index());
1305 }
1306 else
1307 attribute_array_binding::disable_global_array(*this, prog_ptr->get_texcoord_index());
1308 }
1309 }
1310 else {
1311 vertex_buffer*& vbo_ptr = get_vbo_ptr();
1312 if (!vbo_ptr)
1313 vbo_ptr = new vertex_buffer();
1314 else
1315 vbo_ptr->destruct(*this);
1316 vbo_ptr->create(*this, P.size() * sizeof(vec3) + N.size() * sizeof(vec3) + T.size() * sizeof(vec2));
1317 vbo_ptr->replace(const_cast<gl_context&>(*this), 0, P.data(), P.size());
1318 size_t nml_off = P.size() * sizeof(vec3);
1319 size_t tex_off = nml_off;
1320 if (!N.empty()) {
1321 vbo_ptr->replace(const_cast<gl_context&>(*this), nml_off, N.data(), N.size());
1322 tex_off += N.size() * sizeof(vec3);
1323 }
1324 if (!T.empty())
1325 vbo_ptr->replace(const_cast<gl_context&>(*this), tex_off, T.data(), T.size());
1326
1327 type_descriptor td3 = element_descriptor_traits<vec3>::get_type_descriptor(P.front());
1328 aab_ptr->set_attribute_array(*this, prog_ptr->get_position_index(), td3, *vbo_ptr, 0, P.size());
1329 aab_ptr->enable_array(*this, prog_ptr->get_position_index());
1330 if (prog_ptr->get_normal_index() != -1) {
1331 if (normals && normal_indices) {
1332 aab_ptr->set_attribute_array(*this, prog_ptr->get_normal_index(), td3, *vbo_ptr, nml_off, N.size());
1333 aab_ptr->enable_array(*this, prog_ptr->get_normal_index());
1334 }
1335 else
1336 aab_ptr->disable_array(*this, prog_ptr->get_normal_index());
1337 }
1338 if (prog_ptr->get_texcoord_index() != -1) {
1339 if (tex_coords && tex_coord_indices) {
1340 type_descriptor td2 = element_descriptor_traits<vec2>::get_type_descriptor(T.front());
1341 aab_ptr->set_attribute_array(*this, prog_ptr->get_texcoord_index(), td2, *vbo_ptr, tex_off, T.size());
1342 aab_ptr->enable_array(*this, prog_ptr->get_texcoord_index());
1343 }
1344 else
1345 aab_ptr->disable_array(*this, prog_ptr->get_texcoord_index());
1346 }
1347 aab_ptr->enable(const_cast<gl_context&>(*this));
1348 }
1349 return true;
1350}
1351
1354 const float* vertices, const float* normals, const float* tex_coords,
1355 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices,
1356 int nr_faces, int face_degree, bool flip_normals) const
1357{
1359 int k = 0;
1360 for (int i = 0; i < nr_faces; ++i) {
1361 glBegin(GL_LINE_LOOP);
1362 for (int j = 0; j < face_degree; ++j, ++k)
1363 render_vertex(k, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1364 glEnd();
1365 }
1366 return;
1367 }
1368 unsigned nr_vertices = face_degree * nr_faces;
1369 std::vector<vec3> P, N;
1370 std::vector<vec2> T;
1371 if (!prepare_attributes(P, N, T, nr_vertices, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals))
1372 return;
1373 for (int i = 0; i < nr_faces; ++i)
1374 glDrawArrays(GL_LINE_LOOP, i*face_degree, face_degree);
1375 release_attributes(normals, tex_coords, normal_indices, tex_coord_indices);
1376}
1377
1378
1379void gl_context::draw_elements_void(GLenum mode, size_t total_count, GLenum type, size_t type_size, const void* indices) const
1380{
1381 ensure_configured();
1382 size_t drawn = 0;
1383 const cgv::type::uint8_type* index_ptr = static_cast<const cgv::type::uint8_type*>(indices);
1384 while (drawn < total_count) {
1385 size_t count = total_count - drawn;
1386 if (count > max_nr_indices)
1387 count = size_t(max_nr_indices);
1388 glDrawElements(mode, GLsizei(count), type, index_ptr + drawn * type_size);
1389 drawn += count;
1390 }
1391}
1392
1393size_t max_nr_indices, max_nr_vertices;
1394void gl_context::ensure_configured() const
1395{
1396 if (max_nr_indices != 0)
1397 return;
1398 glGetInteger64v(GL_MAX_ELEMENTS_INDICES, reinterpret_cast<GLint64*>(&max_nr_indices));
1399 glGetInteger64v(GL_MAX_ELEMENTS_VERTICES, reinterpret_cast<GLint64*>(&max_nr_vertices));
1400}
1401
1404 const float* vertices, const float* normals, const float* tex_coords,
1405 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices,
1406 int nr_faces, int face_degree, bool is_fan, bool flip_normals) const
1407{
1408 int s = face_degree - 2;
1409 int i, k = 2;
1410 std::vector<GLuint> I;
1411 I.push_back(0); I.push_back(1);
1412 for (i = 0; i < nr_faces; ++i) {
1413 if (is_fan) {
1414 I.push_back(k - 1); I.push_back(k);
1415 I.push_back(0); I.push_back(k);
1416 continue;
1417 }
1418 if (s == 1) {
1419 I.push_back(k - 1); I.push_back(k);
1420 I.push_back(k - 2); I.push_back(k);
1421 }
1422 else {
1423 I.push_back(k - 1); I.push_back(k + 1);
1424 I.push_back(k - 2); I.push_back(k);
1425 I.push_back(k); I.push_back(k + 1);
1426 }
1427 k += 2;
1428 }
1429
1431 glBegin(GL_LINES);
1432 for (GLuint j:I)
1433 render_vertex(j, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1434 glEnd();
1435 return;
1436 }
1437 unsigned nr_vertices = 2 + (face_degree - 2) * nr_faces;
1438 std::vector<vec3> P, N;
1439 std::vector<vec2> T;
1440 if (!prepare_attributes(P, N, T, nr_vertices, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals))
1441 return;
1442 draw_elements(GL_LINES, I.size(), &I[0]);
1443 release_attributes(normals, tex_coords, normal_indices, tex_coord_indices);
1444}
1445
1447 const float* vertices, const float* normals, const float* tex_coords,
1448 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices,
1449 int nr_faces, int face_degree, bool flip_normals) const
1450{
1452 int k = 0;
1453 if (face_degree < 5)
1454 glBegin(face_degree == 3 ? GL_TRIANGLES : GL_QUADS);
1455 for (int i = 0; i < nr_faces; ++i) {
1456 if (face_degree >= 5)
1457 glBegin(GL_POLYGON);
1458 for (int j = 0; j < face_degree; ++j, ++k)
1459 render_vertex(k, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1460 if (face_degree >= 5)
1461 glEnd();
1462 }
1463 if (face_degree < 5)
1464 glEnd();
1465 return;
1466 }
1467 unsigned nr_vertices = face_degree * nr_faces;
1468 std::vector<vec3> P, N;
1469 std::vector<vec2> T;
1470 if (!prepare_attributes(P, N, T, nr_vertices, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals))
1471 return;
1472 /*
1473 for (unsigned x = 0; x < nr_vertices; ++x) {
1474 std::cout << x << ": [" << P[x] << "]";
1475 if (N.size() > 0)
1476 std::cout << ", <" << N[x] << ">";
1477 if (T.size() > 0)
1478 std::cout << ", {" << T[x] << "}";
1479 std::cout << std::endl;
1480 }
1481 */
1482 if (face_degree == 3)
1483 glDrawArrays(GL_TRIANGLES, 0, nr_vertices);
1484 else {
1485 for (int i = 0; i < nr_faces; ++i) {
1486 glDrawArrays(GL_TRIANGLE_FAN, i*face_degree, face_degree);
1487 }
1488 }
1489 release_attributes(normals, tex_coords, normal_indices, tex_coord_indices);
1490}
1491
1493 const float* vertices, const float* normals, const float* tex_coords,
1494 const int* vertex_indices, const int* normal_indices, const int* tex_coord_indices,
1495 int nr_faces, int face_degree, bool is_fan, bool flip_normals) const
1496{
1497 int s = face_degree - 2;
1498 int k = 2;
1500 glBegin(face_degree == 3 ? (is_fan ? GL_TRIANGLE_FAN : GL_TRIANGLE_STRIP) : GL_QUAD_STRIP);
1501 render_vertex(0, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1502 render_vertex(1, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1503 for (int i = 0; i < nr_faces; ++i)
1504 for (int j = 0; j < s; ++j, ++k)
1505 render_vertex(k, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals);
1506 glEnd();
1507 return;
1508 }
1509 unsigned nr_vertices = 2 + (face_degree-2) * nr_faces;
1510 std::vector<vec3> P, N;
1511 std::vector<vec2> T;
1512 if (!prepare_attributes(P, N, T, nr_vertices, vertices, normals, tex_coords, vertex_indices, normal_indices, tex_coord_indices, flip_normals))
1513 return;
1514 glDrawArrays(is_fan ? GL_TRIANGLE_FAN : GL_TRIANGLE_STRIP, 0, nr_vertices);
1515 release_attributes(normals, tex_coords, normal_indices, tex_coord_indices);
1516}
1517
1519 if(state.enabled)
1520 glEnable(GL_DEPTH_TEST);
1521 else
1522 glDisable(GL_DEPTH_TEST);
1523 glDepthFunc(map_to_gl(state.test_func));
1525}
1526
1528 glDepthFunc(map_to_gl(func));
1530}
1531
1533 glEnable(GL_DEPTH_TEST);
1535}
1536
1538 glDisable(GL_DEPTH_TEST);
1540}
1541
1543 switch(culling_mode) {
1544 case CM_OFF:
1545 glDisable(GL_CULL_FACE);
1546 break;
1547 case CM_BACKFACE:
1548 glEnable(GL_CULL_FACE);
1549 glCullFace(GL_BACK);
1550 break;
1551 case CM_FRONTFACE:
1552 glEnable(GL_CULL_FACE);
1553 glCullFace(GL_FRONT);
1554 break;
1555 default:
1556 break;
1557 }
1558 context::set_cull_state(culling_mode);
1559}
1560
1562 if(state.enabled)
1563 glEnable(GL_BLEND);
1564 else
1565 glDisable(GL_BLEND);
1566 if(GLEW_EXT_blend_func_separate) {
1567 glBlendFuncSeparate(
1568 map_to_gl(state.src_color),
1569 map_to_gl(state.dst_color),
1570 map_to_gl(state.src_alpha),
1571 map_to_gl(state.dst_alpha)
1572 );
1573 } else {
1574 glBlendFunc(map_to_gl(state.src_color), map_to_gl(state.dst_color));
1575 }
1577}
1578
1580 glBlendFunc(map_to_gl(src_factor), map_to_gl(dst_factor));
1581 context::set_blend_func(src_factor, dst_factor);
1582}
1583
1584void gl_context::set_blend_func_separate(BlendFunction src_color_factor, BlendFunction dst_color_factor, BlendFunction src_alpha_factor, BlendFunction dst_alpha_factor) {
1585 glBlendFuncSeparate(
1586 map_to_gl(src_color_factor),
1587 map_to_gl(dst_color_factor),
1588 map_to_gl(src_alpha_factor),
1589 map_to_gl(dst_alpha_factor)
1590 );
1591 context::set_blend_func_separate(src_color_factor, dst_color_factor, src_alpha_factor, dst_alpha_factor);
1592}
1593
1595 glEnable(GL_BLEND);
1597}
1598
1600 glDisable(GL_BLEND);
1602}
1603
1605 glDepthMask(map_to_gl(mask.depth_flag));
1606 glColorMask(
1607 map_to_gl(mask.red_flag),
1608 map_to_gl(mask.green_flag),
1609 map_to_gl(mask.blue_flag),
1610 map_to_gl(mask.alpha_flag)
1611 );
1613}
1614
1616 glDepthMask(map_to_gl(flag));
1618}
1619
1621 glColorMask(
1622 map_to_gl(flags[0]),
1623 map_to_gl(flags[1]),
1624 map_to_gl(flags[2]),
1625 map_to_gl(flags[3])
1626 );
1628}
1629
1632{
1634 GLdouble V[16];
1635 glGetDoublev(GL_MODELVIEW_MATRIX, V);
1636 return dmat4(4,4,V);
1637 }
1638 if (modelview_matrix_stack.empty())
1639 return identity4<double>();
1640 return modelview_matrix_stack.top();
1641}
1642
1645{
1647 GLdouble P[16];
1648 glGetDoublev(GL_PROJECTION_MATRIX, P);
1649 return dmat4(4,4,P);
1650 }
1651 if (projection_matrix_stack.empty())
1652 return identity4<double>();
1653 return projection_matrix_stack.top();
1654}
1655
1657{
1659 update_window_transformation_array();
1660}
1661
1662void gl_context::update_window_transformation_array()
1663{
1664 const std::vector<window_transformation>& wta = window_transformation_stack.top();
1665 if (wta.size() == 1) {
1666 const ivec4& viewport = wta.front().viewport;
1667 const dvec2& depth_range = wta.front().depth_range;
1668 glViewport(viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1669 glScissor(viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1670 glDepthRange(depth_range[0], depth_range[1]);
1671 }
1672 else {
1673 for (GLuint array_index = 0; array_index < (GLuint)wta.size(); ++array_index) {
1674 const ivec4& viewport = wta[array_index].viewport;
1675 const dvec2& depth_range = wta[array_index].depth_range;
1676 glViewportIndexedf(array_index, (GLfloat)viewport[0], (GLfloat)viewport[1], (GLfloat)viewport[2], (GLfloat)viewport[3]);
1677 glScissorIndexed(array_index, viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1678 glDepthRangeIndexed(array_index, (GLclampd)depth_range[0], (GLclampd)depth_range[1]);
1679 }
1680 }
1681}
1682
1684{
1685 GLint max_value = 1;
1686 if (GLEW_VERSION_4_1)
1687 glGetIntegerv(GL_MAX_VIEWPORTS, &max_value);
1688 return max_value;
1689}
1690
1692void gl_context::set_viewport(const ivec4& viewport, int array_index)
1693{
1694 size_t nr = window_transformation_stack.top().size();
1695 context::set_viewport(viewport, array_index);
1696 if (nr != window_transformation_stack.top().size())
1697 update_window_transformation_array();
1698 else {
1699 if (array_index < 1) {
1700 glViewport(viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1701 glScissor(viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1702 }
1703 else {
1704 glViewportIndexedf(array_index, (GLfloat)viewport[0], (GLfloat)viewport[1], (GLfloat)viewport[2], (GLfloat)viewport[3]);
1705 glScissorIndexed(array_index, viewport[0], viewport[1], (GLsizei)viewport[2], (GLsizei)viewport[3]);
1706 }
1707 }
1708}
1709
1711void gl_context::set_depth_range(const dvec2& depth_range, int array_index)
1712{
1713 size_t nr = window_transformation_stack.top().size();
1714 context::set_depth_range(depth_range, array_index);
1715 if (nr != window_transformation_stack.top().size())
1716 update_window_transformation_array();
1717 else {
1718 if (array_index < 1)
1719 glDepthRange(depth_range[0], depth_range[1]);
1720 else
1721 glDepthRangeIndexed(array_index, (GLclampd)depth_range[0], (GLclampd)depth_range[1]);
1722 }
1723}
1724/*
1726gl_context::dmat4 gl_context::get_device_matrix() const
1727{
1728 GLint vp[4];
1729 glGetIntegerv(GL_VIEWPORT, vp);
1730 dmat4 D; D.zeros();
1731 D(0, 0) = 0.5*vp[2];
1732 D(0, 3) = 0.5*vp[2] + vp[0];
1733 D(1, 1) = -0.5*vp[3]; // flip y-coordinate
1734 D(1, 3) = get_height() - 0.5*vp[3] - vp[1];
1735 D(2, 2) = 0.5;
1736 D(2, 3) = 0.5;
1737 D(3, 3) = 1.0;
1738 return D;
1739}
1740*/
1742{
1744 GLint mm;
1745 glGetIntegerv(GL_MATRIX_MODE, &mm);
1746 glMatrixMode(GL_MODELVIEW);
1747 glLoadMatrixd(V.data());
1748 glMatrixMode(mm);
1749 }
1751}
1752
1754{
1756 GLint mm;
1757 glGetIntegerv(GL_MATRIX_MODE, &mm);
1758 glMatrixMode(GL_PROJECTION);
1759 glLoadMatrixd(P.data());
1760 glMatrixMode(mm);
1761 }
1763}
1764
1766double gl_context::get_window_z(int x_window, int y_window) const
1767{
1768 GLfloat z_window;
1769
1770 if (!in_render_process() && !is_current())
1771 make_current();
1772
1773 glReadPixels(x_window, y_window, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z_window);
1774 /*
1775 GLenum err = glGetError();
1776 if (err != GL_NO_ERROR) {
1777 std::cout << "gl error:";
1778 switch (err) {
1779 case GL_INVALID_ENUM : std::cout << "invalid enum"; break;
1780 case GL_INVALID_VALUE : std::cout << "invalid value"; break;
1781 case GL_INVALID_OPERATION : std::cout << "invalid operation"; break;
1782 case GL_STACK_OVERFLOW : std::cout << "stack overflow"; break;
1783 case GL_STACK_UNDERFLOW : std::cout << "stack underflow"; break;
1784 case GL_OUT_OF_MEMORY : std::cout << "out of memory"; break;
1785 default: std::cout << "unknown error"; break;
1786 }
1787 std::cout << std::endl;
1788
1789 }
1790 */
1791 return z_window;
1792}
1793
1794#include <iomanip>
1795cgv::data::component_format gl_context::texture_find_best_format(
1796 const cgv::data::component_format& cf,
1797 render_component& rc, const std::vector<cgv::data::data_view>* palettes) const
1798{
1799 GLuint& gl_format = (GLuint&)rc.internal_format;
1801 if (debug_texture_format_matching)
1802 std::cout << "Texture Format Search for '" << cf << "':" << std::endl;
1803 gl_format = find_best_texture_format(cf, &best_cf, palettes, debug_texture_format_matching);
1804 if (debug_texture_format_matching)
1805 std::cout << "found: '" << best_cf << "' = " << std::hex << gl_format << std::endl;
1806 return best_cf;
1807}
1808
1809std::string gl_error_to_string(GLenum eid) {
1810 switch (eid) {
1811 case GL_NO_ERROR: return "";
1812 case GL_INVALID_ENUM: return "invalid enum";
1813 case GL_INVALID_VALUE: return "invalid value";
1814 case GL_INVALID_OPERATION: return "invalid operation";
1815 case GL_INVALID_FRAMEBUFFER_OPERATION: return "invalid framebuffe";
1816 case GL_OUT_OF_MEMORY: return "out of memory";
1817 case GL_STACK_UNDERFLOW: return "stack underflow";
1818 case GL_STACK_OVERFLOW: return "stack overflow";
1819 default:
1820 return "undefined error (id: " + std::to_string(eid) + ")";
1821 }
1822 //return std::string((const char*)gluErrorString(eid));
1823}
1824
1825std::string gl_error() {
1826 GLenum eid = glGetError();
1827 // Clear potential other error flags, see https://registry.khronos.org/OpenGL-Refpages/gl4/html/glGetError.xhtml:
1828 // "glGetError should always be called in a loop, until it returns GL_NO_ERROR, if all error flags are to be reset."
1829 while (glGetError());
1830 return gl_error_to_string(eid);
1831}
1832
1833bool gl_context::check_gl_error(const std::string& where, const cgv::render::render_component* rc) const
1834{
1835 GLenum eid = glGetError();
1836 if (eid == GL_NO_ERROR)
1837 return false;
1838 std::string error_string = where + ": " + gl_error_to_string(eid);
1839 error(error_string, rc);
1840 while (glGetError()); // Clear all error flags, see gl_error.
1841 return true;
1842}
1843
1844bool gl_context::check_texture_support(TextureType tt, const std::string& where, const cgv::render::render_component* rc) const
1845{
1846 switch (tt) {
1847 case TT_3D:
1848 if (!GLEW_VERSION_1_2) {
1849 error(where + ": 3D texture not supported", rc);
1850 return false;
1851 }
1852 break;
1853 case TT_CUBEMAP:
1854 if (!GLEW_VERSION_1_3) {
1855 error(where + ": cubemap texture not supported", rc);
1856 return false;
1857 }
1858 default:
1859 break;
1860 }
1861 return true;
1862}
1863
1864bool gl_context::check_shader_support(ShaderType st, const std::string& where, const cgv::render::render_component* rc) const
1865{
1866 switch (st) {
1867 case ST_TASK:
1868 case ST_MESH:
1869 if(GLEW_VERSION_4_5) {
1870 if(GLEW_NV_mesh_shader || GLEW_EXT_mesh_shader)
1871 return true;
1872 else {
1873 error(where + ": task and mesh shaders require support of the GL_NV_mesh_shader or GLSL_EXT_mesh_shader extensions", rc);
1874 return false;
1875 }
1876 } else {
1877 error(where + ": task and mesh shaders are only supported starting from OpenGL version 4.5", rc);
1878 return false;
1879 }
1880 case ST_COMPUTE:
1881 if (GLEW_VERSION_4_3)
1882 return true;
1883 else {
1884 error(where+": compute shaders are only supported starting from OpenGL version 4.3", rc);
1885 return false;
1886 }
1887 case ST_TESS_CONTROL:
1888 case ST_TESS_EVALUATION:
1889 if (GLEW_VERSION_4_0)
1890 return true;
1891 else {
1892 error(where+": tessellation shaders are only supported starting from OpenGL version 4.0", rc);
1893 return false;
1894 }
1895 case ST_GEOMETRY:
1896 if (GLEW_VERSION_3_2)
1897 return true;
1898 else {
1899 error(where + ": geometry shaders are only supported starting from OpenGL version 3.2", rc);
1900 return false;
1901 }
1902 default:
1903 if (GLEW_VERSION_2_0)
1904 return true;
1905 else {
1906 error(where + ": shaders are only supported starting from OpenGL version 2.0", rc);
1907 return false;
1908 }
1909 }
1910}
1911
1912bool gl_context::check_fbo_support(const std::string& where, const cgv::render::render_component* rc) const
1913{
1914 if (!GLEW_VERSION_3_0) {
1915 error(where + ": framebuffer objects not supported", rc);
1916 return false;
1917 }
1918 return true;
1919}
1920
1921GLuint gl_context::texture_generate(texture_base& tb) const
1922{
1923 if (!check_texture_support(tb.tt, "gl_context::texture_generate", &tb))
1924 return get_gl_id(0);
1925 GLuint tex_id = get_gl_id(0);
1926 glGenTextures(1, &tex_id);
1927 if (glGetError() == GL_INVALID_OPERATION)
1928 error("gl_context::texture_generate: attempt to create texture inside glBegin-glEnd-block", &tb);
1929 return tex_id;
1930}
1931
1932GLuint gl_context::texture_bind(TextureType tt, GLuint tex_id) const
1933{
1934 GLint tmp_id;
1935 glGetIntegerv(get_tex_bind(tt), &tmp_id);
1936 glBindTexture(get_tex_dim(tt), tex_id);
1937 return tmp_id;
1938}
1939
1940void gl_context::texture_unbind(TextureType tt, GLuint tmp_id) const
1941{
1942 glBindTexture(get_tex_dim(tt), tmp_id);
1943}
1944
1945bool gl_context::texture_create(texture_base& tb, cgv::data::data_format& df) const
1946{
1947 GLuint gl_format = (const GLuint&) tb.internal_format;
1948
1949 if (tb.tt == TT_UNDEF)
1950 tb.tt = (TextureType)df.get_nr_dimensions();
1951 GLuint tex_id = texture_generate(tb);
1952 if (tex_id == get_gl_id(0))
1953 return false;
1954 GLuint tmp_id = texture_bind(tb.tt, tex_id);
1955
1956 // extract component type
1957 unsigned int transfer_format = map_to_gl(df.get_standard_component_format(), df.get_integer_interpretation());
1958 if (transfer_format == -1) {
1959 error("could not determine transfer format", &tb);
1960 return false;
1961 }
1962 switch (tb.tt) {
1963 case TT_1D :
1964 glTexImage1D(GL_TEXTURE_1D, 0,
1965 gl_format, GLsizei(df.get_width()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1966 break;
1967 case TT_1D_ARRAY :
1968 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0,
1969 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1970 break;
1971 case TT_2D :
1972 glTexImage2D(GL_TEXTURE_2D, 0, gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1973 break;
1974 case TT_MULTISAMPLE_2D:
1975 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));
1976 break;
1977 case TT_2D_ARRAY :
1978 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);
1979 break;
1980 case TT_MULTISAMPLE_2D_ARRAY:
1981 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));
1982 break;
1983 case TT_3D :
1984 glTexImage3D(GL_TEXTURE_3D, 0,
1985 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), GLsizei(df.get_depth()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1986 break;
1987 case TT_CUBEMAP :
1988 glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0,
1989 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1990 glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0,
1991 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1992 glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0,
1993 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1994 glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0,
1995 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1996 glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0,
1997 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
1998 glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0,
1999 gl_format, GLsizei(df.get_width()), GLsizei(df.get_height()), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2000 default:
2001 break;
2002 }
2003 if (check_gl_error("gl_context::texture_create", &tb)) {
2004 glDeleteTextures(1, &tex_id);
2005 texture_unbind(tb.tt, tmp_id);
2006 return false;
2007 }
2008
2009 texture_unbind(tb.tt, tmp_id);
2010 tb.have_mipmaps = false;
2011 tb.handle = get_handle(tex_id);
2012 return true;
2013}
2014
2015bool gl_context::texture_create(
2016 texture_base& tb,
2017 cgv::data::data_format& target_format,
2018 const cgv::data::const_data_view& data,
2019 int level, int cube_side, int num_array_layers, const std::vector<cgv::data::data_view>* palettes) const
2020{
2021 // query the format to be used for the texture
2022 GLuint gl_tex_format = (const GLuint&) tb.internal_format;
2023
2024 // define the texture type from the data format and the cube_side parameter
2025 tb.tt = (TextureType)data.get_format()->get_nr_dimensions();
2026 if(cube_side > -1) {
2027 if(tb.tt == TT_2D)
2028 tb.tt = TT_CUBEMAP;
2029 } else if(num_array_layers != 0) {
2030 if(num_array_layers < 0) {
2031 // automatic inference of layers from texture dimensions
2032 unsigned n_dims = data.get_format()->get_nr_dimensions();
2033 if(n_dims == 2)
2034 tb.tt = TT_1D_ARRAY;
2035 if(n_dims == 3)
2036 tb.tt = TT_2D_ARRAY;
2037 } else {
2038 switch(tb.tt) {
2039 case TT_1D: tb.tt = TT_1D_ARRAY; break;
2040 case TT_2D: tb.tt = TT_2D_ARRAY; break;
2041 case TT_3D: tb.tt = TT_2D_ARRAY; break;
2042 default:
2043 break;
2044 }
2045 }
2046 }
2047 // create texture is not yet done
2048 GLuint tex_id;
2049 if (tb.is_created())
2050 tex_id = get_gl_id(tb.handle);
2051 else {
2052 tex_id = texture_generate(tb);
2053 if (tex_id == get_gl_id(0))
2054 return false;
2055 tb.handle = get_handle(tex_id);
2056 }
2057
2058 // bind texture
2059 GLuint tmp_id = texture_bind(tb.tt, tex_id);
2060
2061 // load data to texture
2062 tb.have_mipmaps = load_texture(data, gl_tex_format, level, cube_side, num_array_layers, palettes);
2063 bool result = !check_gl_error("gl_context::texture_create", &tb);
2064 // restore old texture
2065 texture_unbind(tb.tt, tmp_id);
2066 return result;
2067}
2068
2069bool gl_context::texture_create_from_buffer(
2070 texture_base& tb,
2071 cgv::data::data_format& df,
2072 int x, int y, int level) const
2073{
2074 GLuint gl_format = (const GLuint&) tb.internal_format;
2075
2076 tb.tt = (TextureType)df.get_nr_dimensions();
2077 if (tb.tt != TT_2D) {
2078 tb.last_error = "texture creation from buffer only possible for 2d textures";
2079 return false;
2080 }
2081 GLuint tex_id;
2082 if (tb.is_created())
2083 tex_id = get_gl_id(tb.handle);
2084 else {
2085 tex_id = texture_generate(tb);
2086 if (tex_id == get_gl_id(0))
2087 return false;
2088 tb.handle = get_handle(tex_id);
2089 }
2090 GLuint tmp_id = texture_bind(tb.tt, tex_id);
2091
2092 // check mipmap type
2093 bool gen_mipmap = level == -1;
2094 if (gen_mipmap)
2095 level = 0;
2096
2097 glCopyTexImage2D(GL_TEXTURE_2D, level, gl_format, x, y, GLsizei(df.get_width()), GLsizei(df.get_height()), 0);
2098 bool result = false;
2099 std::string error_string("gl_context::texture_create_from_buffer: ");
2100 switch (glGetError()) {
2101 case GL_NO_ERROR :
2102 result = true;
2103 break;
2104 case GL_INVALID_ENUM :
2105 error_string += "target was not an accepted value.";
2106 break;
2107 case GL_INVALID_VALUE :
2108 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"
2109 "or border was not zero or 1.\n"
2110 "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.";
2111 break;
2112 case GL_INVALID_OPERATION :
2113 error_string += "glCopyTexImage2D was called between a call to glBegin and the corresponding call to glEnd.";
2114 break;
2115 default:
2116 error_string += gl_error_to_string(glGetError());
2117 break;
2118 }
2119 texture_unbind(tb.tt, tmp_id);
2120 if (!result)
2121 error(error_string, &tb);
2122 else
2123 if (gen_mipmap)
2124 result = texture_generate_mipmaps(tb, tb.tt == TT_CUBEMAP ? 2 : (int)tb.tt);
2125
2126 return result;
2127}
2128
2129bool gl_context::texture_replace(
2130 texture_base& tb,
2131 int x, int y, int z,
2132 const cgv::data::const_data_view& data,
2133 int level, const std::vector<cgv::data::data_view>* palettes) const
2134{
2135 if (!tb.is_created()) {
2136 error("gl_context::texture_replace: attempt to replace in not created texture", &tb);
2137 return false;
2138 }
2139 // determine dimension from location arguments
2140 unsigned int dim = 1;
2141 if (y != -1) {
2142 ++dim;
2143 if (z != -1)
2144 ++dim;
2145 }
2146 // check consistency
2147 if (tb.tt == TT_CUBEMAP) {
2148 if (dim != 3) {
2149 error("gl_context::texture_replace: replace on cubemap without the side defined", &tb);
2150 return false;
2151 }
2152 if (z < 0 || z > 5) {
2153 error("gl_context::texture_replace: replace on cubemap with invalid side specification", &tb);
2154 return false;
2155 }
2156 }
2157 else {
2158 if (tb.tt != dim) {
2159 error("gl_context::texture_replace: replace on texture with invalid position specification", &tb);
2160 return false;
2161 }
2162 }
2163
2164 // bind texture
2165 GLuint tmp_id = texture_bind(tb.tt, get_gl_id(tb.handle));
2166 tb.have_mipmaps = replace_texture(data, level, x, y, z, palettes) || tb.have_mipmaps;
2167 bool result = !check_gl_error("gl_context::texture_replace", &tb);
2168 texture_unbind(tb.tt, tmp_id);
2169 return result;
2170}
2171
2172bool gl_context::texture_replace_from_buffer(
2173 texture_base& tb,
2174 int x, int y, int z,
2175 int x_buffer, int y_buffer,
2176 unsigned int width, unsigned int height,
2177 int level) const
2178{
2179 if (!tb.is_created()) {
2180 error("gl_context::texture_replace_from_buffer: attempt to replace in not created texture", &tb);
2181 return false;
2182 }
2183 // determine dimension from location arguments
2184 unsigned int dim = 2;
2185 if (z != -1)
2186 ++dim;
2187
2188 // consistency checks
2189 if (tb.tt == TT_CUBEMAP) {
2190 if (dim != 3) {
2191 error("gl_context::texture_replace_from_buffer: replace on cubemap without the side defined", &tb);
2192 return false;
2193 }
2194 if (z < 0 || z > 5) {
2195 error("gl_context::texture_replace_from_buffer: replace on cubemap without invalid side specification", &tb);
2196 return false;
2197 }
2198 }
2199 else {
2200 if (tb.tt != dim) {
2201 tb.last_error = "replace on texture with invalid position specification";
2202 return false;
2203 }
2204 }
2205 // check mipmap type
2206 bool gen_mipmap = level == -1;
2207 if (gen_mipmap)
2208 level = 0;
2209
2210 // bind texture
2211 GLuint tmp_id = texture_bind(tb.tt, get_gl_id(tb.handle));
2212 switch (tb.tt) {
2213 case TT_2D : glCopyTexSubImage2D(GL_TEXTURE_2D, level, x, y, x_buffer, y_buffer, width, height); break;
2214 case TT_3D : glCopyTexSubImage3D(GL_TEXTURE_3D, level, x, y, z, x_buffer, y_buffer, width, height); break;
2215 case TT_CUBEMAP : glCopyTexSubImage2D(get_gl_cube_map_target(z), level, x, y, x_buffer, y_buffer, width, height);
2216 default: break;
2217 }
2218 bool result = !check_gl_error("gl_context::texture_replace_from_buffer", &tb);
2219 texture_unbind(tb.tt, tmp_id);
2220
2221 if (result && gen_mipmap)
2222 result = texture_generate_mipmaps(tb, tb.tt == TT_CUBEMAP ? 2 : (int)tb.tt);
2223
2224 return result;
2225}
2226
2227bool gl_context::texture_copy_back(const texture_base& tb, int level, cgv::data::data_view& dv) const
2228{
2229 if(!tb.is_created()) {
2230 error("gl_context::texture_copy_back: attempt to copy from not created texture", &tb);
2231 return false;
2232 }
2233
2234 GLuint tmp_id = texture_bind(tb.tt, get_gl_id(tb.handle));
2235 read_texture(dv, level);
2236
2237 bool result = !check_gl_error("gl_context::texture_copy_back", &tb);
2238 texture_unbind(tb.tt, tmp_id);
2239
2240 return result;
2241}
2242
2243bool gl_context::texture_create_mipmaps(texture_base& tb, cgv::data::data_format& df) const
2244{
2245 GLuint gl_format = (const GLuint&)tb.internal_format;
2246
2247 // extract component type
2248 unsigned int transfer_format = map_to_gl(df.get_standard_component_format(), df.get_integer_interpretation());
2249
2250 if(transfer_format == -1) {
2251 error("could not determine transfer format", &tb);
2252 return false;
2253 }
2254
2255 // extract texture size and compute number of mip-levels
2256 uvec3 size(unsigned(df.get_width()), unsigned(df.get_height()), unsigned(df.get_depth()));
2257
2258 unsigned max_size = cgv::math::max_value(size);
2259 unsigned num_levels = 1 + static_cast<unsigned>(log2(static_cast<float>(max_size)));
2260
2261 // compute mip-level sizes
2262 std::vector<uvec3> level_sizes(num_levels);
2263 level_sizes[0] = size;
2264
2265 for(unsigned level = 1; level < num_levels; ++level) {
2266 uvec3 level_size = level_sizes[level - 1];
2267 level_size = level_size / 2u;
2268 level_size = cgv::math::max(level_size, uvec3(1u));
2269 level_sizes[level] = level_size;
2270 }
2271
2272 GLuint tmp_id = texture_bind(tb.tt, get_gl_id(tb.handle));
2273
2274 bool result = true;
2275
2276 switch(tb.tt) {
2277 case TT_1D:
2278 for(unsigned level = 1; level < num_levels; ++level) {
2279 uvec3 level_size = level_sizes[level];
2280 glTexImage1D(GL_TEXTURE_1D, level, gl_format, level_size.x(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2281 }
2282 break;
2283 case TT_1D_ARRAY:
2284 //glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2285 error("create mipmaps not implemented for 1D array textures", &tb);
2286 result = false;
2287 break;
2288 case TT_2D:
2289 for(unsigned level = 1; level < num_levels; ++level) {
2290 uvec3 level_size = level_sizes[level];
2291 glTexImage2D(GL_TEXTURE_2D, level, gl_format, level_size.x(), level_size.y(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2292 }
2293 break;
2294 case TT_MULTISAMPLE_2D:
2295 //glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, tb.nr_multi_samples, gl_format, df.get_width(), df.get_height(), map_to_gl(tb.fixed_sample_locations));
2296 error("create mipmaps not implemented for 2D multisample textures", &tb);
2297 result = false;
2298 break;
2299 case TT_2D_ARRAY:
2300 //glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, gl_format, df.get_width(), df.get_height(), df.get_depth(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2301 error("create mipmaps not implemented for 2D array textures", &tb);
2302 result = false;
2303 break;
2304 case TT_MULTISAMPLE_2D_ARRAY:
2305 //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));
2306 error("create mipmaps not implemented for 2D multisample array textures", &tb);
2307 result = false;
2308 break;
2309 case TT_3D:
2310 for(unsigned level = 1; level < num_levels; ++level) {
2311 uvec3 level_size = level_sizes[level];
2312 glTexImage3D(GL_TEXTURE_3D, level, gl_format, level_size.x(), level_size.y(), level_size.z(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2313 }
2314 break;
2315 case TT_CUBEMAP:
2316 /*glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0,
2317 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2318 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0,
2319 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2320 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0,
2321 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2322 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0,
2323 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2324 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0,
2325 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2326 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0,
2327 gl_format, df.get_width(), df.get_height(), 0, transfer_format, GL_UNSIGNED_BYTE, 0);
2328 */
2329 error("create mipmaps not implemented for cubemap textures", &tb);
2330 result = false;
2331 default:
2332 break;
2333 }
2334
2335 if(check_gl_error("gl_context::texture_create_mipmaps", &tb))
2336 result = false;
2337
2338 if(result)
2339 tb.have_mipmaps = true;
2340
2341 texture_unbind(tb.tt, tmp_id);
2342 return result;
2343}
2344
2345bool gl_context::texture_generate_mipmaps(texture_base& tb, unsigned int dim) const
2346{
2347 GLuint tmp_id = texture_bind(tb.tt,get_gl_id(tb.handle));
2348
2349 bool is_array = tb.tt == TT_1D_ARRAY || tb.tt == TT_2D_ARRAY;
2350 bool is_cubemap = tb.tt == TT_CUBEMAP;
2351 std::string error_string;
2352 bool result = generate_mipmaps(dim, is_cubemap, is_array, &error_string);
2353 if (result)
2354 tb.have_mipmaps = true;
2355 else
2356 error(std::string("gl_context::texture_generate_mipmaps: ") + error_string);
2357
2358 texture_unbind(tb.tt, tmp_id);
2359 return result;
2360}
2361
2362bool gl_context::texture_destruct(texture_base& tb) const
2363{
2364 if (!tb.is_created()) {
2365 error("gl_context::texture_destruct: attempt to destruct not created texture", &tb);
2366 return false;
2367 }
2368 GLuint tex_id = get_gl_id(tb.handle);
2369 glDeleteTextures(1, &tex_id);
2370 bool result = !check_gl_error("gl_context::texture_destruct", &tb);
2371 tb.handle = 0;
2372 tb.ctx_ptr = 0;
2373 return result;
2374}
2375
2376bool gl_context::texture_set_state(const texture_base& tb) const
2377{
2378 if (tb.tt == TT_UNDEF) {
2379 error("gl_context::texture_set_state: attempt to set state on texture without type", &tb);
2380 return false;
2381 }
2382 GLuint tex_id = (GLuint&) tb.handle - 1;
2383 if (tex_id == -1) {
2384 error("gl_context::texture_set_state: attempt of setting texture state of not created texture", &tb);
2385 return false;
2386 }
2387 GLint tmp_id = texture_bind(tb.tt, tex_id);
2388
2389 if (tb.tt != TT_MULTISAMPLE_2D && tb.tt != TT_MULTISAMPLE_2D_ARRAY) {
2390 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_MIN_FILTER, map_to_gl(tb.min_filter));
2391 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_MAG_FILTER, map_to_gl(tb.mag_filter));
2392 if (tb.min_filter == TF_ANISOTROP)
2393 glTexParameterf(get_tex_dim(tb.tt), GL_TEXTURE_MAX_ANISOTROPY_EXT, tb.anisotropy);
2394 else
2395 glTexParameterf(get_tex_dim(tb.tt), GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
2396 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_COMPARE_FUNC, map_to_gl(tb.compare_function));
2397 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_COMPARE_MODE, (tb.use_compare_function ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE));
2398 if (!core_profile)
2399 glTexParameterf(get_tex_dim(tb.tt), GL_TEXTURE_PRIORITY, tb.priority);
2400 glTexParameterfv(get_tex_dim(tb.tt), GL_TEXTURE_BORDER_COLOR, tb.border_color);
2401 // if (tb.border_color[0] >= 0.0f)
2402 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_WRAP_S, map_to_gl(tb.wrap_s));
2403 if (tb.tt > TT_1D)
2404 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_WRAP_T, map_to_gl(tb.wrap_t));
2405 if (tb.tt == TT_3D)
2406 glTexParameteri(get_tex_dim(tb.tt), GL_TEXTURE_WRAP_R, map_to_gl(tb.wrap_r));
2407 }
2408
2409 bool result = !check_gl_error("gl_context::texture_set_state", &tb);
2410 texture_unbind(tb.tt, tmp_id);
2411 return result;
2412}
2413
2414bool gl_context::texture_enable(texture_base& tb, int tex_unit, unsigned int dim) const
2415{
2416 if (dim < 1 || dim > 3) {
2417 error("gl_context::texture_enable: invalid texture dimension", &tb);
2418 return false;
2419 }
2420 GLuint tex_id = (GLuint&) tb.handle - 1;
2421 if (tex_id == -1) {
2422 error("gl_context::texture_enable: texture not created", &tb);
2423 return false;
2424 }
2425 if (tex_unit >= 0) {
2426 if (!GLEW_VERSION_1_3) {
2427 error("gl_context::texture_enable: multi texturing not supported", &tb);
2428 return false;
2429 }
2430 glActiveTexture(GL_TEXTURE0+tex_unit);
2431 }
2432 GLint& old_binding = (GLint&) tb.user_data;
2433 glGetIntegerv(get_tex_bind(tb.tt), &old_binding);
2434 ++old_binding;
2435 glBindTexture(get_tex_dim(tb.tt), tex_id);
2436 // glEnable is not needed for texture arrays and will throw an invalid enum error
2437 //if(!(tb.tt == TT_1D_ARRAY || tb.tt == TT_2D_ARRAY))
2438 // glEnable(get_tex_dim(tb.tt));
2439 bool result = !check_gl_error("gl_context::texture_enable", &tb);
2440 if (tex_unit >= 0)
2441 glActiveTexture(GL_TEXTURE0);
2442 return result;
2443}
2444
2445bool gl_context::texture_disable(
2446 texture_base& tb,
2447 int tex_unit, unsigned int dim) const
2448{
2449 if (dim < 1 || dim > 3) {
2450 error("gl_context::texture_disable: invalid texture dimension", &tb);
2451 return false;
2452 }
2453 if (tex_unit == -2) {
2454 error("gl_context::texture_disable: invalid texture unit", &tb);
2455 return false;
2456 }
2457 GLuint old_binding = (const GLuint&) tb.user_data;
2458 --old_binding;
2459 if (tex_unit >= 0)
2460 glActiveTexture(GL_TEXTURE0+tex_unit);
2461 // glDisable is not needed for texture arrays and will throw an invalid enum error
2462 //if(!(tb.tt == TT_1D_ARRAY || tb.tt == TT_2D_ARRAY))
2463 // glDisable(get_tex_dim(tb.tt));
2464 bool result = !check_gl_error("gl_context::texture_disable", &tb);
2465 glBindTexture(get_tex_dim(tb.tt), old_binding);
2466 if (tex_unit >= 0)
2467 glActiveTexture(GL_TEXTURE0);
2468 return result;
2469}
2470
2471bool gl_context::texture_bind_as_image(texture_base& tb, int tex_unit, int level, bool bind_array, int layer, AccessType access) const
2472{
2473 GLuint tex_id = (GLuint&)tb.handle - 1;
2474 if(tex_id == -1) {
2475 error("gl_context::texture_enable: texture not created", &tb);
2476 return false;
2477 }
2478
2479 if(!GLEW_VERSION_4_2) {
2480 error("gl_context::texture_bind_as_image: image textures not supported", &tb);
2481 return false;
2482 }
2483
2484 GLuint gl_format = (const GLuint&)tb.internal_format;
2485 glBindImageTexture(tex_unit, tex_id, level, map_to_gl(bind_array), layer, map_to_gl(access), gl_format);
2486
2487 bool result = !check_gl_error("gl_context::texture_bind_as_image", &tb);
2488 return result;
2489}
2490
2491bool gl_context::render_buffer_create(render_buffer_base& rb, cgv::data::component_format& cf, int& _width, int& _height) const
2492{
2493 if (!GLEW_VERSION_3_0) {
2494 error("gl_context::render_buffer_create: frame buffer objects not supported", &rb);
2495 return false;
2496 }
2497 if (_width == -1)
2498 _width = get_width();
2499 if (_height == -1)
2500 _height = get_height();
2501
2502 GLuint rb_id;
2503 glGenRenderbuffers(1, &rb_id);
2504 glBindRenderbuffer(GL_RENDERBUFFER, rb_id);
2505
2506 GLuint& gl_format = (GLuint&)rb.internal_format;
2507 unsigned i = find_best_match(cf, color_buffer_formats);
2508 cgv::data::component_format best_cf(color_buffer_formats[i]);
2509 gl_format = gl_color_buffer_format_ids[i];
2510
2511 i = find_best_match(cf, depth_formats, &best_cf);
2512 if (i != -1) {
2513 best_cf = cgv::data::component_format(depth_formats[i]);
2514 gl_format = gl_depth_format_ids[i];
2515 }
2516
2517 cf = best_cf;
2518 if (rb.nr_multi_samples == 0)
2519 glRenderbufferStorage(GL_RENDERBUFFER, gl_format, _width, _height);
2520 else
2521 glRenderbufferStorageMultisample(GL_RENDERBUFFER, rb.nr_multi_samples, gl_format, _width, _height);
2522
2523 if (check_gl_error("gl_context::render_buffer_create", &rb))
2524 return false;
2525 rb.handle = get_handle(rb_id);
2526 return true;
2527}
2528
2529bool gl_context::render_buffer_destruct(render_buffer_base& rc) const
2530{
2531 if (!GLEW_VERSION_3_0) {
2532 error("gl_context::render_buffer_destruct: frame buffer objects not supported", &rc);
2533 return false;
2534 }
2535 GLuint rb_id = ((GLuint&) rc.handle)+1;
2536 glDeleteRenderbuffers(1, &rb_id);
2537 if (check_gl_error("gl_context::render_buffer_destruct", &rc))
2538 return false;
2539 rc.handle = 0;
2540 rc.ctx_ptr = 0;
2541 return true;
2542}
2543
2544bool gl_context::frame_buffer_create(frame_buffer_base& fbb) const
2545{
2546 if (!check_fbo_support("gl_context::frame_buffer_create", &fbb))
2547 return false;
2548
2549 if (!context::frame_buffer_create(fbb))
2550 return false;
2551
2552 // allocate framebuffer object
2553 GLuint fbo_id = 0;
2554 glGenFramebuffers(1, &fbo_id);
2555 if (fbo_id == 0) {
2556 error("gl_context::frame_buffer_create: could not allocate framebuffer object", &fbb);
2557 return false;
2558 }
2559 fbb.handle = get_handle(fbo_id);
2560 return true;
2561}
2562
2563bool gl_context::frame_buffer_enable(frame_buffer_base& fbb)
2564{
2565 if (!context::frame_buffer_enable(fbb))
2566 return false;
2567 std::vector<int> buffers;
2568 bool depth_buffer = false;
2569 get_buffer_list(fbb, depth_buffer, buffers, GL_COLOR_ATTACHMENT0);
2570 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(fbb.handle));
2571
2572 if (buffers.size() == 1)
2573 glDrawBuffer(buffers[0]);
2574 else if (buffers.size() > 1) {
2575 glDrawBuffers(GLsizei(buffers.size()), reinterpret_cast<GLenum*>(&buffers[0]));
2576 }
2577 else if(depth_buffer) {
2578 glDrawBuffer(GL_NONE);
2579 //glReadBuffer(GL_NONE);
2580 } else {
2581 error("gl_context::frame_buffer_enable: no attached draw buffer selected!!", &fbb);
2582 return false;
2583 }
2584 return true;
2585}
2586
2589{
2590 if (!context::frame_buffer_disable(fbb))
2591 return false;
2592 if (frame_buffer_stack.empty()) {
2593 error("gl_context::frame_buffer_disable called with empty frame buffer stack!!", &fbb);
2594 return false;
2595 }
2596 else
2597 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(frame_buffer_stack.top()->handle));
2598 return true;
2599}
2600
2601bool gl_context::frame_buffer_destruct(frame_buffer_base& fbb) const
2602{
2603 if (!context::frame_buffer_destruct(fbb))
2604 return false;
2605 GLuint fbo_id = get_gl_id(fbb.handle);
2606 glDeleteFramebuffers(1, &fbo_id);
2607 fbb.handle = 0;
2608 fbb.ctx_ptr = 0;
2609 return true;
2610}
2611
2612void complete_rect_from_vp(ivec4& D, GLint vp[4])
2613{
2614 if (D(0) == -1)
2615 D(0) = vp[0];
2616 if (D(1) == -1)
2617 D(1) = vp[1];
2618 if (D(2) == -1)
2619 D(2) = vp[0] + vp[2];
2620 if (D(3) == -1)
2621 D(3) = vp[1] + vp[3];
2622}
2623
2624void gl_context::frame_buffer_blit(
2625 const frame_buffer_base* src_fbb_ptr, const ivec4& _S,
2626 frame_buffer_base* dst_fbb_ptr, const ivec4& _D, BufferTypeBits btbs, bool interpolate) const
2627{
2628 static const GLenum masks[8]{
2629 0,
2630 GL_COLOR_BUFFER_BIT,
2631 GL_DEPTH_BUFFER_BIT,
2632 GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
2633 GL_STENCIL_BUFFER_BIT,
2634 GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT,
2635 GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
2636 GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT
2637 };
2638 ivec4 S = _S;
2639 ivec4 D = _D;
2640 if ((src_fbb_ptr == 0 && (S(0) == -1 || S(1) == -1 || S(2) == -1 || S(3) == -1)) ||
2641 (dst_fbb_ptr == 0 && (D(0) == -1 || D(1) == -1 || D(2) == -1 || D(3) == -1))) {
2642 GLint vp[4];
2643 glGetIntegerv(GL_VIEWPORT, vp);
2644 if (src_fbb_ptr == 0)
2645 complete_rect_from_vp(S, vp);
2646 if (dst_fbb_ptr == 0)
2647 complete_rect_from_vp(D, vp);
2648 }
2649 GLint old_draw_fbo, old_read_fbo;
2650 if (src_fbb_ptr) {
2651 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &old_read_fbo);
2652 glBindFramebuffer(GL_READ_FRAMEBUFFER, get_gl_id(src_fbb_ptr->handle));
2653 }
2654 if (dst_fbb_ptr) {
2655 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &old_draw_fbo);
2656 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, get_gl_id(dst_fbb_ptr->handle));
2657 }
2658 glBlitFramebuffer(S(0), S(1), S(2), S(3), D(0), D(1), D(2), D(3), masks[btbs], interpolate ? GL_LINEAR : GL_NEAREST);
2659 if (src_fbb_ptr)
2660 glBindFramebuffer(GL_READ_FRAMEBUFFER, old_read_fbo);
2661 if (dst_fbb_ptr)
2662 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, old_draw_fbo);
2663}
2664
2665bool gl_context::frame_buffer_attach(frame_buffer_base& fbb, const render_buffer_base& rb, bool is_depth, int i) const
2666{
2667 if (!context::frame_buffer_attach(fbb, rb, is_depth, i))
2668 return false;
2669 GLint old_binding;
2670 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_binding);
2671 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(fbb.handle));
2672 glFramebufferRenderbuffer(GL_FRAMEBUFFER,
2673 is_depth ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0 + i,
2674 GL_RENDERBUFFER,
2675 get_gl_id(rb.handle));
2676 glBindFramebuffer(GL_FRAMEBUFFER, old_binding);
2677 return true;
2678}
2679
2681bool gl_context::frame_buffer_attach(frame_buffer_base& fbb,
2682 const texture_base& t, bool is_depth,
2683 int level, int i, int z_or_cube_side) const
2684{
2685 if (!context::frame_buffer_attach(fbb, t, is_depth, level, i, z_or_cube_side))
2686 return false;
2687 GLint old_binding;
2688 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_binding);
2689 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(fbb.handle));
2690
2691 if (z_or_cube_side == -1) {
2692 glFramebufferTexture2D(GL_FRAMEBUFFER,
2693 is_depth ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0+i,
2694 t.tt == TT_2D ? GL_TEXTURE_2D : GL_TEXTURE_2D_MULTISAMPLE, get_gl_id(t.handle), level);
2695 }
2696 else {
2697 if (t.tt == TT_CUBEMAP) {
2698 glFramebufferTexture2D(GL_FRAMEBUFFER,
2699 GL_COLOR_ATTACHMENT0+i,
2700 get_gl_cube_map_target(z_or_cube_side), get_gl_id(t.handle), level);
2701 }
2702 else {
2703 glFramebufferTexture3D(GL_FRAMEBUFFER,
2704 GL_COLOR_ATTACHMENT0+i,
2705 t.tt == TT_3D ? GL_TEXTURE_3D : GL_TEXTURE_2D_MULTISAMPLE_ARRAY , get_gl_id(t.handle), level, z_or_cube_side);
2706 }
2707 }
2708 bool result = !check_gl_error("gl_context::frame_buffer_attach", &fbb);
2709 glBindFramebuffer(GL_FRAMEBUFFER, old_binding);
2710 return result;
2711}
2712
2715{
2716 if (fbb.handle == 0) {
2717 error("gl_context::frame_buffer_is_complete: attempt to check completeness on frame buffer that is not created", &fbb);
2718 return false;
2719 }
2720 GLint old_binding;
2721 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_binding);
2722 glBindFramebuffer(GL_FRAMEBUFFER, get_gl_id(fbb.handle));
2723 GLenum error = glCheckFramebufferStatus(GL_FRAMEBUFFER);
2724 glBindFramebuffer(GL_FRAMEBUFFER, old_binding);
2725 switch (error) {
2726 case GL_FRAMEBUFFER_COMPLETE:
2727 return true;
2728 case GL_FRAMEBUFFER_UNDEFINED:
2729 fbb.last_error = "undefined framebuffer";
2730 return false;
2731 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
2732 fbb.last_error = "incomplete attachment";
2733 return false;
2734 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
2735 fbb.last_error = "incomplete or missing attachment";
2736 return false;
2737 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
2738 fbb.last_error = "incomplete multisample";
2739 return false;
2740 case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
2741 fbb.last_error = "incomplete layer targets";
2742 return false;
2743 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
2744 fbb.last_error = "incomplete draw buffer";
2745 return false;
2746 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
2747 fbb.last_error = "incomplete read buffer";
2748 return false;
2749 case GL_FRAMEBUFFER_UNSUPPORTED:
2750 fbb.last_error = "framebuffer objects unsupported";
2751 return false;
2752 }
2753 fbb.last_error = "unknown error";
2754 return false;
2755}
2756
2757int gl_context::frame_buffer_get_max_nr_color_attachments() const
2758{
2759 if (!check_fbo_support("gl_context::frame_buffer_get_max_nr_color_attachments"))
2760 return 0;
2761
2762 GLint nr;
2763 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &nr);
2764 return nr;
2765}
2766
2767int gl_context::frame_buffer_get_max_nr_draw_buffers() const
2768{
2769 if (!check_fbo_support("gl_context::frame_buffer_get_max_nr_draw_buffers"))
2770 return 0;
2771
2772 GLint nr;
2773 glGetIntegerv(GL_MAX_DRAW_BUFFERS, &nr);
2774 return nr;
2775}
2776
2777GLuint gl_shader_type[] =
2778{
2779 0, GL_COMPUTE_SHADER, GL_VERTEX_SHADER, GL_TESS_CONTROL_SHADER, GL_TESS_EVALUATION_SHADER, GL_GEOMETRY_SHADER, GL_FRAGMENT_SHADER, GL_TASK_SHADER_EXT, GL_MESH_SHADER_EXT
2780};
2781
2782void gl_context::shader_code_destruct(render_component& sc) const
2783{
2784 if (sc.handle == 0) {
2785 error("gl_context::shader_code_destruct: shader not created", &sc);
2786 return;
2787 }
2788 glDeleteShader(get_gl_id(sc.handle));
2789 sc.handle = 0;
2790 sc.ctx_ptr = 0;
2791 check_gl_error("gl_context::shader_code_destruct", &sc);
2792}
2793
2794bool gl_context::shader_code_create(render_component& sc, ShaderType st, const std::string& source) const
2795{
2796 if (!check_shader_support(st, "gl_context::shader_code_create", &sc))
2797 return false;
2798
2799 while (glGetError()); // Clear error flags.
2800
2801 GLuint s_id = glCreateShader(gl_shader_type[st]);
2802 if (s_id == -1) {
2803 error(std::string("gl_context::shader_code_create: ")+gl_error(), &sc);
2804 return false;
2805 }
2806 sc.handle = get_handle(s_id);
2807
2808 const char* s = source.c_str();
2809 glShaderSource(s_id, 1, &s,NULL);
2810 if (check_gl_error("gl_context::shader_code_create", &sc))
2811 return false;
2812
2813 return true;
2814}
2815
2816bool gl_context::shader_code_compile(render_component& sc) const
2817{
2818 if (sc.handle == 0) {
2819 error("gl_context::shader_code_compile: shader not created", &sc);
2820 return false;
2821 }
2822 GLuint s_id = get_gl_id(sc.handle);
2823 glCompileShader(s_id);
2824 GLint result = GL_FALSE;
2825 glGetShaderiv(s_id, GL_COMPILE_STATUS, &result);
2826 if (result == GL_TRUE)
2827 return true;
2828 sc.last_error = std::string();
2829 GLint infologLength = 0;
2830 glGetShaderiv(s_id, GL_INFO_LOG_LENGTH, &infologLength);
2831 if (infologLength > 0) {
2832 GLsizei charsWritten = 0;
2833 sc.last_error = std::string(infologLength, 0);
2834 glGetShaderInfoLog(s_id, infologLength, &charsWritten, &sc.last_error.front());
2835 sc.last_error.resize(static_cast<size_t>(charsWritten));
2836 }
2837 return false;
2838}
2839
2840bool gl_context::shader_program_create(shader_program_base& spb) const
2841{
2842 if (!check_shader_support(ST_VERTEX, "gl_context::shader_program_create", &spb))
2843 return false;
2844 spb.handle = get_handle(glCreateProgram());
2845 return true;
2846}
2847
2848void gl_context::shader_program_attach(shader_program_base& spb, const render_component& sc) const
2849{
2850 if (spb.handle == 0) {
2851 error("gl_context::shader_program_attach: shader program not created", &spb);
2852 return;
2853 }
2854 glAttachShader(get_gl_id(spb.handle), get_gl_id(sc.handle));
2855}
2856
2857void gl_context::shader_program_detach(shader_program_base& spb, const render_component& sc) const
2858{
2859 if (spb.handle == 0) {
2860 error("gl_context::shader_program_detach: shader program not created", &spb);
2861 return;
2862 }
2863 glDetachShader(get_gl_id(spb.handle), get_gl_id(sc.handle));
2864}
2865
2866bool gl_context::shader_program_link(shader_program_base& spb) const
2867{
2868 if (spb.handle == 0) {
2869 error("gl_context::shader_program_link: shader program not created", &spb);
2870 return false;
2871 }
2872 GLuint p_id = get_gl_id(spb.handle);
2873 glLinkProgram(p_id);
2874 GLint result = GL_FALSE;
2875 glGetProgramiv(p_id, GL_LINK_STATUS, &result);
2876 if (result == GL_TRUE)
2877 return context::shader_program_link(spb);
2878 GLint infologLength = 0;
2879 glGetProgramiv(p_id, GL_INFO_LOG_LENGTH, &infologLength);
2880 if (infologLength > 0) {
2881 GLsizei charsWritten = 0;
2882 spb.last_error = std::string(infologLength, 0);
2883 glGetProgramInfoLog(p_id, infologLength, &charsWritten, &spb.last_error.front());
2884 spb.last_error.resize(static_cast<size_t>(charsWritten));
2885 error("gl_context::shader_program_link\n" + spb.last_error, &spb);
2886 }
2887
2888 return false;
2889}
2890
2891bool gl_context::shader_program_set_state(shader_program_base& spb) const
2892{
2893 if (spb.handle == 0) {
2894 error("gl_context::shader_program_set_state: shader program not created", &spb);
2895 return false;
2896 }
2897 GLuint p_id = get_gl_id(spb.handle);
2898 glProgramParameteri(p_id, GL_GEOMETRY_VERTICES_OUT_ARB, spb.geometry_shader_output_count);
2899 glProgramParameteri(p_id, GL_GEOMETRY_INPUT_TYPE_ARB, map_to_gl(spb.geometry_shader_input_type));
2900 glProgramParameteri(p_id, GL_GEOMETRY_OUTPUT_TYPE_ARB, map_to_gl(spb.geometry_shader_output_type));
2901 return true;
2902}
2903
2904bool gl_context::shader_program_enable(shader_program_base& spb)
2905{
2906 if (!context::shader_program_enable(spb))
2907 return false;
2908 glUseProgram(get_gl_id(spb.handle));
2909 shader_program& prog = static_cast<shader_program&>(spb);
2910 if (auto_set_lights_in_current_shader_program && spb.does_use_lights())
2911 set_current_lights(prog);
2912 if (auto_set_material_in_current_shader_program && spb.does_use_material())
2914 if (auto_set_view_in_current_shader_program && spb.does_use_view())
2915 set_current_view(prog);
2916 if (auto_set_gamma_in_current_shader_program && spb.does_use_gamma())
2917 set_current_gamma(prog);
2918 if (prog.does_context_set_color() && prog.get_color_index() >= 0)
2919 prog.set_attribute(*this, prog.get_color_index(), current_color);
2920 return true;
2921}
2922
2923bool gl_context::shader_program_disable(shader_program_base& spb)
2924{
2925 if (!context::shader_program_disable(spb))
2926 return false;
2927 if (shader_program_stack.empty())
2928 glUseProgram(0);
2929 else
2930 glUseProgram(get_gl_id(shader_program_stack.top()->handle));
2931 return true;
2932}
2933
2934bool gl_context::shader_program_destruct(shader_program_base& spb) const
2935{
2936 if (!context::shader_program_destruct(spb))
2937 return false;
2938 glDeleteProgram(get_gl_id(spb.handle));
2939 spb.handle = 0;
2940 spb.ctx_ptr = 0;
2941 return true;
2942}
2943
2944bool gl_context::shader_program_get_active_uniforms(shader_program_base& spb, std::vector<std::string>& names) const
2945{
2946 if (spb.handle == 0)
2947 return false;
2948
2949 GLuint p_id = get_gl_id(spb.handle);
2950
2951 GLint num_active_uniforms = 0;
2952 glGetProgramiv(p_id, GL_ACTIVE_UNIFORMS, &num_active_uniforms);
2953
2954 names.reserve(num_active_uniforms);
2955
2956 std::vector<GLchar> buffer(256);
2957 for (int i = 0; i < num_active_uniforms; ++i) {
2958 GLint array_size = 0;
2959 GLenum type = 0;
2960 GLsizei actual_length = 0;
2961
2962 glGetActiveUniform(p_id, i, GLsizei(buffer.size()), &actual_length, &array_size, &type, buffer.data());
2963 std::string name(static_cast<char*>(buffer.data()), actual_length);
2964
2965 // Uniforms for arrays of non-compound (non-struct) types are listed once with a "[0]" suffix and a given array size greater than 1.
2966 if(array_size > 1) {
2967 // Remove the brackets to get the base name of the uniform
2968 size_t bracket_pos = name.find('[');
2969 if(bracket_pos != std::string::npos)
2970 name.resize(bracket_pos);
2971
2972 if(!name.empty()) {
2973 // Store the name without the brackets to allow setting complete arrays using just the uniform name.
2974 names.push_back(name);
2975 // Additionally store an entry for every possible indexed name to allow setting elements individually.
2976 for(GLint i = 0; i < array_size; ++i)
2977 names.push_back(name + "[" + std::to_string(i) + "]");
2978 }
2979 } else {
2980 if(!name.empty())
2981 names.push_back(name);
2982 }
2983 }
2984 return true;
2985}
2986
2987program_variable_info construct_program_variable(const std::vector<GLchar>& buffer, GLsizei actual_length, GLint array_size, GLenum type)
2988{
2989 program_variable_info V;
2990 V.name = std::string(static_cast<const char*>(buffer.data()), actual_length);
2991 // Uniforms for arrays of non-compound (non-struct) types are listed once with a "[0]" suffix and a given array size greater than 1.
2992 if (array_size > 1) {
2993 // Remove the brackets to get the base name of the uniform
2994 size_t bracket_pos = V.name.find('[');
2995 if (bracket_pos != std::string::npos)
2996 V.name.resize(bracket_pos);
2997 if (!V.name.empty())
2998 V.array_size = array_size;
2999 }
3000 else {
3001 V.array_size = 1;
3002 }
3003 switch (type) {
3004 case GL_FLOAT: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, false); break;
3005 case GL_FLOAT_VEC2: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 2u); break;
3006 case GL_FLOAT_VEC3: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 3u); break;
3007 case GL_FLOAT_VEC4: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 4u); break;
3008 case GL_FLOAT_MAT2: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 2u, 2u, false); break;
3009 case GL_FLOAT_MAT3: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 3u, 3u, false); break;
3010 case GL_FLOAT_MAT4: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 4u, 4u, false); break;
3011 case GL_FLOAT_MAT2x3: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 2u, 3u, false); break;
3012 case GL_FLOAT_MAT2x4: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 2u, 4u, false); break;
3013 case GL_FLOAT_MAT3x2: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 3u, 2u, false); break;
3014 case GL_FLOAT_MAT3x4: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 3u, 4u, false); break;
3015 case GL_FLOAT_MAT4x2: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 4u, 2u, false); break;
3016 case GL_FLOAT_MAT4x3: V.type_descr = type_descriptor(cgv::type::info::TI_FLT32, 4u, 3u, false); break;
3017 case GL_BOOL: V.type_descr = type_descriptor(cgv::type::info::TI_BOOL, false); break;
3018 case GL_BOOL_VEC2:V.type_descr = type_descriptor(cgv::type::info::TI_BOOL, 2u); break;
3019 case GL_BOOL_VEC3:V.type_descr = type_descriptor(cgv::type::info::TI_BOOL, 3u); break;
3020 case GL_BOOL_VEC4:V.type_descr = type_descriptor(cgv::type::info::TI_BOOL, 4u); break;
3021 case GL_INT: V.type_descr = type_descriptor(cgv::type::info::TI_INT32, false); break;
3022 case GL_INT_VEC2:V.type_descr = type_descriptor(cgv::type::info::TI_INT32, 2u); break;
3023 case GL_INT_VEC3:V.type_descr = type_descriptor(cgv::type::info::TI_INT32, 3u); break;
3024 case GL_INT_VEC4:V.type_descr = type_descriptor(cgv::type::info::TI_INT32, 4u); break;
3025 case GL_UNSIGNED_INT:V.type_descr = type_descriptor(cgv::type::info::TI_UINT32, false); break;
3026 case GL_UNSIGNED_INT_VEC2:V.type_descr = type_descriptor(cgv::type::info::TI_UINT32, 2u); break;
3027 case GL_UNSIGNED_INT_VEC3:V.type_descr = type_descriptor(cgv::type::info::TI_UINT32, 3u); break;
3028 case GL_UNSIGNED_INT_VEC4:V.type_descr = type_descriptor(cgv::type::info::TI_UINT32, 4u); break;
3029 case GL_DOUBLE: V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, false); break;
3030 case GL_DOUBLE_VEC2:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 2u); break;
3031 case GL_DOUBLE_VEC3:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 3u); break;
3032 case GL_DOUBLE_VEC4:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 4u); break;
3033 case GL_DOUBLE_MAT2:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 2u, 2u, false); break;
3034 case GL_DOUBLE_MAT3:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 3u, 3u, false); break;
3035 case GL_DOUBLE_MAT4:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 4u, 4u, false); break;
3036 case GL_DOUBLE_MAT2x3:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 2u, 3u, false); break;
3037 case GL_DOUBLE_MAT2x4:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 2u, 4u, false); break;
3038 case GL_DOUBLE_MAT3x2:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 3u, 2u, false); break;
3039 case GL_DOUBLE_MAT3x4:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 3u, 4u, false); break;
3040 case GL_DOUBLE_MAT4x2:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 4u, 2u, false); break;
3041 case GL_DOUBLE_MAT4x3:V.type_descr = type_descriptor(cgv::type::info::TI_FLT64, 4u, 3u, false); break;
3042 }
3043 return V;
3044}
3045
3046void 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
3047{
3048 GLint prog_id;
3049 spb.put_id(prog_id);
3050 // name buffer and sizeing informations
3051 std::vector<GLchar> buffer(256);
3052 GLint array_size = 0;
3053 GLenum type = 0;
3054 GLsizei actual_length = 0;
3055 // query number of active program variables of \c kind
3056 GLint num_active_variables = 0;
3057 glGetProgramiv(prog_id, kind == cgv::render::PVK_UNIFORM ? GL_ACTIVE_UNIFORMS : GL_ACTIVE_ATTRIBUTES, &num_active_variables);
3058 // for inspecting attribute values, one has to use the to be inspected program. Remember previously used program
3059 GLint old_prog_id = prog_id;
3060 if (kind == cgv::render::PVK_ATTRIBUTE) {
3061 glGetIntegerv(GL_CURRENT_PROGRAM, &old_prog_id);
3062 if (old_prog_id != prog_id)
3063 glUseProgram(prog_id);
3064 }
3065 // iterate all variables of \c kind
3066 for (int i = 0; i < num_active_variables; ++i) {
3067 // extract type and array information of program variable
3068 (kind == cgv::render::PVK_UNIFORM ? glGetActiveUniform : glGetActiveAttrib)(prog_id, i,
3069 GLsizei(buffer.size()), &actual_length, &array_size, &type, buffer.data());
3070 cgv::render::program_variable_info V = construct_program_variable(buffer, actual_length, array_size, type);
3071 // compute component count \c cnt, array element size \c s and total size \c S for all values in array
3072 size_t cnt = 1, s, S;
3073 if (get_value) {
3074 V.compute_sizes(cnt, s, S);
3075 V.current_value.resize(S);
3076 }
3077 // in case of attributes provide a read buffer to read array elements which write
3078 // always 4 components even if only one component is declared
3079 std::vector<char> read_buffer;
3080 if (kind == cgv::render::PVK_ATTRIBUTE && cnt != 4)
3081 read_buffer.resize(4 * s / cnt);
3082 for (unsigned j = 0; j < V.array_size; ++j) {
3083 // in case of array variables use per array element postfix to query location
3084 std::string postfix;
3085 if (V.array_size > 1)
3086 postfix += "[" + cgv::utils::to_string(j) + "]";
3087 // query location of variable in
3088 if (get_location || get_value)
3089 V.program_location = (kind == cgv::render::PVK_UNIFORM ? glGetUniformLocation : glGetAttribLocation)(
3090 prog_id, (V.name + postfix).c_str());
3091 // one is not allowed to query program attribute at location 0
3092 if (kind == cgv::render::PVK_ATTRIBUTE && V.program_location == 0) {
3093 V.current_value.clear();
3094 break;
3095 }
3096 if (!get_value)
3097 break;
3098 // let read_ptr point where program variable values should be queried to
3099 void* value_ptr = V.current_value.data() + j * s;
3100 void* read_ptr = read_buffer.empty() ? value_ptr : read_buffer.data();
3101 // switch over coordinate type to vary gl getter function
3102 switch (V.type_descr.coordinate_type) {
3105 if (kind == cgv::render::PVK_UNIFORM)
3106 glGetUniformiv(prog_id, V.program_location, (GLint*)(read_ptr));
3107 else
3108 glGetVertexAttribIiv(V.program_location, GL_CURRENT_VERTEX_ATTRIB, (GLint*)(read_ptr));
3109 break;
3111 if (kind == cgv::render::PVK_UNIFORM)
3112 glGetUniformuiv(prog_id, V.program_location, (GLuint*)(read_ptr));
3113 else
3114 glGetVertexAttribIuiv(V.program_location, GL_CURRENT_VERTEX_ATTRIB, (GLuint*)(read_ptr));
3115 break;
3117 if (kind == cgv::render::PVK_UNIFORM)
3118 glGetUniformfv(prog_id, V.program_location, (GLfloat*)(read_ptr));
3119 else
3120 glGetVertexAttribfv(V.program_location, GL_CURRENT_VERTEX_ATTRIB, (GLfloat*)(read_ptr));
3121 break;
3123 if (kind == cgv::render::PVK_UNIFORM)
3124 glGetUniformdv(prog_id, V.program_location, (GLdouble*)(read_ptr));
3125 else
3126 glGetVertexAttribdv(V.program_location, GL_CURRENT_VERTEX_ATTRIB, (GLdouble*)(read_ptr));
3127 break;
3128 }
3129 // in case we copied to read buffer, copy used value[s] to value buffer
3130 if (read_ptr != value_ptr)
3131 std::copy((const char*)read_ptr, (const char*)read_ptr + s, (char*)value_ptr);
3132 }
3133 // add inspected variable to list
3134 Vs.push_back(V);
3135 }
3136 // recover previously used program
3137 if (old_prog_id != prog_id)
3138 glUseProgram(old_prog_id);
3139}
3140
3141
3142int gl_context::get_uniform_location(const shader_program_base& spb, const std::string& name) const
3143{
3144 return glGetUniformLocation(get_gl_id(spb.handle), name.c_str());
3145}
3146
3147std::string value_type_index_to_string(type_descriptor td)
3148{
3149 std::string res = cgv::type::info::get_type_name(td.coordinate_type);
3150 switch (td.element_type) {
3151 case ET_VECTOR:
3152 res = std::string("vector<") + res + "," + cgv::utils::to_string(td.nr_rows) + ">";
3153 break;
3154 case ET_MATRIX:
3155 res = std::string("matrix<") + res + "," + cgv::utils::to_string(td.nr_rows) + "," + cgv::utils::to_string(td.nr_columns) + ">";
3156 if (td.is_row_major)
3157 res += "^T";
3158 default:
3159 break;
3160 }
3161 if (td.is_array)
3162 res += "[]";
3163 return res;
3164}
3165
3166bool gl_context::set_uniform_void(shader_program_base& spb, int loc, type_descriptor value_type, const void* value_ptr) const
3167{
3168 if (value_type.is_array) {
3169 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);
3170 return false;
3171 }
3172 if (!spb.handle) {
3173 error("gl_context::set_uniform_void() called on not created program", &spb);
3174 return false;
3175 }
3176 bool not_current = shader_program_stack.empty() || shader_program_stack.top() != &spb;
3177 if (not_current)
3178 glUseProgram(get_gl_id(spb.handle));
3179 bool res = true;
3180 switch (value_type.element_type) {
3181 case ET_VALUE:
3182 switch (value_type.coordinate_type) {
3183 case TI_BOOL: glUniform1i(loc, *reinterpret_cast<const bool*>(value_ptr) ? 1 : 0); break;
3184 case TI_UINT8: glUniform1ui(loc, *reinterpret_cast<const uint8_type*>(value_ptr)); break;
3185 case TI_UINT16: glUniform1ui(loc, *reinterpret_cast<const uint16_type*>(value_ptr)); break;
3186 case TI_UINT32: glUniform1ui(loc, *reinterpret_cast<const uint32_type*>(value_ptr)); break;
3187 case TI_INT8: glUniform1i(loc, *reinterpret_cast<const int8_type*>(value_ptr)); break;
3188 case TI_INT16: glUniform1i(loc, *reinterpret_cast<const int16_type*>(value_ptr)); break;
3189 case TI_INT32: glUniform1i(loc, *reinterpret_cast<const int32_type*>(value_ptr)); break;
3190 case TI_FLT32: glUniform1f(loc, *reinterpret_cast<const flt32_type*>(value_ptr)); break;
3191 case TI_FLT64: glUniform1d(loc, *reinterpret_cast<const flt64_type*>(value_ptr)); break;
3192 default:
3193 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3194 res = false; break;
3195 }
3196 break;
3197 case ET_VECTOR:
3198 switch (value_type.nr_rows) {
3199 case 2:
3200 switch (value_type.coordinate_type) {
3201 case TI_BOOL: glUniform2i(loc, reinterpret_cast<const bool*>(value_ptr)[0] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[1] ? 1 : 0); break;
3202 case TI_UINT8: glUniform2ui(loc, reinterpret_cast<const uint8_type*> (value_ptr)[0], reinterpret_cast<const uint8_type*> (value_ptr)[1]); break;
3203 case TI_UINT16: glUniform2ui(loc, reinterpret_cast<const uint16_type*>(value_ptr)[0], reinterpret_cast<const uint16_type*>(value_ptr)[1]); break;
3204 case TI_UINT32: glUniform2ui(loc, reinterpret_cast<const uint32_type*>(value_ptr)[0], reinterpret_cast<const uint32_type*>(value_ptr)[1]); break;
3205 case TI_INT8: glUniform2i(loc, reinterpret_cast<const int8_type*> (value_ptr)[0], reinterpret_cast<const int8_type*> (value_ptr)[1]); break;
3206 case TI_INT16: glUniform2i(loc, reinterpret_cast<const int16_type*> (value_ptr)[0], reinterpret_cast<const int16_type*> (value_ptr)[1]); break;
3207 case TI_INT32: glUniform2i(loc, reinterpret_cast<const int32_type*> (value_ptr)[0], reinterpret_cast<const int32_type*> (value_ptr)[1]); break;
3208 case TI_FLT32: glUniform2f(loc, reinterpret_cast<const flt32_type*> (value_ptr)[0], reinterpret_cast<const flt32_type*> (value_ptr)[1]); break;
3209 case TI_FLT64: glUniform2d(loc, reinterpret_cast<const flt64_type*> (value_ptr)[0], reinterpret_cast<const flt64_type*> (value_ptr)[1]); break;
3210 default:
3211 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3212 res = false; break;
3213 }
3214 break;
3215 case 3:
3216 switch (value_type.coordinate_type) {
3217 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;
3218 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;
3219 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;
3220 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;
3221 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;
3222 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;
3223 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;
3224 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;
3225 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;
3226 default:
3227 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3228 res = false; break;
3229 }
3230 break;
3231 case 4:
3232 switch (value_type.coordinate_type) {
3233 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;
3234 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;
3235 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;
3236 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;
3237 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;
3238 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;
3239 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;
3240 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;
3241 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;
3242 default:
3243 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3244 res = false; break;
3245 }
3246 break;
3247 }
3248 break;
3249 case ET_MATRIX:
3250 switch (value_type.coordinate_type) {
3251 case TI_FLT32:
3252 switch (value_type.nr_rows) {
3253 case 2:
3254 switch (value_type.nr_columns) {
3255 case 2: glUniformMatrix2fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3256 case 3: glUniformMatrix2x3fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3257 case 4: glUniformMatrix2x4fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3258 default:
3259 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3260 res = false; break;
3261 }
3262 break;
3263 case 3:
3264 switch (value_type.nr_columns) {
3265 case 2: glUniformMatrix3x2fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3266 case 3: glUniformMatrix3fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3267 case 4: glUniformMatrix3x4fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3268 default:
3269 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3270 res = false; break;
3271 }
3272 break;
3273 case 4:
3274 switch (value_type.nr_columns) {
3275 case 2: glUniformMatrix4x2fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3276 case 3: glUniformMatrix4x3fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3277 case 4: glUniformMatrix4fv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt32_type*> (value_ptr)); break;
3278 default:
3279 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3280 res = false; break;
3281 }
3282 break;
3283 default:
3284 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of rows outside [2,..,4].", &spb);
3285 res = false; break;
3286 }
3287 break;
3288 case TI_FLT64:
3289 switch (value_type.nr_rows) {
3290 case 2:
3291 switch (value_type.nr_columns) {
3292 case 2: glUniformMatrix2dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3293 case 3: glUniformMatrix2x3dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3294 case 4: glUniformMatrix2x4dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3295 default:
3296 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3297 res = false; break;
3298 }
3299 break;
3300 case 3:
3301 switch (value_type.nr_columns) {
3302 case 2: glUniformMatrix3x2dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3303 case 3: glUniformMatrix3dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3304 case 4: glUniformMatrix3x4dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3305 default:
3306 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3307 res = false; break;
3308 }
3309 break;
3310 case 4:
3311 switch (value_type.nr_columns) {
3312 case 2: glUniformMatrix4x2dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3313 case 3: glUniformMatrix4x3dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3314 case 4: glUniformMatrix4dv(loc, 1, !value_type.is_row_major, reinterpret_cast<const flt64_type*> (value_ptr)); break;
3315 default:
3316 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..,4].", &spb);
3317 res = false; break;
3318 }
3319 break;
3320 default:
3321 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") matrix number of rows outside [2,..,4].", &spb);
3322 res = false; break;
3323 }
3324 break;
3325 default:
3326 error(std::string("gl_context::set_uniform_void(") + value_type_index_to_string(value_type) + ") non float coordinate type not supported.", &spb);
3327 res = false; break;
3328 }
3329 break;
3330 }
3331 if (not_current)
3332 glUseProgram(shader_program_stack.empty() ? 0 : get_gl_id(shader_program_stack.top()->handle));
3333
3334 if (check_gl_error("gl_context::set_uniform_void()", &spb))
3335 res = false;
3336 return res;
3337}
3338
3339bool 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
3340{
3341 if (!value_type.is_array) {
3342 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") non array type not allowed.", &spb);
3343 return false;
3344 }
3345 if (!spb.handle) {
3346 error("gl_context::set_uniform_array_void() called on not created program", &spb);
3347 return false;
3348 }
3349 bool not_current = shader_program_stack.empty() || shader_program_stack.top() != &spb;
3350 if (not_current)
3351 glUseProgram(get_gl_id(spb.handle));
3352 bool res = true;
3353 switch (value_type.coordinate_type) {
3354 case TI_INT32:
3355 switch (value_type.element_type) {
3356 case ET_VALUE:
3357 glUniform1iv(loc, GLsizei(nr_elements), reinterpret_cast<const int32_type*>(value_ptr));
3358 break;
3359 case ET_VECTOR:
3360 switch (value_type.nr_rows) {
3361 case 2: glUniform2iv(loc, GLsizei(nr_elements), reinterpret_cast<const int32_type*>(value_ptr)); break;
3362 case 3: glUniform3iv(loc, GLsizei(nr_elements), reinterpret_cast<const int32_type*>(value_ptr)); break;
3363 case 4: glUniform4iv(loc, GLsizei(nr_elements), reinterpret_cast<const int32_type*>(value_ptr)); break;
3364 default:
3365 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") vector dimension outside [2,..4].", &spb);
3366 res = false;
3367 break;
3368 }
3369 break;
3370 case ET_MATRIX:
3371 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") type not supported.", &spb);
3372 res = false;
3373 break;
3374 }
3375 break;
3376 case TI_UINT32:
3377 switch (value_type.element_type) {
3378 case ET_VALUE:
3379 glUniform1uiv(loc, GLsizei(nr_elements), reinterpret_cast<const uint32_type*>(value_ptr));
3380 break;
3381 case ET_VECTOR:
3382 switch (value_type.nr_rows) {
3383 case 2: glUniform2uiv(loc, GLsizei(nr_elements), reinterpret_cast<const uint32_type*>(value_ptr)); break;
3384 case 3: glUniform3uiv(loc, GLsizei(nr_elements), reinterpret_cast<const uint32_type*>(value_ptr)); break;
3385 case 4: glUniform4uiv(loc, GLsizei(nr_elements), reinterpret_cast<const uint32_type*>(value_ptr)); break;
3386 default:
3387 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") vector dimension outside [2,..4].", &spb);
3388 res = false;
3389 break;
3390 }
3391 break;
3392 case ET_MATRIX:
3393 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") type not supported.", &spb);
3394 res = false;
3395 break;
3396 }
3397 break;
3398 case TI_FLT32:
3399 switch (value_type.element_type) {
3400 case ET_VALUE:
3401 glUniform1fv(loc, GLsizei(nr_elements), reinterpret_cast<const flt32_type*>(value_ptr));
3402 break;
3403 case ET_VECTOR:
3404 switch (value_type.nr_rows) {
3405 case 2: glUniform2fv(loc, GLsizei(nr_elements), reinterpret_cast<const flt32_type*>(value_ptr)); break;
3406 case 3: glUniform3fv(loc, GLsizei(nr_elements), reinterpret_cast<const flt32_type*>(value_ptr)); break;
3407 case 4: glUniform4fv(loc, GLsizei(nr_elements), reinterpret_cast<const flt32_type*>(value_ptr)); break;
3408 default:
3409 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") vector dimension outside [2,..4].", &spb);
3410 res = false;
3411 break;
3412 }
3413 break;
3414 case ET_MATRIX:
3415 switch (value_type.nr_rows) {
3416 case 2:
3417 switch (value_type.nr_columns) {
3418 case 2: glUniformMatrix2fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3419 case 3: glUniformMatrix2x3fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3420 case 4: glUniformMatrix2x4fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3421 default:
3422 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..4].", &spb);
3423 res = false;
3424 break;
3425 }
3426 break;
3427 case 3:
3428 switch (value_type.nr_columns) {
3429 case 2: glUniformMatrix3x2fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3430 case 3: glUniformMatrix3fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3431 case 4: glUniformMatrix3x4fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3432 default:
3433 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..4].", &spb);
3434 res = false;
3435 break;
3436 }
3437 break;
3438 case 4:
3439 switch (value_type.nr_columns) {
3440 case 2: glUniformMatrix4x2fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3441 case 3: glUniformMatrix4x3fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3442 case 4: glUniformMatrix4fv(loc, GLsizei(nr_elements), value_type.is_row_major, reinterpret_cast<const flt32_type*>(value_ptr)); break;
3443 default:
3444 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") matrix number of columns outside [2,..4].", &spb);
3445 res = false;
3446 break;
3447 }
3448 break;
3449 default:
3450 error(std::string("gl_context::set_uniform_array_void(") + value_type_index_to_string(value_type) + ") matrix number of rows outside [2,..4].", &spb);
3451 res = false;
3452 break;
3453 }
3454 break;
3455 }
3456 break;
3457 default:
3458 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);
3459 res = false;
3460 break;
3461 }
3462 if (check_gl_error("gl_context::set_uniform_array_void()", &spb))
3463 res = false;
3464
3465 if (not_current)
3466 glUseProgram(shader_program_stack.empty() ? 0 : get_gl_id(shader_program_stack.top()->handle));
3467
3468 return res;
3469}
3470
3471int gl_context::get_uniform_block_index(const shader_program_base& spb, const std::string& name) const
3472{
3473 return glGetUniformBlockIndex(get_gl_id(spb.handle), name.c_str());
3474}
3475
3476bool gl_context::set_uniform_block_binding(shader_program_base& spb, int index, int binding) const
3477{
3478 if(!spb.handle) {
3479 error("gl_context::set_uniform_block_binding() called on not created program", &spb);
3480 return false;
3481 }
3482 glUniformBlockBinding(get_gl_id(spb.handle), index, binding);
3483 return check_gl_error("gl_context::set_uniform_block_binding()", &spb);
3484}
3485
3486int gl_context::get_attribute_location(const shader_program_base& spb, const std::string& name) const
3487{
3488 return glGetAttribLocation(get_gl_id(spb.handle), name.c_str());
3489}
3490
3491bool gl_context::set_attribute_void(shader_program_base& spb, int loc, type_descriptor value_type, const void* value_ptr) const
3492{
3493 if (!spb.handle) {
3494 error("gl_context::set_attribute_void() called on not created program", &spb);
3495 return false;
3496 }
3497 bool not_current = shader_program_stack.empty() || shader_program_stack.top() != &spb;
3498 if (not_current)
3499 glUseProgram(get_gl_id(spb.handle));
3500 bool res = true;
3501 switch (value_type.element_type) {
3502 case ET_VALUE:
3503 switch (value_type.coordinate_type) {
3504 case TI_BOOL: glVertexAttrib1s(loc, *reinterpret_cast<const bool*>(value_ptr) ? 1 : 0); break;
3505 case TI_INT8: glVertexAttrib1s(loc, *reinterpret_cast<const int8_type*>(value_ptr)); break;
3506 case TI_INT16: glVertexAttrib1s(loc, *reinterpret_cast<const int16_type*>(value_ptr)); break;
3507 case TI_INT32: glVertexAttribI1i(loc, *reinterpret_cast<const int32_type*>(value_ptr)); break;
3508 case TI_UINT8: glVertexAttrib1s(loc, *reinterpret_cast<const uint8_type*>(value_ptr)); break;
3509 case TI_UINT16: glVertexAttribI1ui(loc, *reinterpret_cast<const uint16_type*>(value_ptr)); break;
3510 case TI_UINT32: glVertexAttribI1ui(loc, *reinterpret_cast<const uint32_type*>(value_ptr)); break;
3511 case TI_FLT32: glVertexAttrib1f(loc, *reinterpret_cast<const flt32_type*>(value_ptr)); break;
3512 case TI_FLT64: glVertexAttrib1d(loc, *reinterpret_cast<const flt64_type*>(value_ptr)); break;
3513 default:
3514 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") type not supported!", &spb);
3515 res = false;
3516 break;
3517 }
3518 break;
3519 case ET_VECTOR:
3520 switch (value_type.nr_rows) {
3521 case 2:
3522 switch (value_type.coordinate_type) {
3523 case TI_BOOL: glVertexAttrib2s(loc, reinterpret_cast<const bool*>(value_ptr)[0] ? 1 : 0, reinterpret_cast<const bool*>(value_ptr)[1] ? 1 : 0); break;
3524 case TI_UINT8: glVertexAttrib2s(loc, reinterpret_cast<const uint8_type*> (value_ptr)[0], reinterpret_cast<const uint8_type*> (value_ptr)[1]); break;
3525 case TI_UINT16: glVertexAttribI2ui(loc, reinterpret_cast<const uint16_type*>(value_ptr)[0], reinterpret_cast<const uint16_type*>(value_ptr)[1]); break;
3526 case TI_UINT32: glVertexAttribI2ui(loc, reinterpret_cast<const uint32_type*>(value_ptr)[0], reinterpret_cast<const uint32_type*>(value_ptr)[1]); break;
3527 case TI_INT8: glVertexAttrib2s(loc, reinterpret_cast<const int8_type*> (value_ptr)[0], reinterpret_cast<const int8_type*> (value_ptr)[1]); break;
3528 case TI_INT16: glVertexAttrib2s(loc, reinterpret_cast<const int16_type*> (value_ptr)[0], reinterpret_cast<const int16_type*> (value_ptr)[1]); break;
3529 case TI_INT32: glVertexAttribI2i(loc, reinterpret_cast<const int32_type*> (value_ptr)[0], reinterpret_cast<const int32_type*> (value_ptr)[1]); break;
3530 case TI_FLT32: glVertexAttrib2f(loc, reinterpret_cast<const flt32_type*> (value_ptr)[0], reinterpret_cast<const flt32_type*> (value_ptr)[1]); break;
3531 case TI_FLT64: glVertexAttrib2d(loc, reinterpret_cast<const flt64_type*> (value_ptr)[0], reinterpret_cast<const flt64_type*> (value_ptr)[1]); break;
3532 default:
3533 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3534 res = false;
3535 break;
3536 }
3537 break;
3538 case 3:
3539 switch (value_type.coordinate_type) {
3540 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;
3541 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;
3542 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;
3543 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;
3544 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;
3545 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;
3546 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;
3547 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;
3548 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;
3549 default:
3550 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3551 res = false; break;
3552 }
3553 break;
3554 case 4:
3555 switch (value_type.coordinate_type) {
3556 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;
3557 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;
3558 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;
3559 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;
3560 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;
3561 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;
3562 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;
3563 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;
3564 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;
3565 default:
3566 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") unsupported coordinate type.", &spb);
3567 res = false;
3568 break;
3569 }
3570 break;
3571 default:
3572 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") vector dimension outside [2..4]", &spb);
3573 res = false;
3574 break;
3575 }
3576 break;
3577 case ET_MATRIX:
3578 error(std::string("gl_context::set_attribute_void(") + value_type_index_to_string(value_type) + ") matrix type not supported!", &spb);
3579 res = false;
3580 break;
3581 }
3582 if (not_current)
3583 glUseProgram(shader_program_stack.empty() ? 0 : get_gl_id(shader_program_stack.top()->handle));
3584
3585 if (check_gl_error("gl_context::set_uniform_array_void()", &spb))
3586 res = false;
3587 return res;
3588}
3589
3590bool gl_context::attribute_array_binding_create(attribute_array_binding_base& aab) const
3591{
3592 if (!GLEW_VERSION_3_0) {
3593 error("gl_context::attribute_array_binding_create() array attribute bindings not supported", &aab);
3594 return false;
3595 }
3596 GLuint a_id;
3597 glGenVertexArrays(1, &a_id);
3598 if (a_id == -1) {
3599 error(std::string("gl_context::attribute_array_binding_create(): ") + gl_error(), &aab);
3600 return false;
3601 }
3602 aab.ctx_ptr = this;
3603 aab.handle = get_handle(a_id);
3604 return true;
3605}
3606
3607bool gl_context::attribute_array_binding_destruct(attribute_array_binding_base& aab) const
3608{
3610 glBindVertexArray(0);
3611 if (!context::attribute_array_binding_destruct(aab))
3612 return false;
3613 if (!aab.handle) {
3614 error("gl_context::attribute_array_binding_destruct(): called on not created attribute array binding", &aab);
3615 return false;
3616 }
3617 GLuint a_id = get_gl_id(aab.handle);
3618 glDeleteVertexArrays(1, &a_id);
3619 aab.handle = 0;
3620 aab.ctx_ptr = 0;
3621 return !check_gl_error("gl_context::attribute_array_binding_destruct");
3622}
3623
3624bool gl_context::attribute_array_binding_enable(attribute_array_binding_base& aab)
3625{
3626 if (!context::attribute_array_binding_enable(aab))
3627 return false;
3628 glBindVertexArray(get_gl_id(aab.handle));
3629 return !check_gl_error("gl_context::attribute_array_binding_enable");
3630}
3631
3632bool gl_context::attribute_array_binding_disable(attribute_array_binding_base& aab)
3633{
3634 if (!context::attribute_array_binding_disable(aab))
3635 return false;
3637 glBindVertexArray(0);
3638 else
3639 glBindVertexArray(get_gl_id(attribute_array_binding_stack.top()->handle));
3640 return true;
3641}
3642
3643bool gl_context::set_element_array(attribute_array_binding_base* aab, const vertex_buffer_base* vbb) const
3644{
3645 if (!vbb) {
3646 error("gl_context::set_element_array(): called without a vertex buffer object", aab);
3647 return false;
3648 }
3649 if (!vbb->handle) {
3650 error("gl_context::set_element_array(): called with not created vertex buffer object", vbb);
3651 return false;
3652 }
3653 if (vbb->type != VBT_INDICES) {
3654 std::cout << "gl_context::set_element_array() : called on vertex buffer object that is not of type VBT_INDICES" << std::endl;
3655// error("gl_context::set_element_array(): called on vertex buffer object that is not of type VBT_INDICES", vbb);
3656// return false;
3657 }
3658 if (aab) {
3659 if (!aab->handle) {
3660 error("gl_context::set_element_array(): called on not created attribute array binding", aab);
3661 return false;
3662 }
3663 }
3664 // enable vertex array
3665 bool not_current = attribute_array_binding_stack.empty() || attribute_array_binding_stack.top() != aab;
3666 if (aab && not_current)
3667 glBindVertexArray(get_gl_id(aab->handle));
3668
3669 // bind buffer to element array
3670 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, get_gl_id(vbb->handle));
3671
3672 if (aab && not_current)
3673 glBindVertexArray(attribute_array_binding_stack.empty() ? 0 : get_gl_id(attribute_array_binding_stack.top()->handle));
3674
3675 return !check_gl_error("gl_context::set_element_array_void()", aab);
3676}
3677
3678
3679bool 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
3680{
3681 if (value_type == ET_MATRIX) {
3682 error("gl_context::set_attribute_array_void(): called with matrix elements not supported", aab);
3683 return false;
3684 }
3685 if (vbb) {
3686 if (!vbb->handle) {
3687 error("gl_context::set_attribute_array_void(): called with not created vertex buffer object", vbb);
3688 return false;
3689 }
3690 }
3691 if (aab) {
3692 if (!aab->handle) {
3693 error("gl_context::set_attribute_array_void(): called on not created attribute array binding", aab);
3694 return false;
3695 }
3696 }
3697
3698 bool not_current = attribute_array_binding_stack.empty() || attribute_array_binding_stack.top() != aab;
3699 if (aab && not_current)
3700 glBindVertexArray(get_gl_id(aab->handle));
3701
3702 if (vbb)
3703 glBindBuffer(GL_ARRAY_BUFFER, get_gl_id(vbb->handle));
3704
3705 bool res = true;
3706 unsigned n = value_type.element_type == ET_VALUE ? 1 : value_type.nr_rows;
3707 switch (value_type.coordinate_type) {
3708 case TI_INT8: value_type.normalize ? glVertexAttribPointer(loc, n, GL_BYTE, value_type.normalize, stride, ptr) : glVertexAttribIPointer(loc, n, GL_BYTE, stride, ptr); break;
3709 case TI_INT16: value_type.normalize ? glVertexAttribPointer(loc, n, GL_SHORT, value_type.normalize, stride, ptr) : glVertexAttribIPointer(loc, n, GL_SHORT, stride, ptr); break;
3710 case TI_INT32: value_type.normalize ? glVertexAttribPointer(loc, n, GL_INT, value_type.normalize, stride, ptr) : glVertexAttribIPointer(loc, n, GL_INT, stride, ptr); break;
3711 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;
3712 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;
3713 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;
3714 case TI_FLT32: glVertexAttribPointer(loc, n, GL_FLOAT, value_type.normalize, stride, ptr); break;
3715 case TI_FLT64:
3716 if (GLEW_VERSION_4_1)
3717 glVertexAttribLPointer(loc, n, GL_DOUBLE, stride, ptr);
3718 else {
3719 error("gl_context::set_attribute_array_void(): called with coordinates of type double only supported starting with OpenGL 4.1", aab);
3720 res = false;
3721 }
3722 break;
3723 default:
3724 error("gl_context::set_attribute_array_void(): called with unsupported coordinate type", aab);
3725 res = false;
3726 }
3727
3728 if (res)
3729 glEnableVertexAttribArray(loc);
3730
3731 if (vbb)
3732 glBindBuffer(GL_ARRAY_BUFFER, 0);
3733
3734 if (aab && not_current)
3735 glBindVertexArray(attribute_array_binding_stack.empty() ? 0 : get_gl_id(attribute_array_binding_stack.top()->handle));
3736
3737
3738 return res && !check_gl_error("gl_context::set_attribute_array_void()", aab);
3739}
3740
3741bool gl_context::enable_attribute_array(attribute_array_binding_base* aab, int loc, bool do_enable) const
3742{
3743 bool not_current = attribute_array_binding_stack.empty() || attribute_array_binding_stack.top() != aab;
3744 if (aab) {
3745 if (!aab->handle) {
3746 error("gl_context::enable_attribute_array(): called on not created attribute array binding", aab);
3747 return false;
3748 }
3749 if (not_current)
3750 glBindVertexArray(get_gl_id(aab->handle));
3751 }
3752
3753 if (do_enable)
3754 glEnableVertexAttribArray(loc);
3755 else
3756 glDisableVertexAttribArray(loc);
3757
3758 if (aab && not_current)
3759 glBindVertexArray(attribute_array_binding_stack.empty() ? 0 : get_gl_id(attribute_array_binding_stack.top()->handle));
3760
3761 return !check_gl_error("gl_context::enable_attribute_array()");
3762}
3763
3764bool gl_context::is_attribute_array_enabled(const attribute_array_binding_base* aab, int loc) const
3765{
3766 bool not_current = attribute_array_binding_stack.empty() || attribute_array_binding_stack.top() != aab;
3767 if (aab) {
3768 if (!aab->handle) {
3769 error("gl_context::is_attribute_array_enabled(): called on not created attribute array binding", aab);
3770 return false;
3771 }
3772 if (not_current)
3773 glBindVertexArray(get_gl_id(aab->handle));
3774 }
3775
3776 GLint res;
3777 glGetVertexAttribiv(loc, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &res);
3778
3779 if (aab && not_current)
3780 glBindVertexArray(attribute_array_binding_stack.empty() ? 0 : get_gl_id(attribute_array_binding_stack.top()->handle));
3781
3782 return res == GL_TRUE;
3783}
3784
3785GLenum buffer_target(VertexBufferType vbt)
3786{
3787 static GLenum buffer_targets[] = {
3788 GL_ARRAY_BUFFER,
3789 GL_ELEMENT_ARRAY_BUFFER,
3790 GL_TEXTURE_BUFFER,
3791 GL_UNIFORM_BUFFER,
3792 GL_TRANSFORM_FEEDBACK_BUFFER,
3793 GL_SHADER_STORAGE_BUFFER,
3794 GL_ATOMIC_COUNTER_BUFFER,
3795 GL_DRAW_INDIRECT_BUFFER
3796 };
3797 return buffer_targets[vbt];
3798}
3799
3800GLenum buffer_usage(VertexBufferUsage vbu)
3801{
3802 static GLenum buffer_usages[] = {
3803 GL_STREAM_DRAW,
3804 GL_STREAM_READ,
3805 GL_STREAM_COPY,
3806 GL_STATIC_DRAW,
3807 GL_STATIC_READ,
3808 GL_STATIC_COPY,
3809 GL_DYNAMIC_DRAW,
3810 GL_DYNAMIC_READ,
3811 GL_DYNAMIC_COPY
3812 };
3813 return buffer_usages[vbu];
3814}
3815
3816bool gl_context::vertex_buffer_bind(const vertex_buffer_base& vbb, VertexBufferType _type, unsigned _idx) const
3817{
3818 if (_idx == unsigned(-1))
3819 glBindBuffer(buffer_target(_type), get_gl_id(vbb.handle));
3820 else
3821 glBindBufferBase(buffer_target(_type), _idx, get_gl_id(vbb.handle));
3822 return !check_gl_error("gl_context::vertex_buffer_bind", &vbb);
3823}
3824
3825bool gl_context::vertex_buffer_unbind(const vertex_buffer_base& vbb, VertexBufferType _type, unsigned _idx) const {
3826 if(_idx == unsigned(-1))
3827 glBindBuffer(buffer_target(_type), 0);
3828 else
3829 glBindBufferBase(buffer_target(_type), _idx, 0);
3830 return !check_gl_error("gl_context::vertex_buffer_unbind", &vbb);
3831}
3832
3833bool gl_context::vertex_buffer_create(vertex_buffer_base& vbb, const void* array_ptr, size_t size_in_bytes) const
3834{
3835 if (!GLEW_VERSION_2_0) {
3836 error("gl_context::vertex_buffer_create() vertex buffer objects not supported", &vbb);
3837 return false;
3838 }
3839 GLuint b_id;
3840 glGenBuffers(1, &b_id);
3841 if (b_id == -1) {
3842 error(std::string("gl_context::vertex_buffer_create(): ") + gl_error(), &vbb);
3843 return false;
3844 }
3845 vbb.handle = get_handle(b_id);
3846 glBindBuffer(buffer_target(vbb.type), b_id);
3847 glBufferData(buffer_target(vbb.type), size_in_bytes, array_ptr, buffer_usage(vbb.usage));
3848 glBindBuffer(buffer_target(vbb.type), 0);
3849 return !check_gl_error("gl_context::vertex_buffer_create", &vbb);
3850}
3851
3852bool gl_context::vertex_buffer_resize(vertex_buffer_base& vbb, const void* array_ptr, size_t size_in_bytes) const {
3853 if(!vbb.handle) {
3854 error("gl_context::vertex_buffer_resize() vertex buffer object must be created before", &vbb);
3855 return false;
3856 }
3857 GLuint b_id = get_gl_id(vbb.handle);
3858 glBindBuffer(buffer_target(vbb.type), b_id);
3859 glBufferData(buffer_target(vbb.type), size_in_bytes, array_ptr, buffer_usage(vbb.usage));
3860 glBindBuffer(buffer_target(vbb.type), 0);
3861 return !check_gl_error("gl_context::vertex_buffer_resize", &vbb);
3862}
3863
3864bool gl_context::vertex_buffer_clear(vertex_buffer_base& vbb, size_t offset, size_t size_in_bytes) const
3865{
3866 if (!vbb.handle) {
3867 error("gl_context::vertex_buffer_clear() vertex buffer object must be created before", &vbb);
3868 return false;
3869 }
3870 GLuint b_id = get_gl_id(vbb.handle);
3871 glBindBuffer(buffer_target(vbb.type), b_id);
3872 glClearBufferSubData(buffer_target(vbb.type), GL_R8, offset, size_in_bytes, GL_RED, GL_UNSIGNED_BYTE, NULL);
3873 glBindBuffer(buffer_target(vbb.type), 0);
3874 return !check_gl_error("gl_context::vertex_buffer_clear", &vbb);
3875}
3876
3877bool gl_context::vertex_buffer_replace(vertex_buffer_base& vbb, size_t offset, size_t size_in_bytes, const void* array_ptr) const
3878{
3879 if (!vbb.handle) {
3880 error("gl_context::vertex_buffer_replace() vertex buffer object must be created before", &vbb);
3881 return false;
3882 }
3883 GLuint b_id = get_gl_id(vbb.handle);
3884 glBindBuffer(buffer_target(vbb.type), b_id);
3885 glBufferSubData(buffer_target(vbb.type), offset, size_in_bytes, array_ptr);
3886 glBindBuffer(buffer_target(vbb.type), 0);
3887 return !check_gl_error("gl_context::vertex_buffer_replace", &vbb);
3888}
3889
3890bool 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
3891{
3892 if (!src.handle || !target.handle) {
3893 error("gl_context::vertex_buffer_copy() source and destination vertex buffer objects must have been created before", &src);
3894 return false;
3895 }
3896 GLuint b_id = get_gl_id(src.handle);
3897 glBindBuffer(GL_COPY_READ_BUFFER, get_gl_id(src.handle));
3898 glBindBuffer(GL_COPY_WRITE_BUFFER, get_gl_id(target.handle));
3899 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, src_offset, target_offset, size_in_bytes);
3900 glBindBuffer(GL_COPY_READ_BUFFER, 0);
3901 glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
3902 return !check_gl_error("gl_context::vertex_buffer_copy", &src);
3903
3904}
3905
3906bool gl_context::vertex_buffer_copy_back(const vertex_buffer_base& vbb, size_t offset, size_t size_in_bytes, void* array_ptr) const
3907{
3908 if (!vbb.handle) {
3909 error("gl_context::vertex_buffer_copy_back() vertex buffer object must be created", &vbb);
3910 return false;
3911 }
3912 GLuint b_id = get_gl_id(vbb.handle);
3913 GLuint bind_point = GL_COPY_READ_BUFFER;
3914 switch (vbb.type) {
3915 case cgv::render::VBT_VERTICES: bind_point = GL_ARRAY_BUFFER; break;
3916 case cgv::render::VBT_INDICES: bind_point = GL_ELEMENT_ARRAY_BUFFER; break;
3917 case cgv::render::VBT_TEXTURE: bind_point = GL_TEXTURE_BUFFER; break;
3918 case cgv::render::VBT_UNIFORM: bind_point = GL_UNIFORM_BUFFER; break;
3919 case cgv::render::VBT_FEEDBACK: bind_point = GL_TRANSFORM_FEEDBACK_BUFFER; break;
3920 case cgv::render::VBT_STORAGE: bind_point = GL_SHADER_STORAGE_BUFFER; break;
3921 case cgv::render::VBT_ATOMIC_COUNTER: bind_point = GL_ATOMIC_COUNTER_BUFFER; break;
3922 case cgv::render::VBT_INDIRECT: bind_point = GL_DRAW_INDIRECT_BUFFER; break;
3923 }
3924 glBindBuffer(bind_point, b_id);
3925 glGetBufferSubData(bind_point, offset, size_in_bytes, array_ptr);
3926 glBindBuffer(bind_point, 0);
3927 return !check_gl_error("gl_context::vertex_buffer_copy_back", &vbb);
3928}
3929
3930bool gl_context::vertex_buffer_destruct(vertex_buffer_base& vbb) const
3931{
3932 if (vbb.handle) {
3933 GLuint b_id = get_gl_id(vbb.handle);
3934 glDeleteBuffers(1, &b_id);
3935 vbb.handle = 0;
3936 vbb.ctx_ptr = 0;
3937 return !check_gl_error("gl_context::vertex_buffer_destruct");
3938 }
3939 else {
3940 error("gl_context::vertex_buffer_destruct(): called on not created vertex buffer", &vbb);
3941 return false;
3942 }
3943}
3944
3945
3946 }
3947 }
3948}
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
unsigned int get_nr_children() const
return the number of children
Definition group.cxx:29
base_ptr get_child(unsigned int i) const
return the i-th child
Definition group.cxx:33
complete implementation of method actions that only call one method when entering a node
Definition action.h:187
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
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
T & z()
return third component
Definition fvec.h:150
T & y()
return second component
Definition fvec.h:146
T * data()
return a pointer to the underlying array serving as component storage
Definition fvec.h:166
T & x()
return first component
Definition fvec.h:142
A matrix type (full column major storage) The matrix can be loaded directly into OpenGL without need ...
Definition mat.h:208
virtual font_face_ptr get_font_face(cgv::media::font::FontFaceAttributes ffa) const =0
return a pointer to a font face
>simple class to hold the properties of a light source
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...
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
static bool set_global_attribute_array(const context &ctx, int loc, const vertex_buffer &vbo, type_descriptor td, size_t size, size_t offset, unsigned stride=0)
point array of vertex attribute at location loc to vertex buffer array array stored in CPU memory; in...
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:1877
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:1032
virtual void mul_modelview_matrix(const dmat4 &MV)
multiply given matrix from right to current modelview matrix
Definition context.cxx:1957
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:2057
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:682
float current_font_size
store current font size
Definition context.h:841
bool enable_vsync
whether vsync should be enabled
Definition context.h:744
virtual void set_buffer_mask(BufferMask mask)
set the buffer mask for depth and color buffers
Definition context.cxx:1926
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:732
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:1885
virtual void on_lights_changed()
helper function to send light update events
Definition context.cxx:738
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:1813
std::stack< shader_program_base * > shader_program_stack
stack of currently enabled shader programs
Definition context.h:777
bool is_light_source_enabled(void *handle)
check whether light source is enabled
Definition context.cxx:782
virtual void disable_depth_test()
disable the depth test
Definition context.cxx:1839
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:806
void pop_depth_test_state()
pop the top of the current depth test state from the stack
Definition context.cxx:1817
void tesselate_unit_sphere(int resolution=25, bool flip_normals=false, bool edges=false)
tesselate a sphere of radius 1
Definition context.cxx:1463
virtual RenderPassFlags get_render_pass_flags() const
return the current render pass flags
Definition context.cxx:864
void tesselate_unit_cylinder(int resolution=25, bool flip_normals=false, bool edges=false)
tesselate a cylinder of radius 1
Definition context.cxx:1371
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:1826
size_t get_nr_enabled_light_sources() const
return the number of light sources
Definition context.cxx:771
virtual unsigned int get_height() const =0
return the height of the window
virtual void disable_blending()
disable blending
Definition context.cxx:1909
BufferMask get_buffer_mask() const
return the current buffer mask
Definition context.cxx:1922
void push_cull_state()
push a copy of the current culling state onto the stack saved attributes: cull face enablement,...
Definition context.cxx:1843
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:1037
std::stack< dmat4 > modelview_matrix_stack
keep two matrix stacks for model view and projection matrices
Definition context.h:771
virtual void pop_window_transformation_array()
restore previous viewport and depth range arrays defining the window transformations
Definition context.cxx:2024
virtual void set_color_mask(bvec4 flags)
set the color buffer mask
Definition context.cxx:1943
virtual void set_material(const cgv::media::illum::surface_material &mat)
set the current material
Definition context.cxx:1776
DepthTestState get_depth_test_state() const
return the current depth test state
Definition context.cxx:1822
bool auto_set_material_in_current_shader_program
whether to automatically set material in current shader program, defaults to true
Definition context.h:734
void set_current_lights(shader_program &prog) const
set the shader program lights to the currently enabled lights
Definition context.cxx:723
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:791
void tesselate_unit_disk(int resolution=25, bool flip_normals=false, bool edges=false)
tesselate a circular disk of radius 1
Definition context.cxx:1295
virtual void enable_depth_test()
enable the depth test
Definition context.cxx:1835
bool support_compatibility_mode
whether to support view and lighting management of compatibility mode, defaults to true
Definition context.h:738
void set_current_gamma(shader_program &prog) const
set the shader program gamma values
Definition context.cxx:1699
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:1974
std::stack< attribute_array_binding_base * > attribute_array_binding_stack
stack of currently enabled attribute array binding
Definition context.h:791
BlendState get_blend_state() const
return the current blend state
Definition context.cxx:1869
virtual void set_cull_state(CullingMode culling_mode)
set the culling state
Definition context.cxx:1856
virtual void set_depth_func(CompareFunction func)
set the depth test function
Definition context.cxx:1830
void set_light_source(void *handle, const cgv::media::illum::light_source &light, bool place_now=true)
set light source newly
Definition context.cxx:669
void push_projection_matrix()
same as push_V but for the projection matrix - a different matrix stack is used.
Definition context.cxx:1969
bool current_material_is_textured
store flag to tell whether current material is textured
Definition context.h:819
virtual void set_projection_matrix(const dmat4 &P)
set the current projection matrix, which transforms from eye to clip space
Definition context.cxx:2002
rgba current_color
current color value
Definition context.h:746
static const unsigned nr_default_light_sources
number of default light sources
Definition context.h:809
cgv::media::illum::light_source default_light_source[nr_default_light_sources]
default light sources
Definition context.h:811
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:2107
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:815
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:1795
std::stack< std::vector< window_transformation > > window_transformation_stack
keep stack of window transformations
Definition context.h:773
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:654
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:740
virtual void set_blend_state(BlendState state)
set the complete blend state
Definition context.cxx:1873
bool sRGB_framebuffer
whether to use opengl option to support sRGB framebuffer
Definition context.h:748
virtual RenderPassFlags get_default_render_pass_flags() const
return the default render pass flags
Definition context.cxx:882
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:1905
void set_current_material(shader_program &prog) const
set the shader program material to the currently enabled material
Definition context.cxx:711
void pop_cull_state()
pop the top of the current culling state from the stack
Definition context.cxx:1847
void pop_modelview_matrix()
see push_V for an explanation
Definition context.cxx:1963
void * default_light_source_handles[nr_default_light_sources]
handles of default light sources
Definition context.h:813
void push_modelview_matrix()
push the current viewing matrix onto a matrix stack for viewing matrices.
Definition context.cxx:1951
std::stack< frame_buffer_base * > frame_buffer_stack
stack of currently enabled frame buffers
Definition context.h:775
bool auto_set_view_in_current_shader_program
whether to automatically set viewing matrixes in current shader program, defaults to true
Definition context.h:730
void tesselate_unit_cone(int resolution=25, bool flip_normals=false, bool edges=false)
tesselate a cone of radius 1
Definition context.cxx:1327
CullingMode get_cull_state() const
return the current culling state
Definition context.cxx:1852
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:2050
const cgv::media::illum::surface_material * current_material_ptr
store pointer to current material
Definition context.h:817
virtual void set_modelview_matrix(const dmat4 &MV)
set the current modelview matrix, which transforms from world to eye space
Definition context.cxx:1985
void * get_enabled_light_source_handle(size_t i) const
access to handle of i-th light source
Definition context.cxx:777
cgv::media::font::font_face_ptr current_font_face
store current font
Definition context.h:843
virtual void set_depth_mask(bool flag)
set the depth buffer mask
Definition context.cxx:1934
bool auto_set_gamma_in_current_shader_program
whether to automatically set gamma in current shader program, defaults to true
Definition context.h:736
virtual void init_frame(context &)
this method is called in one pass over all drawables before the draw method
Definition drawable.cxx:125
virtual void resize(unsigned int w, unsigned int h)
callback to announce resizing of the output window
Definition drawable.cxx:121
virtual bool init(context &)
this method is called after creation or recreation of the context, return whether all necessary funct...
Definition drawable.cxx:116
base interface for framebuffer
Definition context.h:529
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:149
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:147
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:357
const context * ctx_ptr
keep pointer to my context
Definition context.h:363
std::string last_error
a string that contains the last error
Definition context.h:365
a shader program combines several shader code fragments to a complete definition of the shading pipel...
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:389
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:62
class that extends obj_material with the management of textures
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
data::ref_ptr< font_face > font_face_ptr
always use this ref counted pointer to store font faces
Definition font.h:52
data::ref_ptr< font > font_ptr
always use this ref counted pointer to store fonts
Definition font.h:71
namespace for opengl specific GPU programming
Definition gl.cxx:6
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,...
namespace for api independent GPU programming
RenderAPI
enumeration of rendering APIs which can be queried from the context
Definition context.h:126
CullingMode
different culling modes
Definition context.h:199
BlendFunction
different blend functions
Definition context.h:206
AccessType
different access types
Definition context.h:322
TextureFilter
different texture filter
Definition context.h:245
TextureWrap
different texture wrap modes
Definition context.h:229
FrameBufferType
different frame buffer types which can be combined together with or
Definition context.h:546
MaterialSide
different sides of a material
Definition context.h:184
ProgramVariableKind
enumerates different kinds of shader program variables
Definition context.h:91
VertexBufferUsage
Provides vertex buffer usage hints as defined in OpenGL.
Definition context.h:487
ShaderType
different shader types
Definition context.h:543
PrimitiveType
different primitive types
Definition context.h:281
VertexBufferType
Provides vertex buffer types to allow implicit binding.
Definition context.h:474
@ VBT_VERTICES
The buffer contains vertices and will be bound to GL_ARRAY_BUFFER.
Definition context.h:476
@ VBT_TEXTURE
The buffer contains texture data and will be bound to GL_TEXTURE_BUFFER.
Definition context.h:478
@ VBT_INDICES
The buffer contains indices and will be bound to GL_ELEMENT_ARRAY_BUFFER.
Definition context.h:477
@ VBT_ATOMIC_COUNTER
The buffer contains atomic counter and will be bound to GL_ATOMIC_COUNTER_BUFFER.
Definition context.h:482
@ VBT_STORAGE
The buffer contains arbitrary data and will be bound to GL_SHADER_STORAGE_BUFFER.
Definition context.h:481
@ VBT_UNIFORM
The buffer contains uniforms and will be bound to GL_UNIFORM_BUFFER.
Definition context.h:479
@ VBT_INDIRECT
The buffer contains indirect draw commands and will be bound to GL_DRAW_INDIRECT_BUFFER.
Definition context.h:483
@ VBT_FEEDBACK
The buffer is used for transform&feedback and will be bound to GL_TRANSFORM_FEEDBACK_BUFFER.
Definition context.h:480
BufferTypeBits
Bits for the selection of different buffer types.
Definition context.h:519
TextureType
different texture types
Definition context.h:257
RenderPassFlags
available flags that can be queried from the context and set for a new render pass
Definition context.h:149
@ RPF_CLEAR_ACCUM
whether to clear the accumulation buffer
Definition context.h:164
@ RPF_SET_MODELVIEW
whether to set default modelview matrix
Definition context.h:152
@ RPF_SET_MATERIAL
whether to define default material
Definition context.h:156
@ RPF_SET_CLEAR_DEPTH
whether to set the clear color
Definition context.h:170
@ RPF_SET_LIGHTS
whether to define default lights
Definition context.h:155
@ RPF_CLEAR_COLOR
whether to clear the color buffer
Definition context.h:161
@ RPF_CLEAR_STENCIL
whether to clear the depth buffer
Definition context.h:163
@ RPF_SET_CLEAR_STENCIL
whether to set the clear color
Definition context.h:171
@ RPF_ENABLE_MATERIAL
whether to enable material
Definition context.h:158
@ RPF_DRAWABLES_INIT_FRAME
whether to call the init_frame method of the drawables
Definition context.h:167
@ RPF_CLEAR_DEPTH
whether to clear the depth buffer
Definition context.h:162
@ RPF_SET_STATE_FLAGS
whether to set depth buffer and culling flags
Definition context.h:168
@ RPF_SET_PROJECTION
whether to set default projection matrix
Definition context.h:151
@ RPF_SET_CLEAR_ACCUM
whether to set the accumulation buffer clear color
Definition context.h:172
@ RPF_SET_CLEAR_COLOR
whether to set the clear color
Definition context.h:169
@ RPF_SET_LIGHTS_ON
whether to turn on default lights
Definition context.h:157
CompareFunction
different comparison functions used for depth testing or texture comparisons
Definition context.h:310
namespace for functions that act on types
Definition clean.h:9
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
Definition bool32_t.h:7
double flt64_type
this type provides a 64 bit floating point type
signed char int8_type
this type provides an 8 bit signed integer type
int int32_type
this type provides an 32 bit signed integer type
short int16_type
this type provides an 16 bit signed integer type
unsigned short uint16_type
this type provides an 16 bit unsigned integer type
unsigned int uint32_type
this type provides an 32 bit unsigned integer type
float flt32_type
this type provides a 32 bit floating point type
unsigned char uint8_type
this type provides an 8 bit unsigned integer type
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::math::fvec< float, 4 > vec4
declare type of 4d single precision floating point vectors (used for homogeneous coordinates)
Definition fvec.h:696
cgv::media::color< float, cgv::media::RGB, cgv::media::OPACITY > rgba
declare rgba color type with 32 bit components
Definition color.h:898
cgv::math::fvec< double, 3 > dvec3
declare type of 3d double precision floating point vectors
Definition fvec.h:701
cgv::math::fvec< uint32_t, 3 > uvec3
declare type of 3d 32 bit unsigned integer vectors
Definition fvec.h:727
cgv::math::fvec< int32_t, 4 > ivec4
declare type of 4d 32 bit integer vectors
Definition fvec.h:723
cgv::media::color< float, cgv::media::RGB > rgb
declare rgb color type with 32 bit components
Definition color.h:896
cgv::math::fmat< double, 4, 4 > dmat4
declare type of 4x4 matrices
Definition fmat.h:481
cgv::math::fvec< float, 2 > vec2
declare type of 2d single precision floating point vectors
Definition fvec.h:692
cgv::math::fvec< bool, 4 > bvec4
declare type of 4d boolean vectors
Definition fvec.h:689
cgv::math::fvec< float, 3 > vec3
declare type of 3d single precision floating point vectors
Definition fvec.h:694
cgv::math::fvec< double, 2 > dvec2
declare type of 2d double precision floating point vectors
Definition fvec.h:699
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:696
bool enabled
whether blending is enabled
Definition context.h:698
BlendFunction dst_color
the destination color (rgb) factor
Definition context.h:702
BlendFunction dst_alpha
the destination alpha factor
Definition context.h:706
BlendFunction src_alpha
the source alpha factor
Definition context.h:704
BlendFunction src_color
the source color (rgb) factor
Definition context.h:700
Represents a buffer mask used to mask depth and color buffer outputs.
Definition context.h:711
bool red_flag
whether to write to the red channel of the color buffer
Definition context.h:715
bool depth_flag
whether to write to the depth buffer if the depth test is enabled
Definition context.h:713
bool alpha_flag
whether to write to the alpha channel of the color buffer
Definition context.h:721
bool green_flag
whether to write to the green channel of the color buffer
Definition context.h:717
bool blue_flag
whether to write to the blue channel of the color buffer
Definition context.h:719
Represents a depth test state used to configure depth testing.
Definition context.h:688
bool enabled
whether the depth test is enabled
Definition context.h:690
CompareFunction test_func
the function used to compare depth values
Definition context.h:692
configuration object used to define context parameters that need to be set already at creation time
Definition context.h:574
int version_minor
default: -1 ... minor version of maximum supported OpenGL version
Definition context.h:603
int version_major
default: -1 ... major version of maximum supported OpenGL version
Definition context.h:601
bool debug
default: false in release and true in debug version
Definition context.h:607
bool forward_compatible
default: false
Definition context.h:605
bool core_profile
default: true
Definition context.h:609
bool depth_buffer
default: true
Definition context.h:578
bool on_enter_children(group_ptr) override
called before the children of a group node g are processed, return whether these should be skipped....
bool on_leave_children(group_ptr) override
called when the children of a group node g have been left, return whether to terminate traversal
std::string name
name as it appears in shaders
Definition context.h:102
std::vector< char > current_value
data storage for the value of the program variable
Definition context.h:110
unsigned array_size
dimension of arrays
Definition context.h:106
void compute_sizes(size_t &cnt, size_t &s, size_t &S) const
helper member function to compute counts and sizes
Definition context.cxx:62
int program_location
location in program, but not for array variables which span multiple locations
Definition context.h:108
cgv::render::type_descriptor type_descr
type descriptor providing information on component and compositions (scalar, vector or matrix)
Definition context.h:104
compact type description of data that can be sent to the context; convertible to int
Definition context.h:61