1#include <cgv/base/base.h>
2#include "shader_code.h"
3#include <cgv/base/register.h>
4#include <cgv/base/import.h>
6#include <cgv/utils/tokenizer.h>
7#include <cgv/ppp/ph_processor.h>
8#include <cgv/utils/dir.h>
9#include <cgv/utils/file.h>
10#include <cgv/type/variant.h>
13#pragma warning(disable:4996)
37 return "shader_config";
54 if (
getenv(
"CGV_SHADER_PATH"))
56 else if (
getenv(
"CGV_DIR"))
58 std::string(
getenv(
"CGV_DIR"))+
"/libs/cgv_gl/glsl;"+
59 std::string(
getenv(
"CGV_DIR"))+
"/libs/plot/glsl;"+
60 std::string(
getenv(
"CGV_DIR")) +
"/libs/cgv_app/glsl;" +
61 std::string(
getenv(
"CGV_DIR")) +
"/libs/cgv_g2d/glsl;" +
62 std::string(
getenv(
"CGV_DIR")) +
"/libs/cgv_gpgpu/glsl;" +
63 std::string(
getenv(
"CGV_DIR")) +
"/libs/holo_disp;" +
64 std::string(
getenv(
"CGV_DIR")) +
"/plugins/examples";
71 if (!content.empty()) {
73 if(content[0] ==
char(0xA7))
96 std::vector<line> lines;
99 for (
unsigned int i = 0;
i<lines.size(); ++
i) {
101 if (
to_upper(
l.substr(0, 5)) ==
"ERROR") {
102 std::vector<token>
toks;
105 if (
toks.size() > 4) {
118 std::vector<token>
toks;
120 unsigned int i,
j, k;
int n;
121 for (
i=0;
i<
toks.size(); ++
i) {
125 for (
j=0;
j<
toks.size(); ++
j) {
129 for (k=0; k<
toks.size(); ++k) {
134 std::string
_fn =
fn;
168 std::cerr <<
"shader code not destructed correctly" << std::endl;
176 ctx.shader_code_destruct(*
this);
182 if (file_name.substr(0, 6) ==
"str://" || file_name.substr(0, 6) ==
"res://") {
183 std::map<std::string, resource_file_info>::const_iterator
it =
ref_resource_file_map().find(file_name.substr(6));
189 if (file::exists(file_name))
196 std::map<std::string, resource_file_info>::const_iterator
it =
199 if (
it->second.file_offset == -1)
200 return std::string(
"str://") + file_name;
202 return std::string(
"res://") + file_name;
205 try_name = std::string(
"glsl/") + file_name;
221 if(
end_pos == std::string::npos) {
233 std::string
ext = file::get_extension(file_name);
234 if(
ext.length() > 2) {
235 if(
ext[0] ==
'g' &&
ext[1] ==
'l' ||
236 ext[0] ==
'p' &&
ext[1] ==
'g' &&
ext[2] ==
'l')
259 std::string source =
"";
281 std::string
ext =
to_lower(file::get_extension(file_name));
283 if (
ext ==
"glfs" ||
ext ==
"pglfs")
285 else if (
ext ==
"glgs" ||
ext ==
"pglgs")
287 else if (
ext ==
"glcs" ||
ext ==
"pglcs")
289 else if (
ext ==
"gltc" ||
ext ==
"pgltc")
290 st = ST_TESS_CONTROL;
291 else if (
ext ==
"glte" ||
ext ==
"pglte")
292 st = ST_TESS_EVALUATION;
302 std::vector<line> lines;
305 for(
size_t i = 0;
i < lines.size(); ++
i) {
342std::string shader_code::resolve_includes(
const std::string& source,
bool use_cache, std::string*
_last_error) {
347void shader_code::resolve_version(std::string& source) {
364 if(offset == std::string::npos) {
385 std::vector<cgv::utils::token> tokens;
388 if(!tokens.empty()) {
395 if(tokens.size() > 1) {
400 }
else if(
profile ==
"compatibility") {
468 std::cout <<
"read shader code <" <<
fn <<
">" << std::endl;
472 if (file::get_extension(file_name)[0] ==
'p') {
475 std::string
paths = file::get_path(
fn);
481 if (!
php.parse_string(source))
483 if (!
php.process_to_string(
code))
485 cgv::ppp::clear_variables();
502 resolve_version(source);
504 set_defines_and_snippets(source, options);
507 set_vertex_attrib_locations(source);
521 return ctx.shader_code_create(*
this,
st, source);
542 std::map<std::string, directive_t*>
directives;
546 std::vector<cgv::utils::line> lines;
548 for(
size_t i = 0;
i < lines.size(); ++
i) {
558 for(; ptr <
line.end; ++ptr) {
564 }
else if(c ==
'/') {
565 if(
line.end - ptr > 7) {
578 std::vector<cgv::utils::token> tokens;
584 case DirectiveType::kDefine:
586 if(tokens.size() > 1) {
596 if(tokens.size() > 2) {
603 case DirectiveType::kSnippet:
605 if(tokens.size() == 1) {
606 tokens.front().begin += 3;
607 if(!tokens.front().empty())
624 for(
const auto&
define : options.defines) {
640 out.reserve(source.length());
642 for(
size_t i = 0;
i < lines.size(); ++
i) {
650 case DirectiveType::kDefine:
653 case DirectiveType::kSnippet:
656 return directive->identifier ==
"cgv::" + snippet.id;
687 source = std::move(
out);
691void shader_code::set_vertex_attrib_locations(std::string& source)
693 struct vertex_attribute {
696 std::string type =
"";
697 std::string name =
"";
702 std::string
str =
"layout (location = ";
703 str += std::to_string(location);
711 std::vector<token>
parts;
712 std::vector<token> tokens;
713 std::vector<vertex_attribute>
attribs;
732 if(tokens.size() > 1 && tokens[0] ==
"#version") {
741 if(tokens.size() == 3 && tokens[2] ==
"core")
751 if(tokens.size() > 1 && tokens[0] ==
"#define") {
752 if(tokens[1] ==
"NO_UPGRADE") {
774 for(
unsigned i = 0;
i <
tok.size() - 2; ++
i) {
785 if(c ==
'i' &&
tok[
i + 1] ==
'n' &&
tok[
i + 2] ==
' ') {
809 size_t size = tokens.size();
811 if(tokens.size() > 2) {
818 for(
size_t j = 0;
j < size; ++
j) {
819 auto&
tok = tokens[
j];
820 if(
tok.size() == 1 &&
tok[0] ==
'=')
848 for(
size_t i = 0;
i <
parts.size(); ++
i) {
858 std::string
str =
"";
872 std::string
first_part = source.substr(0, offset);
873 std::string
second_part = source.substr(offset + length + 1);
883 if (!ctx.shader_code_compile(*
this)) {
888 user_data = (
void*&)
id;
910 return user_data != 0;
More advanced text processing for splitting text into lines or tokens.
virtual bool end()
perform the leave part of the action on the current object
complete implementation of method actions that only call one method when entering a node
bool begin()
uses call_method of base class method_action to call the method refered to by the stored method point...
reference counted pointer, which can work together with types that are derived from ref_counted,...
bool empty() const
check if pointer is not yet set
the pre header processor parses a pre header file and converts it to a header file or uses the inform...
the self reflection handler is passed to the virtual self_reflect() method of cgv::base::base.
bool reflect_member(const std::string &member_name, T &member_ref, bool hard_cast=false)
call this to reflect a member by member name and reference to the member.
base class for all drawables, which is independent of the used rendering API.
virtual GPUVendorID get_gpu_vendor_id() const
device information
bool is_shader_file_cache_enabled() const
whether the shader file caches are enabled
const context * ctx_ptr
keep pointer to my context
std::string last_error
a string that contains the last error
static bool shader_file_name_map_initialized
whether the shader file name map is initialized
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.
shader_code()
create shader a shader code object
static std::string read_code_file(const std::string &file_name, std::string *_last_error=0)
read shader code from file and return string with content or empty string if read failed
static std::map< std::string, std::string > code_cache
map that caches shader file contents indexed by their 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
void destruct(const context &ctx)
destruct shader code
~shader_code()
calls the destruct method
static void decode_if_base64(std::string &content)
decode a string if it is base64 encoded
static std::string retrieve_code(const std::string &file_name, bool use_cache, std::string *_last_error)
retreive shader code either by reading the file from disk or from the cache if enabled
ShaderType st
store the shader type
static std::string get_last_error(const std::string &file_name, const std::string &last_error)
format given last error in a way that developer environments can locate errors in the source file
static std::map< std::string, std::string > shader_file_name_map
map that caches full shader file paths indexed by the shader file name
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_code(const context &ctx, const std::string &file_name, ShaderType st=ST_DETECT, const shader_compile_options &options={})
read shader code from file that is searched for with find_file.
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.
static ShaderType detect_shader_type(const std::string &file_name)
detect the shader type from the extension of the given file_name, i.e.
the tokenizer allows to split text into tokens in a convenient way.
tokenizer & set_sep(const std::string &sep, bool merge)
set the list of separators and specify whether succeeding separators are merged into single tokens
tokenizer & set_ws(const std::string &ws)
set the list of white spaces, that separate tokens and are skipped
the base namespace holds the base hierarchy, support for plugin registration and signals
bool read_data_file(const std::string &file_name, std::string &content, bool ascii)
read ascii file into a string
std::map< std::string, resource_file_info > & ref_resource_file_map()
return a reference to a mapping of resource file names to resource file infos
void register_object(base_ptr object, const std::string &options)
register an object and send event to all current registration ref_listeners()
std::string & ref_prog_name()
return a refence to the name of the started executable
shader_config_ptr get_shader_config()
return a reference to the current shader configuration
cgv::data::ref_ptr< shader_config > shader_config_ptr
type of ref counted pointer to shader configuration
ShaderType
different shader types
namespace for compile time type information
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...
std::string & trim(std::string &str, const std::string &chars)
trim white space or other characters from start and end of string
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.
char to_lower(char c)
convert char to lower case
char to_upper(char c)
convert char to upper case
bool is_space(char c)
check if char is a whitespace
std::string decode_base64(std::string const &encoded_string)
decode a base64 encoded string
std::string strip_cpp_comments(const std::string &source, bool correct_new_lines)
remove cpp-style comments from string
bool from_string(std::string &v, const std::string &s)
specialization to extract string value from string
holds options applied before and during shader compilation, such as preprocessor defines and code sni...
std::vector< shader_code_snippet > snippets
shader code snippets
shader_define_map defines
map of pre-processor define names to values
a globally unique shader config is registered by default when the cgv library is used.
std::string get_type_name() const
return "shader_config"
bool show_file_paths
whether to output full paths of read shaders
shader_config()
construct config without file name tracing
bool trace_file_names
whether to keep track of file names
bool self_reflect(cgv::reflect::reflection_handler &srh)
reflect the shader_path member
std::string shader_path
the path used to find shaders with the cgv::utils::file::find_in_paths function
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 ...
bool empty() const
return whether the token is empty
const char * begin
pointers that define the range of characters