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", "glts", "glms", "pglvs", "pglfs", "pglgs", "pglcs", "pgltc", "pglte", "pglts", "pglms", 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 (const cgv::utils::line& line : lines) {
155 std::string l = to_string(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, 10) == "task_file:")
161 added_file = collect_file(l.substr(10), use_cache, file_names) || added_file;
162 else if(l.substr(0, 10) == "mesh_file:")
163 added_file = collect_file(l.substr(10), use_cache, file_names) || added_file;
164 else if (l.substr(0, 14) == "geometry_file:")
165 added_file = collect_file(l.substr(14), use_cache, file_names) || added_file;
166 else if (l.substr(0, 26) == "tessellation_control_file:")
167 added_file = collect_file(l.substr(26), use_cache, file_names) || added_file;
168 else if (l.substr(0, 29) == "tessellation_evaluation_file:")
169 added_file = collect_file(l.substr(29), use_cache, file_names) || added_file;
170 else if (l.substr(0,14) == "fragment_file:")
171 added_file = collect_file(l.substr(14), use_cache, file_names) || added_file;
172 else if (l.substr(0,6) == "files:")
173 added_file = collect_files(l.substr(6), use_cache, file_names) || added_file;
174 else if (l.substr(0,4) == "dir:")
175 added_file = collect_dir(l.substr(4), false, file_names) || added_file;
176 else if (l.substr(0,8) == "rec_dir:")
177 added_file = collect_dir(l.substr(8), true, file_names) || added_file;
178 else if (l.substr(0,8) == "program:")
179 added_file = collect_program(l.substr(8), use_cache, file_names) || added_file;
180 }
181
182 get_shader_config()->shader_path = old_shader_path;
183 return added_file;
184}
185
187shader_program::shader_program(bool _show_code_errors)
188{
189 show_code_errors = _show_code_errors;
190 linked = false;
191 state_out_of_date = true;
192 nr_attached_geometry_shaders = 0;
193}
194
197{
198 if (ctx_ptr && ctx_ptr->make_current())
200 else
201 if (handle != 0)
202 std::cerr << "could not destruct shader program properly" << std::endl;
203}
204
206bool shader_program::create(const context& ctx)
207{
208 state_out_of_date = true;
209 nr_attached_geometry_shaders = 0;
210 if (ctx_ptr)
212 else
213 if (handle)
214 destruct(ctx);
215 ctx_ptr = &ctx;
216 return ctx.shader_program_create(*this);
217}
218
220bool shader_program::attach_code(const context& ctx, const shader_code& code)
221{
222 if (!handle) {
223 last_error = "attach_code to shader program that was not created";
224 return false;
225 }
226 if (!code.handle) {
227 last_error = "attempt to attach_code that is not created to shader program";
228 return false;
229 }
230 if(!code.is_compiled()) {
231 last_error = "attempt to attach_code that is not compiled to shader program";
232 return false;
233 }
234 ctx.shader_program_attach(*this, code);
235 if(code.get_shader_type() == ST_GEOMETRY)
236 ++nr_attached_geometry_shaders;
237 return true;
238}
239
241bool shader_program::detach_code(const context& ctx, const shader_code& code) {
242 if(!handle) {
243 last_error = "detach_code from shader program that was not created";
244 return false;
245 }
246 if(!code.handle) {
247 last_error = "attempt to detach_code that is not created to shader program";
248 return false;
249 }
250 ctx.shader_program_detach(*this, code);
251 if(code.get_shader_type() == ST_GEOMETRY)
252 --nr_attached_geometry_shaders;
253 return true;
254}
255
256
258bool shader_program::attach_code(const context& ctx, const std::string& source, ShaderType st) {
259 /*
260 shader_code* code_ptr = new shader_code;
261 if(code_ptr->set_code(ctx, source, st) && code_ptr->compile(ctx)) {
262 managed_codes.push_back(code_ptr);
263 return attach_code(ctx, *code_ptr);
264 }
265 last_error = code_ptr->last_error;
266 delete code_ptr;
267 return false;
268 */
269 shader_code code;
270 if(code.set_code(ctx, source, st) && code.compile(ctx))
271 return attach_code(ctx, code);
272 last_error = code.last_error;
273 return false;
274}
275
276
278bool shader_program::attach_file(const context& ctx, const std::string& file_name, ShaderType st, const shader_compile_options& options) {
279 /*
280 shader_code* code_ptr = new shader_code;
281 if(!code_ptr->read_and_compile(ctx, file_name, st, options, show_code_errors)) {
282 last_error = code_ptr->last_error;
283 delete code_ptr;
284 return false;
285 }
286 managed_codes.push_back(code_ptr);
287 return attach_code(ctx, *code_ptr);
288 */
289 shader_code code;
290 if(code.read_and_compile(ctx, file_name, st, options, show_code_errors))
291 return attach_code(ctx, code);
292 last_error = code.last_error;
293 return false;
294}
295
297bool shader_program::attach_files(const context& ctx, const std::string& base_name, const shader_compile_options& options) {
298 std::vector<std::string> file_names;
299 if(!collect_files(base_name, ctx.is_shader_file_cache_enabled(), file_names))
300 return false;
301 return attach_files(ctx, file_names, options);
302}
303
304bool shader_program::attach_dir(const context& ctx, const std::string& dir_name, bool recursive, const shader_compile_options& options) {
305 std::vector<std::string> file_names;
306 if(!collect_dir(dir_name, recursive, file_names))
307 return false;
308 return attach_files(ctx, file_names, options);
309}
310bool shader_program::open_program_file(std::string& file_name, bool use_cache, std::string& content, std::vector<line>& lines, std::string* last_error_ptr)
311{
312 std::string fn = "";
313
314 if(use_cache) {
315 auto it = program_file_cache.find(file_name);
316 if(it != program_file_cache.end()) {
317 fn = it->second;
318 }
319 }
320
321 if(fn.empty())
322 fn = shader_code::find_file(file_name);
323
324 if(use_cache)
325 program_file_cache.emplace(file_name, fn);
326
327 if (fn.empty()) {
328 if (last_error_ptr)
329 *last_error_ptr = "could not find shader program file " + file_name;
330 return false;
331 }
332 if (!cgv::base::read_data_file(fn, content, true)) {
333 if (last_error_ptr)
334 *last_error_ptr = "could not read shader program file " + file_name;
335 return false;
336 }
338 split_to_lines(content, lines);
339 file_name = fn;
340 return true;
341}
342std::vector<shader_compile_options> shader_program::extract_instances(std::string file_name)
343{
344 std::string content;
345 std::vector<line> lines;
346 std::vector<shader_compile_options> result;
347 if (!open_program_file(file_name, false, content, lines))
348 return result;
349 for (unsigned int i = 0; i < lines.size(); ++i) {
350 token tok = lines[i];
351 while (tok.begin < tok.end && is_space(*tok.begin))
352 ++tok.begin;
353 std::string l = to_string(tok);
354 if (l.empty() || l[0] == '/')
355 continue;
356 if (l.substr(0, 9) != "instance:")
357 continue;
358 std::string defs=l.substr(9);
359 std::vector<token> toks;
360 split_to_tokens(defs, toks, "", false, "", "", ";");
362 for (const auto& t : toks) {
363 std::vector<token> sides;
364 split_to_tokens(t, sides, "", false, "", "", "=");
365 std::vector<std::string> S;
366 for (auto& s : sides) {
367 while (s.begin < s.end && is_space(*s.begin))
368 ++s.begin;
369 while (s.begin < s.end && is_space(s.end[-1]))
370 --s.end;
371 if (s.begin < s.end)
372 S.push_back(to_string(s));
373 }
374 if(S.size() == 2)
375 options.define_macro(S[0], S[1]);
376 }
377 result.push_back(options);
378 }
379 return result;
380}
381
382bool shader_program::attach_program(const context& ctx, std::string file_name, bool show_error, const shader_compile_options& options)
383{
384 std::string content;
385 std::vector<line> lines;
386 if (!open_program_file(file_name, ctx.is_shader_file_cache_enabled(), content, lines, &last_error)) {
387 std::cerr << last_error << std::endl;
388 return false;
389 }
390 if (get_shader_config()->show_file_paths)
391 std::cout << "read shader program <" << file_name << ">" << std::endl;
392 std::string old_shader_path = get_shader_config()->shader_path;
393 std::string path = file::get_path(file_name);
394 if (!path.empty())
395 get_shader_config()->shader_path = path+";"+get_shader_config()->shader_path;
396
397 bool no_error = true;
398 std::string error = "2 : attach command failed";
399 for (unsigned int i=0; i<lines.size(); ++i) {
400 token tok = lines[i];
401 while (tok.begin < tok.end && is_space(*tok.begin))
402 ++tok.begin;
403 std::string l = to_string(tok);
404
405 bool success = true;
406 // ignore empty lines
407 if (l.empty())
408 continue;
409 // ignore comments
410 if (l[0] == '/')
411 continue;
412 if (l.substr(0,5) == "file:")
413 success = attach_file(ctx, l.substr(5), ST_DETECT, options);
414 else if (l.substr(0,12) == "vertex_file:")
415 success = attach_file(ctx, l.substr(12), ST_VERTEX, options);
416 else if(l.substr(0, 10) == "task_file:")
417 success = attach_file(ctx, l.substr(10), ST_TASK, options);
418 else if(l.substr(0, 10) == "mesh_file:")
419 success = attach_file(ctx, l.substr(10), ST_MESH, options);
420 else if (l.substr(0,14) == "geometry_file:")
421 success = attach_file(ctx, l.substr(14), ST_GEOMETRY, options);
422 else if (l.substr(0, 26) == "tessellation_control_file:")
423 success = attach_file(ctx, l.substr(26), ST_TESS_CONTROL, options);
424 else if (l.substr(0, 29) == "tessellation_evaluation_file:")
425 success = attach_file(ctx, l.substr(29), ST_TESS_EVALUATION, options);
426 else if (l.substr(0,14) == "fragment_file:")
427 success = attach_file(ctx, l.substr(14), ST_FRAGMENT, options);
428 else if(l.substr(0, 13) == "compute_file:")
429 success = attach_file(ctx, l.substr(13), ST_COMPUTE, options);
430 else if (l.substr(0,6) == "files:")
431 success = attach_files(ctx, l.substr(6), options);
432 else if (l.substr(0,4) == "dir:")
433 success = attach_dir(ctx, l.substr(4), false);
434 else if (l.substr(0,8) == "rec_dir:")
435 success = attach_dir(ctx, l.substr(8), true);
436 else if (l.substr(0,8) == "program:")
437 success = attach_program(ctx, l.substr(8));
438 else if (l.substr(0,21) == "geometry_shader_info:") {
439 std::vector<token> toks;
440 std::string l1 = l.substr(21);
441 tokenizer(l1).set_ws(";").bite_all(toks);
442 if (toks.size() == 3) {
443 PrimitiveType i_pt = PT_UNDEF, o_pt = PT_UNDEF;
444 int pi, count = 0;
445 for (pi = PT_UNDEF+1; pi < PT_LAST; ++pi) {
447 std::string s = to_string(pt);
448 if (s == to_string(toks[0]))
449 i_pt = pt;
450 if (s == to_string(toks[1]))
451 o_pt = pt;
452 }
453 if (i_pt == PT_UNDEF) {
454 error = "4 : unknown input_type for geometry shader <";
455 error += to_string(toks[0])+">";
456 success = false;
457 }
458 else if (o_pt == PT_UNDEF) {
459 error = "5 : unknown ouput_type for geometry shader <";
460 error += to_string(toks[1])+">";
461 success = false;
462 }
463 else if (!is_integer(toks[2].begin,toks[2].end,count)) {
464 error = "6 : max_output_count of geometry shader must be an integer but received <";
465 error += to_string(toks[2])+">";
466 success = false;
467 }
468 else {
469 set_geometry_shader_info(i_pt, o_pt, count);
470 }
471 }
472 else {
473 success = false;
474 error = "3 : geometry_shader_info takes three arguments separated by colons";
475 }
476 }
477 else if (l.substr(0, 9) == "instance:") {
478 }
479 else if (show_error) {
480 std::cerr << file_name.c_str() << " (" << i + 1
481 << "): warning G0001 : syntax error in line '"
482 << l.c_str() << "'" << std::endl;
483 }
484 if (!success) {
485 if (show_error) {
486 std::cerr << file_name.c_str() << " (" << i+1
487 << "): error G000" << error.c_str() << std::endl;
488 }
489 no_error = false;
490 }
491 }
492
493 get_shader_config()->shader_path = old_shader_path;
494 if (show_error && !no_error)
495 std::cerr << last_error << std::endl;
496 return no_error;
497}
498
500bool shader_program::build_files(const context& ctx, const std::string& base_name, bool show_error) {
501 return build_files(ctx, base_name, {}, show_error);
502}
503
505bool shader_program::build_dir(const context& ctx, const std::string& dir_name, bool recursive, bool show_error) {
506 return build_dir(ctx, dir_name, {}, recursive, show_error);
507}
508
510bool shader_program::build_program(const context& ctx, const std::string& file_name, bool show_error) {
511 return build_program(ctx, file_name, {}, show_error);
512}
513
515bool shader_program::build_files(const context& ctx, const std::string& base_name, const shader_compile_options& options, bool show_error) {
516 return (is_created() || create(ctx)) &&
517 attach_files(ctx, base_name, options) && link(ctx, show_error);
518}
519
520bool shader_program::build_dir(const context& ctx, const std::string& dir_name, const shader_compile_options& options, bool recursive, bool show_error) {
521 return (is_created() || create(ctx)) &&
522 attach_dir(ctx, dir_name, recursive, options) && link(ctx, show_error);
523}
524
526bool shader_program::build_program(const context& ctx, const std::string& file_name, const shader_compile_options& options, bool show_error) {
527 if(!(is_created() || create(ctx)))
528 return false;
529
530 if(!attach_program(ctx, file_name, show_error, options))
531 return false;
532
533 if(!link(ctx, show_error)) {
534 if(show_error) {
535 std::string fn = shader_code::find_file(file_name);
536 std::vector<line> lines;
538 std::string formated_error;
539 for(unsigned int i = 0; i < lines.size(); ++i) {
540 formated_error += fn + "(1) : error G0002: " + to_string(lines[i]) + "\n";
541 }
542 std::cerr << formated_error.c_str() << std::endl;
543 }
544 return false;
545 }
546
547 return true;
548}
549
552{
553 return ctx.get_device_capabilities().max_geometry_shader_output_vertex_count;
554}
555
557void shader_program::update_state(const context& ctx)
558{
559 if (state_out_of_date) {
560 if (nr_attached_geometry_shaders > 0) {
561 if (geometry_shader_output_count < 1)
562 geometry_shader_output_count = get_max_nr_geometry_shader_output_vertices(ctx);
563 ctx.shader_program_set_state(*this);
564 }
565 state_out_of_date = false;
566 }
567}
568
570bool shader_program::link(const context& ctx, bool show_error)
571{
572 update_state(ctx);
573 if (ctx.shader_program_link(*this)) {
574 ctx.shader_program_set_uniform_locations(*this);
575 linked = true;
576 return true;
577 }
578 else {
579 linked = false;
580 if (show_error)
581 std::cerr << "link error:\n" << last_error.c_str() << std::endl;
582 return false;
583 }
584}
585
587{
588 return linked;
589}
590
592void shader_program::set_geometry_shader_info(PrimitiveType input_type, PrimitiveType output_type, int max_output_count)
593{
594 geometry_shader_input_type = input_type;
595 geometry_shader_output_type = output_type;
596 geometry_shader_output_count = max_output_count;
597 state_out_of_date = true;
598}
599
601bool shader_program::enable(context& ctx)
602{
603 if (!is_created()) {
604 ctx.error("attempt to enable shader_program that is not created", this);
605 return false;
606 }
607 if (!is_linked()) {
608 ctx.error("attempt to enable shader_program that is not linked", this);
609 return false;
610 }
611 if (is_enabled()) {
612 ctx.error("attempt to enable shader_program that is already enabled or was not disabled properly", this);
613 return false;
614 }
615 update_state(ctx);
616 bool res = ctx.shader_program_enable(*this);
617 if (res)
618 shader_program_base::is_enabled = true;
619 return res;
620}
621
623bool shader_program::disable(context& ctx)
624{
625 if (!is_enabled()) {
626 ctx.error("attempt to disable shader_program that is not enabled", this);
627 return false;
628 }
629 bool res = ctx.shader_program_disable(*this);
630 shader_program_base::is_enabled = false;
631 return res;
632}
633
635const std::map<std::string, int>& shader_program::get_uniform_locations() const
636{
637 return uniform_locations;
638}
639
641int shader_program::get_uniform_location(const context& ctx, const std::string& name) const
642{
643 // debug fallback: get uniform location from context through GL call
644 //return ctx.get_uniform_location(*this, name);
645
646 // get from cache
647 auto it = uniform_locations.find(name);
648 return it != uniform_locations.end() ? it->second : -1;
649}
650
651bool shader_program::set_material_uniform(const context& ctx, const std::string& name, const cgv::media::illum::surface_material& material, bool generate_error)
652{
653 bool res = set_uniform(ctx, name + ".brdf_type", static_cast<int>(material.brdf_type), generate_error);
654 res = set_uniform(ctx, name + ".diffuse_reflectance", material.diffuse_reflectance, generate_error) && res;
655 res = set_uniform(ctx, name + ".roughness", material.roughness, generate_error) && res;
656 res = set_uniform(ctx, name + ".ambient_occlusion", material.ambient_occlusion, generate_error) && res;
657 res = set_uniform(ctx, name + ".emission", material.emission, generate_error) && res;
658 res = set_uniform(ctx, name + ".specular_reflectance", material.specular_reflectance, generate_error) && res;
659 res = set_uniform(ctx, name + ".roughness_anisotropy", material.roughness_anisotropy, generate_error) && res;
660 res = set_uniform(ctx, name + ".roughness_orientation", material.roughness_orientation, generate_error) && res;
661 res = set_uniform(ctx, name + ".propagation_slow_down", vec2(material.propagation_slow_down.real(), material.propagation_slow_down.imag()), generate_error) && res;
662 res = set_uniform(ctx, name + ".transparency", material.transparency, generate_error) && res;
663 res = set_uniform(ctx, name + ".metalness", material.metalness, generate_error) && res;
664 return res;
665}
666
668bool shader_program::set_textured_material_uniform(const context& ctx, const std::string& name, const textured_material& material, bool generate_error)
669{
670 const char* texture_names[] = {
671 "tex0", "tex1", "tex2", "tex3", "tex4", "tex5"
672 };
673 for (int i = 0; i < (int)material.get_nr_textures(); ++i)
674 if (!set_uniform(ctx, texture_names[i], i, generate_error))
675 return false;
676 bool res = set_material_uniform(ctx, name, material, generate_error);
677 res = set_uniform(ctx, "sRGBA_textures", material.sRGBA_textures, generate_error) && res;
678 res = set_uniform(ctx, "diffuse_index", material.diffuse_index, generate_error) && res;
679 res = set_uniform(ctx, "roughness_index", material.roughness_index, generate_error) && res;
680 res = set_uniform(ctx, "metalness_index", material.metalness_index, generate_error) && res;
681 res = set_uniform(ctx, "ambient_index", material.ambient_index, generate_error) && res;
682 res = set_uniform(ctx, "emission_index", material.emission_index, generate_error) && res;
683 res = set_uniform(ctx, "transparency_index", material.transparency_index, generate_error) && res;
684 res = set_uniform(ctx, "bump_index", material.bump_index, generate_error) && res;
685 res = set_uniform(ctx, "specular_index", material.specular_index, generate_error) && res;
686 return res;
687}
688
689
690
692bool shader_program::set_light_uniform(const context& ctx, const std::string& name, const cgv::media::illum::light_source& L, bool generate_error)
693{
694 if (!set_uniform(ctx, name + ".light_source_type", static_cast<int>(L.get_type()), generate_error))
695 return false;
696 if (!set_uniform(ctx, name + ".position", L.get_position(), generate_error))
697 return false;
698 if (!set_uniform(ctx, name + ".emission", L.get_emission(), generate_error))
699 return false;
700 if (!set_uniform(ctx, name + ".ambient_scale", L.get_ambient_scale(), generate_error))
701 return false;
702 if (!set_uniform(ctx, name + ".spot_direction", L.get_spot_direction(), generate_error))
703 return false;
704 if (!set_uniform(ctx, name + ".spot_exponent", L.get_spot_exponent(), generate_error))
705 return false;
706 if (!set_uniform(ctx, name + ".spot_cos_cutoff", cos(0.01745329252f*L.get_spot_cutoff()), generate_error))
707 return false;
708 if (!set_uniform(ctx, name + ".constant_attenuation", L.get_constant_attenuation(), generate_error))
709 return false;
710 if (!set_uniform(ctx, name + ".linear_attenuation", L.get_linear_attenuation(), generate_error))
711 return false;
712 if (!set_uniform(ctx, name + ".quadratic_attenuation", L.get_quadratic_attenuation(), generate_error))
713 return false;
714 return true;
715}
716
717int shader_program::get_uniform_block_index(const context& ctx, const std::string& name) const
718{
719 return ctx.get_uniform_block_index(*this, name);
720}
721
722bool shader_program::set_uniform_block_binding(const context& ctx, int index, int binding)
723{
724 return ctx.set_uniform_block_binding(*this, index, binding);
725}
726
727bool shader_program::set_uniform_block_binding(const context& ctx, const std::string& name, int binding)
728{
729 int index = ctx.get_uniform_block_index(*this, name);
730 if(index == -1) {
731 ctx.error(std::string("shader_program::set_uniform_block_binding() block <") + name + "> not found", this);
732 return false;
733 }
734 return ctx.set_uniform_block_binding(*this, index, binding);
735}
736
738int shader_program::get_attribute_location(const context& ctx, const std::string& name) const
739{
740 return ctx.get_attribute_location(*this, name);
741}
742
744void shader_program::destruct(const context& ctx)
745{
746 /*
747 while(managed_codes.size() > 0) {
748 delete managed_codes.back();
749 managed_codes.pop_back();
750 }
751 */
752 if (handle) {
753 ctx.shader_program_destruct(*this);
754 handle = 0;
755 }
756 linked = false;
757 state_out_of_date = true;
758 auto_detect_uniforms = true;
759 auto_detect_vertex_attributes = true;
760 nr_attached_geometry_shaders = 0;
761}
762
763 }
764}
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:670
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 is_created() const
return whether component has been created
Definition context.cxx:2231
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
namespace for api independent GPU programming
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
std::string to_string(TextureWrap wrap)
convert texture wrap to string
Definition context.cxx:1099
ShaderType
different shader types
Definition context.h:543
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.
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:692
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