cgv
Loading...
Searching...
No Matches
shader_program.cxx
1#include <cgv/base/base.h>
2#include "shader_program.h"
3#include <cgv/utils/file.h>
4#include <cgv/utils/dir.h>
5#include <cgv/utils/scan.h>
7#include <cgv/utils/tokenizer.h>
8#include <cgv/base/import.h>
9
10using namespace cgv::utils;
11
12namespace cgv {
13 namespace render {
14
15std::map<std::string, std::string> shader_program::program_file_cache;
16std::map<std::string, std::vector<std::string>> shader_program::files_cache;
17
18
19void shader_program::inspect_program_variables(const context& ctx, cgv::render::ProgramVariableKind kind, std::vector<cgv::render::program_variable_info>& Vs,
20 bool get_location, bool get_value)
21{
22 ctx.shader_program_inspect_variables(*this, kind, Vs, get_location, get_value);
23}
24
26bool shader_program::attach_files(const context& ctx, const std::vector<std::string>& file_names, const shader_compile_options& options)
27{
28 bool no_error = true;
29 for(unsigned int i = 0; i < file_names.size(); ++i) {
30 no_error = attach_file(ctx, file_names[i], ST_DETECT, options) && no_error;
31 if(!no_error)
32 std::cout << last_error << std::endl;
33 }
34 return no_error;
35}
36
37bool shader_program::collect_files_from_cache(const std::string& name, std::vector<std::string>& file_names, bool& added_files) {
38
39 auto it = files_cache.find(name);
40 if(it != files_cache.end()) {
41 const std::vector<std::string>& cached_file_names = it->second;
42 for(size_t i = 0; i < cached_file_names.size(); ++i)
43 file_names.push_back(cached_file_names[i]);
44
45 added_files = !cached_file_names.empty();
46 return true;
47 }
48
49 added_files = false;
50 return false;
51}
52
53bool shader_program::collect_file(const std::string& file_name, bool use_cache, std::vector<std::string>& file_names)
54{
55 if(use_cache) {
56 bool added_files = false;
57 if(collect_files_from_cache(file_name, file_names, added_files))
58 return added_files;
59 }
60
61 std::vector<std::string> collected_file_names;
62
63 std::string fn = shader_code::find_file(file_name);
64 bool found = false;
65
66 if (!fn.empty()) {
67 file_names.push_back(fn);
68 if(use_cache)
69 collected_file_names.push_back(fn);
70 found = true;
71 }
72
73 if(use_cache)
74 files_cache.emplace(file_name, collected_file_names);
75
76 return found;
77}
78
79bool shader_program::collect_files(const std::string& base_name, bool use_cache, std::vector<std::string>& file_names)
80{
81 if(use_cache) {
82 bool added_files = false;
83 if(collect_files_from_cache(base_name, file_names, added_files))
84 return added_files;
85 }
86
87 std::vector<std::string> collected_file_names;
88
89 const char* exts[] = { "glvs", "glgs", "glfs", "glcs", "gltc", "glte", "pglvs", "pglfs", "pglgs", "pglcs", "pgltc", "pglte", 0 };
90 const char** iter = exts;
91 bool added_file = false;
92 while (*iter) {
93 std::string fn = shader_code::find_file(base_name+"."+*iter);
94 if (!fn.empty()) {
95 file_names.push_back(fn);
96
97 if(use_cache)
98 collected_file_names.push_back(fn);
99
100 added_file = true;
101 }
102 ++iter;
103 }
104 if(!added_file)
105 std::cerr << "could not find shader file " << base_name.c_str() << std::endl;
106
107 if(use_cache)
108 files_cache.emplace(base_name, collected_file_names);
109
110 return added_file;
111}
112
113bool shader_program::collect_dir(const std::string& dir_name, bool recursive, std::vector<std::string>& file_names)
114{
115 std::string dn = dir_name;
116 if (!dir::exists(dn)) {
117 if (get_shader_config()->shader_path.empty()) {
118 return false;
119 }
120 dn = file::find_in_paths(dir_name, get_shader_config()->shader_path, true);
121 if (dn.empty()) {
122 return false;
123 }
124 }
125 void* handle = file::find_first(dn+"/*.gl*");
126 if (!handle)
127 return false;
128 while (handle) {
129 file_names.push_back(dir_name+"/"+file::find_name(handle));
130 handle = file::find_next(handle);
131 }
132 return true;
133}
134
135bool shader_program::collect_program(const std::string& file_name, bool use_cache, std::vector<std::string>& file_names)
136{
137 std::string fn = shader_code::find_file(file_name);
138 if (fn.empty())
139 return false;
140 std::string content;
141 if (!cgv::base::read_data_file(fn, content, true))
142 return false;
143
145
146 std::vector<line> lines;
147 split_to_lines(content, lines);
148 bool added_file = false;
149 std::string old_shader_path = get_shader_config()->shader_path;
150 std::string path = file::get_path(file_name);
151 if (!path.empty())
152 get_shader_config()->shader_path = path+";"+get_shader_config()->shader_path;
153
154 for (auto line : lines) {
155 std::string l = to_string((const token&)line);
156 if (l.substr(0,5) == "file:")
157 added_file = collect_file(l.substr(5), use_cache, file_names) || added_file;
158 else if (l.substr(0,12) == "vertex_file:")
159 added_file = collect_file(l.substr(12), use_cache, file_names) || added_file;
160 else if (l.substr(0, 14) == "geometry_file:")
161 added_file = collect_file(l.substr(14), use_cache, file_names) || added_file;
162 else if (l.substr(0, 26) == "tessellation_control_file:")
163 added_file = collect_file(l.substr(26), use_cache, file_names) || added_file;
164 else if (l.substr(0, 29) == "tessellation_evaluation_file:")
165 added_file = collect_file(l.substr(29), use_cache, file_names) || added_file;
166 else if (l.substr(0,14) == "fragment_file:")
167 added_file = collect_file(l.substr(14), use_cache, file_names) || added_file;
168 else if (l.substr(0,6) == "files:")
169 added_file = collect_files(l.substr(6), use_cache, file_names) || added_file;
170 else if (l.substr(0,4) == "dir:")
171 added_file = collect_dir(l.substr(4), false, file_names) || added_file;
172 else if (l.substr(0,8) == "rec_dir:")
173 added_file = collect_dir(l.substr(8), true, file_names) || added_file;
174 else if (l.substr(0,8) == "program:")
175 added_file = collect_program(l.substr(8), use_cache, file_names) || added_file;
176 }
177
178 get_shader_config()->shader_path = old_shader_path;
179 return added_file;
180}
181
183shader_program::shader_program(bool _show_code_errors)
184{
185 show_code_errors = _show_code_errors;
186 linked = false;
187 state_out_of_date = true;
188 nr_attached_geometry_shaders = 0;
189}
190
193{
194 if (ctx_ptr && ctx_ptr->make_current())
196 else
197 if (handle != 0)
198 std::cerr << "could not destruct shader program properly" << std::endl;
199}
200
203{
204 state_out_of_date = true;
205 nr_attached_geometry_shaders = 0;
206 if (ctx_ptr)
208 else
209 if (handle)
210 destruct(ctx);
211 ctx_ptr = &ctx;
212 return ctx.shader_program_create(*this);
213}
214
217{
218 if (!handle) {
219 last_error = "attach_code to shader program that was not created";
220 return false;
221 }
222 if (!code.handle) {
223 last_error = "attempt to attach_code that is not created to shader program";
224 return false;
225 }
226 if(!code.is_compiled()) {
227 last_error = "attempt to attach_code that is not compiled to shader program";
228 return false;
229 }
230 ctx.shader_program_attach(*this, code);
231 if(code.get_shader_type() == ST_GEOMETRY)
232 ++nr_attached_geometry_shaders;
233 return true;
234}
235
237bool shader_program::detach_code(const context& ctx, const shader_code& code) {
238 if(!handle) {
239 last_error = "detach_code from shader program that was not created";
240 return false;
241 }
242 if(!code.handle) {
243 last_error = "attempt to detach_code that is not created to shader program";
244 return false;
245 }
246 ctx.shader_program_detach(*this, code);
247 if(code.get_shader_type() == ST_GEOMETRY)
248 --nr_attached_geometry_shaders;
249 return true;
250}
251
252
254bool shader_program::attach_code(const context& ctx, const std::string& source, ShaderType st) {
255 /*
256 shader_code* code_ptr = new shader_code;
257 if(code_ptr->set_code(ctx, source, st) && code_ptr->compile(ctx)) {
258 managed_codes.push_back(code_ptr);
259 return attach_code(ctx, *code_ptr);
260 }
261 last_error = code_ptr->last_error;
262 delete code_ptr;
263 return false;
264 */
265 shader_code code;
266 if(code.set_code(ctx, source, st) && code.compile(ctx))
267 return attach_code(ctx, code);
268 last_error = code.last_error;
269 return false;
270}
271
272
274bool shader_program::attach_file(const context& ctx, const std::string& file_name, ShaderType st, const shader_compile_options& options) {
275 /*
276 shader_code* code_ptr = new shader_code;
277 if(!code_ptr->read_and_compile(ctx, file_name, st, options, show_code_errors)) {
278 last_error = code_ptr->last_error;
279 delete code_ptr;
280 return false;
281 }
282 managed_codes.push_back(code_ptr);
283 return attach_code(ctx, *code_ptr);
284 */
285 shader_code code;
286 if(code.read_and_compile(ctx, file_name, st, options, show_code_errors))
287 return attach_code(ctx, code);
288 last_error = code.last_error;
289 return false;
290}
291
293bool shader_program::attach_files(const context& ctx, const std::string& base_name, const shader_compile_options& options) {
294 std::vector<std::string> file_names;
295 if(!collect_files(base_name, ctx.is_shader_file_cache_enabled(), file_names))
296 return false;
297 return attach_files(ctx, file_names, options);
298}
300bool shader_program::attach_dir(const context& ctx, const std::string& dir_name, bool recursive, const shader_compile_options& options) {
301 std::vector<std::string> file_names;
302 if(!collect_dir(dir_name, recursive, file_names))
303 return false;
304 return attach_files(ctx, file_names, options);
305}
306bool shader_program::open_program_file(std::string& file_name, bool use_cache, std::string& content, std::vector<line>& lines, std::string* last_error_ptr)
307{
308 std::string fn = "";
309
310 if(use_cache) {
311 auto it = program_file_cache.find(file_name);
312 if(it != program_file_cache.end()) {
313 fn = it->second;
314 }
315 }
316
317 if(fn.empty())
318 fn = shader_code::find_file(file_name);
319
320 if(use_cache)
321 program_file_cache.emplace(file_name, fn);
322
323 if (fn.empty()) {
324 if (last_error_ptr)
325 *last_error_ptr = "could not find shader program file " + file_name;
326 return false;
327 }
328 if (!cgv::base::read_data_file(fn, content, true)) {
329 if (last_error_ptr)
330 *last_error_ptr = "could not read shader program file " + file_name;
331 return false;
332 }
334 split_to_lines(content, lines);
335 file_name = fn;
336 return true;
337}
338std::vector<shader_compile_options> shader_program::extract_instances(std::string file_name)
339{
340 std::string content;
341 std::vector<line> lines;
342 std::vector<shader_compile_options> result;
343 if (!open_program_file(file_name, false, content, lines))
344 return result;
345 for (unsigned int i = 0; i < lines.size(); ++i) {
346 token tok = lines[i];
347 while (tok.begin < tok.end && is_space(*tok.begin))
348 ++tok.begin;
349 std::string l = to_string(tok);
350 if (l.empty() || l[0] == '/')
351 continue;
352 if (l.substr(0, 9) != "instance:")
353 continue;
354 std::string defs=l.substr(9);
355 std::vector<token> toks;
356 split_to_tokens(defs, toks, "", false, "", "", ";");
358 for (const auto& t : toks) {
359 std::vector<token> sides;
360 split_to_tokens(t, sides, "", false, "", "", "=");
361 std::vector<std::string> S;
362 for (auto& s : sides) {
363 while (s.begin < s.end && is_space(*s.begin))
364 ++s.begin;
365 while (s.begin < s.end && is_space(s.end[-1]))
366 --s.end;
367 if (s.begin < s.end)
368 S.push_back(to_string(s));
369 }
370 if(S.size() == 2)
371 options.define_macro(S[0], S[1]);
372 }
373 result.push_back(options);
374 }
375 return result;
376}
377
378bool shader_program::attach_program(const context& ctx, std::string file_name, bool show_error, const shader_compile_options& options)
379{
380 std::string content;
381 std::vector<line> lines;
382 if (!open_program_file(file_name, ctx.is_shader_file_cache_enabled(), content, lines, &last_error)) {
383 std::cerr << last_error << std::endl;
384 return false;
385 }
386 if (get_shader_config()->show_file_paths)
387 std::cout << "read shader program <" << file_name << ">" << std::endl;
388 std::string old_shader_path = get_shader_config()->shader_path;
389 std::string path = file::get_path(file_name);
390 if (!path.empty())
391 get_shader_config()->shader_path = path+";"+get_shader_config()->shader_path;
392
393 bool no_error = true;
394 std::string error = "2 : attach command failed";
395 for (unsigned int i=0; i<lines.size(); ++i) {
396 token tok = lines[i];
397 while (tok.begin < tok.end && is_space(*tok.begin))
398 ++tok.begin;
399 std::string l = to_string(tok);
400
401 bool success = true;
402 // ignore empty lines
403 if (l.empty())
404 continue;
405 // ignore comments
406 if (l[0] == '/')
407 continue;
408 if (l.substr(0,5) == "file:")
409 success = attach_file(ctx, l.substr(5), ST_DETECT, options);
410 else if (l.substr(0,12) == "vertex_file:")
411 success = attach_file(ctx, l.substr(12), ST_VERTEX, options);
412 else if (l.substr(0,14) == "geometry_file:")
413 success = attach_file(ctx, l.substr(14), ST_GEOMETRY, options);
414 else if (l.substr(0, 26) == "tessellation_control_file:")
415 success = attach_file(ctx, l.substr(26), ST_TESS_CONTROL, options);
416 else if (l.substr(0, 29) == "tessellation_evaluation_file:")
417 success = attach_file(ctx, l.substr(29), ST_TESS_EVALUATION, options);
418 else if (l.substr(0,14) == "fragment_file:")
419 success = attach_file(ctx, l.substr(14), ST_FRAGMENT, options);
420 else if(l.substr(0, 13) == "compute_file:")
421 success = attach_file(ctx, l.substr(13), ST_COMPUTE, options);
422 else if (l.substr(0,6) == "files:")
423 success = attach_files(ctx, l.substr(6), options);
424 else if (l.substr(0,4) == "dir:")
425 success = attach_dir(ctx, l.substr(4), false);
426 else if (l.substr(0,8) == "rec_dir:")
427 success = attach_dir(ctx, l.substr(8), true);
428 else if (l.substr(0,8) == "program:")
429 success = attach_program(ctx, l.substr(8));
430 else if (l.substr(0,21) == "geometry_shader_info:") {
431 std::vector<token> toks;
432 std::string l1 = l.substr(21);
433 tokenizer(l1).set_ws(";").bite_all(toks);
434 if (toks.size() == 3) {
435 PrimitiveType i_pt = PT_UNDEF, o_pt = PT_UNDEF;
436 int pi, count = 0;
437 for (pi = PT_UNDEF+1; pi < PT_LAST; ++pi) {
439 std::string s = to_string(pt);
440 if (s == to_string(toks[0]))
441 i_pt = pt;
442 if (s == to_string(toks[1]))
443 o_pt = pt;
444 }
445 if (i_pt == PT_UNDEF) {
446 error = "4 : unknown input_type for geometry shader <";
447 error += to_string(toks[0])+">";
448 success = false;
449 }
450 else if (o_pt == PT_UNDEF) {
451 error = "5 : unknown ouput_type for geometry shader <";
452 error += to_string(toks[1])+">";
453 success = false;
454 }
455 else if (!is_integer(toks[2].begin,toks[2].end,count)) {
456 error = "6 : max_output_count of geometry shader must be an integer but received <";
457 error += to_string(toks[2])+">";
458 success = false;
459 }
460 else {
461 set_geometry_shader_info(i_pt, o_pt, count);
462 }
463 }
464 else {
465 success = false;
466 error = "3 : geometry_shader_info takes three arguments separated by colons";
467 }
468 }
469 else if (l.substr(0, 9) == "instance:") {
470 }
471 else if (show_error) {
472 std::cerr << file_name.c_str() << " (" << i + 1
473 << "): warning G0001 : syntax error in line '"
474 << l.c_str() << "'" << std::endl;
475 }
476 if (!success) {
477 if (show_error) {
478 std::cerr << file_name.c_str() << " (" << i+1
479 << "): error G000" << error.c_str() << std::endl;
480 }
481 no_error = false;
482 }
483 }
484
485 get_shader_config()->shader_path = old_shader_path;
486 if (show_error && !no_error)
487 std::cerr << last_error << std::endl;
488 return no_error;
489}
490
492bool shader_program::build_files(const context& ctx, const std::string& base_name, bool show_error) {
493 return build_files(ctx, base_name, {}, show_error);
494}
495
497bool shader_program::build_dir(const context& ctx, const std::string& dir_name, bool recursive, bool show_error) {
498 return build_dir(ctx, dir_name, {}, recursive, show_error);
499}
500
502bool shader_program::build_program(const context& ctx, const std::string& file_name, bool show_error) {
503 return build_program(ctx, file_name, {}, show_error);
504}
505
507bool shader_program::build_files(const context& ctx, const std::string& base_name, const shader_compile_options& options, bool show_error) {
508 return (is_created() || create(ctx)) &&
509 attach_files(ctx, base_name, options) && link(ctx, show_error);
510}
512bool shader_program::build_dir(const context& ctx, const std::string& dir_name, const shader_compile_options& options, bool recursive, bool show_error) {
513 return (is_created() || create(ctx)) &&
514 attach_dir(ctx, dir_name, recursive, options) && link(ctx, show_error);
515}
516
518bool shader_program::build_program(const context& ctx, const std::string& file_name, const shader_compile_options& options, bool show_error) {
519 if(!(is_created() || create(ctx)))
520 return false;
521
522 if(!attach_program(ctx, file_name, show_error, options))
523 return false;
524
525 if(!link(ctx, show_error)) {
526 if(show_error) {
527 std::string fn = shader_code::find_file(file_name);
528 std::vector<line> lines;
530 std::string formated_error;
531 for(unsigned int i = 0; i < lines.size(); ++i) {
532 formated_error += fn + "(1) : error G0002: " + to_string(lines[i]) + "\n";
533 }
534 std::cerr << formated_error.c_str() << std::endl;
535 }
536 return false;
537 }
538
539 return true;
540}
541
544{
545 return ctx.get_device_capabilities().max_geometry_shader_output_vertex_count;
546}
547
550{
551 if (state_out_of_date) {
552 if (nr_attached_geometry_shaders > 0) {
553 if (geometry_shader_output_count < 1)
554 geometry_shader_output_count = get_max_nr_geometry_shader_output_vertices(ctx);
555 ctx.shader_program_set_state(*this);
556 }
557 state_out_of_date = false;
558 }
559}
560
562bool shader_program::link(const context& ctx, bool show_error)
563{
564 update_state(ctx);
565 if (ctx.shader_program_link(*this)) {
566 ctx.shader_program_set_uniform_locations(*this);
567 linked = true;
568 return true;
569 }
570 else {
571 linked = false;
572 if (show_error)
573 std::cerr << "link error:\n" << last_error.c_str() << std::endl;
574 return false;
575 }
576}
579{
580 return linked;
581}
582
584void shader_program::set_geometry_shader_info(PrimitiveType input_type, PrimitiveType output_type, int max_output_count)
585{
586 geometry_shader_input_type = input_type;
587 geometry_shader_output_type = output_type;
588 geometry_shader_output_count = max_output_count;
589 state_out_of_date = true;
590}
591
594{
595 if (!is_created()) {
596 ctx.error("attempt to enable shader_program that is not created", this);
597 return false;
598 }
599 if (!is_linked()) {
600 ctx.error("attempt to enable shader_program that is not linked", this);
601 return false;
602 }
603 if (is_enabled()) {
604 ctx.error("attempt to enable shader_program that is already enabled or was not disabled properly", this);
605 return false;
606 }
607 update_state(ctx);
608 bool res = ctx.shader_program_enable(*this);
609 if (res)
610 shader_program_base::is_enabled = true;
611 return res;
612}
613
616{
617 if (!is_enabled()) {
618 ctx.error("attempt to disable shader_program that is not enabled", this);
619 return false;
620 }
621 bool res = ctx.shader_program_disable(*this);
622 shader_program_base::is_enabled = false;
623 return res;
624}
625
627const std::map<std::string, int>& shader_program::get_uniform_locations() const
628{
629 return uniform_locations;
630}
631
633int shader_program::get_uniform_location(const context& ctx, const std::string& name) const
634{
635 // debug fallback: get uniform location from context through GL call
636 //return ctx.get_uniform_location(*this, name);
637
638 // get from cache
639 auto it = uniform_locations.find(name);
640 return it != uniform_locations.end() ? it->second : -1;
641}
643bool shader_program::set_material_uniform(const context& ctx, const std::string& name, const cgv::media::illum::surface_material& material, bool generate_error)
644{
645 bool res = set_uniform(ctx, name + ".brdf_type", static_cast<int>(material.brdf_type), generate_error);
646 res = set_uniform(ctx, name + ".diffuse_reflectance", material.diffuse_reflectance, generate_error) && res;
647 res = set_uniform(ctx, name + ".roughness", material.roughness, generate_error) && res;
648 res = set_uniform(ctx, name + ".ambient_occlusion", material.ambient_occlusion, generate_error) && res;
649 res = set_uniform(ctx, name + ".emission", material.emission, generate_error) && res;
650 res = set_uniform(ctx, name + ".specular_reflectance", material.specular_reflectance, generate_error) && res;
651 res = set_uniform(ctx, name + ".roughness_anisotropy", material.roughness_anisotropy, generate_error) && res;
652 res = set_uniform(ctx, name + ".roughness_orientation", material.roughness_orientation, generate_error) && res;
653 res = set_uniform(ctx, name + ".propagation_slow_down", vec2(material.propagation_slow_down.real(), material.propagation_slow_down.imag()), generate_error) && res;
654 res = set_uniform(ctx, name + ".transparency", material.transparency, generate_error) && res;
655 res = set_uniform(ctx, name + ".metalness", material.metalness, generate_error) && res;
656 return res;
657}
658
660bool shader_program::set_textured_material_uniform(const context& ctx, const std::string& name, const textured_material& material, bool generate_error)
661{
662 const char* texture_names[] = {
663 "tex0", "tex1", "tex2", "tex3", "tex4", "tex5"
664 };
665 for (int i = 0; i < (int)material.get_nr_textures(); ++i)
666 if (!set_uniform(ctx, texture_names[i], i, generate_error))
667 return false;
668 bool res = set_material_uniform(ctx, name, material, generate_error);
669 res = set_uniform(ctx, "sRGBA_textures", material.sRGBA_textures, generate_error) && res;
670 res = set_uniform(ctx, "diffuse_index", material.diffuse_index, generate_error) && res;
671 res = set_uniform(ctx, "roughness_index", material.roughness_index, generate_error) && res;
672 res = set_uniform(ctx, "metalness_index", material.metalness_index, generate_error) && res;
673 res = set_uniform(ctx, "ambient_index", material.ambient_index, generate_error) && res;
674 res = set_uniform(ctx, "emission_index", material.emission_index, generate_error) && res;
675 res = set_uniform(ctx, "transparency_index", material.transparency_index, generate_error) && res;
676 res = set_uniform(ctx, "bump_index", material.bump_index, generate_error) && res;
677 res = set_uniform(ctx, "specular_index", material.specular_index, generate_error) && res;
678 return res;
679}
680
681
682
684bool shader_program::set_light_uniform(const context& ctx, const std::string& name, const cgv::media::illum::light_source& L, bool generate_error)
685{
686 if (!set_uniform(ctx, name + ".light_source_type", static_cast<int>(L.get_type()), generate_error))
687 return false;
688 if (!set_uniform(ctx, name + ".position", L.get_position(), generate_error))
689 return false;
690 if (!set_uniform(ctx, name + ".emission", L.get_emission(), generate_error))
691 return false;
692 if (!set_uniform(ctx, name + ".ambient_scale", L.get_ambient_scale(), generate_error))
693 return false;
694 if (!set_uniform(ctx, name + ".spot_direction", L.get_spot_direction(), generate_error))
695 return false;
696 if (!set_uniform(ctx, name + ".spot_exponent", L.get_spot_exponent(), generate_error))
697 return false;
698 if (!set_uniform(ctx, name + ".spot_cos_cutoff", cos(0.01745329252f*L.get_spot_cutoff()), generate_error))
699 return false;
700 if (!set_uniform(ctx, name + ".constant_attenuation", L.get_constant_attenuation(), generate_error))
701 return false;
702 if (!set_uniform(ctx, name + ".linear_attenuation", L.get_linear_attenuation(), generate_error))
703 return false;
704 if (!set_uniform(ctx, name + ".quadratic_attenuation", L.get_quadratic_attenuation(), generate_error))
705 return false;
706 return true;
707}
708
709int shader_program::get_uniform_block_index(const context& ctx, const std::string& name) const
710{
711 return ctx.get_uniform_block_index(*this, name);
712}
713
714bool shader_program::set_uniform_block_binding(const context& ctx, int index, int binding)
715{
716 return ctx.set_uniform_block_binding(*this, index, binding);
717}
718
719bool shader_program::set_uniform_block_binding(const context& ctx, const std::string& name, int binding)
720{
721 int index = ctx.get_uniform_block_index(*this, name);
722 if(index == -1) {
723 ctx.error(std::string("shader_program::set_uniform_block_binding() block <") + name + "> not found", this);
724 return false;
725 }
726 return ctx.set_uniform_block_binding(*this, index, binding);
727}
728
730int shader_program::get_attribute_location(const context& ctx, const std::string& name) const
731{
732 return ctx.get_attribute_location(*this, name);
733}
734
737{
738 /*
739 while(managed_codes.size() > 0) {
740 delete managed_codes.back();
741 managed_codes.pop_back();
742 }
743 */
744 if (handle) {
745 ctx.shader_program_destruct(*this);
746 handle = 0;
747 }
748 linked = false;
749 state_out_of_date = true;
750 auto_detect_uniforms = true;
751 auto_detect_vertex_attributes = true;
752 nr_attached_geometry_shaders = 0;
753}
754
755 }
756}
More advanced text processing for splitting text into lines or tokens.
bool empty() const
check if pointer is not yet set
Definition ref_ptr.h:230
>simple class to hold the properties of a light source
int metalness_index
index of image from which metalness should be mapped, -1 corresponds to no mapping
int transparency_index
index of image from which transparency should be mapped, -1 corresponds to no mapping
bool sRGBA_textures
whether textures are in sRGB format
int roughness_index
index of image from which roughness should be mapped, -1 corresponds to no mapping
int specular_index
index of image from which specular_reflectance should be mapped, -1 corresponds to no mapping
int ambient_index
index of image from which ambient_occlusion should be mapped, -1 corresponds to no mapping
int emission_index
index of image from which emission should be mapped, -1 corresponds to no mapping
int bump_index
index of image from which bumps should be mapped, -1 corresponds to no mapping
int diffuse_index
index of image from which diffuse_reflectance should be mapped, -1 corresponds to no mapping
base class for all drawables, which is independent of the used rendering API.
Definition context.h:668
virtual void error(const std::string &message, const render_component *rc=0) const
error handling
Definition context.cxx:307
bool is_shader_file_cache_enabled() const
whether the shader file caches are enabled
Definition context.cxx:569
virtual bool make_current() const =0
make the current context current if possible
virtual bool is_created() const
return whether component has been created
Definition context.cxx:2226
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 code object holds a code fragment of a geometry vertex or fragment shader and can be added t...
static std::string find_file(const std::string &file_name, bool search_exhaustive=false)
Find the full path to a shader by its file name.
ShaderType get_shader_type() const
return the shader type of this code
bool is_compiled() const
return whether shader has been compiled successfully
static void decode_if_base64(std::string &content)
decode a string if it is base64 encoded
bool compile(const context &ctx)
compile attached source; returns true if successful
bool set_code(const context &ctx, const std::string &source, ShaderType st)
set shader code from string
bool read_and_compile(const context &ctx, const std::string &file_name, ShaderType st=ST_DETECT, const shader_compile_options &options={}, bool show_error=true)
read shader code with read_code and compile.
Stores preprocessor options used for conditionally compiling shader programs.
Definition shader_code.h:73
void define_macro(const std::string &identifier)
Define a macro as identifier and no replacement text.
Definition shader_code.h:99
bool enable(context &ctx)
enable the shader program
bool disable(context &ctx)
disable shader program and restore fixed functionality
static bool collect_file(const std::string &file_name, bool use_cache, std::vector< std::string > &file_names)
resolve file name with shader_code::find_file and add file to list if found
shader_program(bool _show_code_errors=false)
create empty shader program and set the option whether errors during shader code attachment should be...
static std::map< std::string, std::string > program_file_cache
maps used to cache program file contents and valid file names indexed by their respective file name
bool set_uniform(const context &ctx, const std::string &name, const T &value, bool generate_error=false)
Set the value of a uniform by name, where the type can be any of int, unsigned, float,...
static unsigned int get_max_nr_geometry_shader_output_vertices(const context &ctx)
return the maximum number of output vertices of a geometry shader
~shader_program()
call destruct method
static bool collect_files_from_cache(const std::string &name, std::vector< std::string > &file_names, bool &added_files)
resolve file name with shader_code::find_file and add file to list if found
bool attach_dir(const context &ctx, const std::string &dir_name, bool recursive, const shader_compile_options &options={})
collect shader code files from directory, compile and attach.
void destruct(const context &ctx)
destruct shader program
bool build_dir(const context &ctx, const std::string &dir_name, bool recursive=false, bool show_error=false)
successively calls create, attach_dir and link.
static bool open_program_file(std::string &file_name, bool use_cache, std::string &content, std::vector< cgv::utils::line > &lines, std::string *last_error_ptr=0)
common code necessary to open file
bool detach_code(const context &ctx, const shader_code &code)
detach a shader code
bool attach_program(const context &ctx, std::string file_name, bool show_error=false, const shader_compile_options &options={})
collect shader code files declared in shader program file, compile and attach them
static bool collect_files(const std::string &base_name, bool use_cache, std::vector< std::string > &file_names)
collect shader code files that extent the given base name.
int get_attribute_location(const context &ctx, const std::string &name) const
query location index of an attribute
bool attach_code(const context &ctx, const shader_code &code)
attach a compiled shader code instance that is managed outside of program
void update_state(const context &ctx)
ensure that the state has been set in the context
void inspect_program_variables(const context &ctx, cgv::render::ProgramVariableKind kind, std::vector< cgv::render::program_variable_info > &Vs, bool get_location=true, bool get_value=true)
retrieve information on all uniform or attribute variables of a shader program
bool create(const context &ctx)
create the shader program
void set_geometry_shader_info(PrimitiveType input_type, PrimitiveType output_type, int max_output_count=0)
configure the geometry shader, if count < 1 set it to get_max_nr_geometry_shader_output_vertices
bool is_linked() const
return whether program is linked
bool link(const context &ctx, bool show_error=false)
link shaders to an executable program
bool build_program(const context &ctx, const std::string &file_name, bool show_error=false)
successively calls create, attach_program and link.
static bool collect_dir(const std::string &dir_name, bool recursive, std::vector< std::string > &file_names)
collect shader code files from directory.
bool is_enabled() const
check whether program is currently enabled
static std::vector< shader_compile_options > extract_instances(std::string file_name)
find and parse all instance definitions in a shader program file
bool attach_file(const context &ctx, const std::string &file_name, ShaderType st=ST_DETECT, const shader_compile_options &options={})
read shader code from file, compile and attach to program
bool set_textured_material_uniform(const context &ctx, const std::string &name, const textured_material &material, bool generate_error=false)
set a uniform of type textured_material
bool set_light_uniform(const context &ctx, const std::string &name, const cgv::media::illum::light_source &light, bool generate_error=false)
set a uniform of type light source
int get_uniform_location(const context &ctx, const std::string &name) const
query location index of an uniform
bool set_material_uniform(const context &ctx, const std::string &name, const cgv::media::illum::surface_material &material, bool generate_error=false)
set a uniform of type material
const std::map< std::string, int > & get_uniform_locations() const
return uniform name and location pairs
bool attach_files(const context &ctx, const std::vector< std::string > &file_names, const shader_compile_options &options={})
attach a list of files
bool build_files(const context &ctx, const std::string &base_name, bool show_error=false)
successively calls create, attach_files and link.
static bool collect_program(const std::string &file_name, bool use_cache, std::vector< std::string > &file_names)
collect shader code files declared in a shader program file.
class that extends obj_material with the management of textures
size_t get_nr_textures() const
virtual method to query number of textures
the tokenizer allows to split text into tokens in a convenient way.
Definition tokenizer.h:68
tokenizer & set_ws(const std::string &ws)
set the list of white spaces, that separate tokens and are skipped
Definition tokenizer.cxx:38
bool read_data_file(const std::string &file_name, std::string &content, bool ascii)
read ascii file into a string
Definition import.cxx:388
shader_config_ptr get_shader_config()
return a reference to the current shader configuration
ProgramVariableKind
enumerates different kinds of shader program variables
Definition context.h:91
ShaderType
different shader types
Definition context.h:541
PrimitiveType
different primitive types
Definition context.h:281
namespace that holds tools that dont fit any other namespace
void split_to_tokens(const char *begin, const char *end, std::vector< token > &tokens, const std::string &separators, bool merge_separators, const std::string &open_parenthesis, const std::string &close_parenthesis, const std::string &whitespaces, unsigned int max_nr_tokens)
this function splits a text range into tokens.
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
bool is_integer(const char *begin, const char *end, int &value)
check if the text range (begin,end( defines an integer value. If yes, store the value in the passed r...
Definition scan.cxx:449
void split_to_lines(const char *global_begin, const char *global_end, std::vector< line > &lines, bool truncate_trailing_spaces)
this function splits a text range at the newline characters into single lines.
bool is_space(char c)
check if char is a whitespace
Definition scan.cxx:12
this header is dependency free
Definition print.h:11
cgv::math::fvec< float, 2 > vec2
declare type of 2d single precision floating point vectors
Definition fvec.h:681
Helper functions to process strings.
Stores properties of a surface material.
color_type diffuse_reflectance
diffuse reflectance of surface, defaults to 0.5,0.5,0.5
BrdfType brdf_type
store brdf type, defaults to BT_STRAUSS_DIFFUSE + BT_STRAUSS
color_type emission
emissive color component, defaults to 0,0,0
float roughness_orientation
orientation of roughness in range [0,1], where 0 corresponds to u-direction and 0....
color_type specular_reflectance
specular color used to modulate specular reflection component, should be 1,1,1
float roughness_anisotropy
difference of roughness matrix eigenvalues in range [0,1] relative to roughness, i....
std::complex< float > propagation_slow_down
complex fraction of complex interior over real exterior index of refraction, defaults to 1....
float metalness
metalness of surface, defaults to 0
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
int max_geometry_shader_output_vertex_count
the maximum supported size for renderbuffers in any dimension
Definition context.h:43
a line in a text is simply represented as a token
representation of a token in a text by two pointers begin and end, that point to the first character ...
Definition token.h:18
const char * begin
pointers that define the range of characters
Definition token.h:20