]> git.tdb.fi Git - libs/gl.git/blob - source/programbuilder.h
Support custom functions in ProgramBuilder
[libs/gl.git] / source / programbuilder.h
1 #ifndef MSP_GL_PROGRAMBUILDER_H_
2 #define MSP_GL_PROGRAMBUILDER_H_
3
4 #include <map>
5 #include <string>
6 #include <vector>
7 #include <msp/datafile/objectloader.h>
8
9 namespace Msp {
10 namespace GL {
11
12 class Program;
13
14 class invalid_variable_definition: public std::invalid_argument
15 {
16 public:
17         invalid_variable_definition(const std::string &w): std::invalid_argument(w) { }
18         virtual ~invalid_variable_definition() throw() { }
19 };
20
21 /**
22 Generates shaders with common features.
23
24 The shader generation model is based on variable substitutions.  Initially, a
25 goal variable is given for each shader stage.  The expression for computing
26 each variable is examined for further variable definitions.  When there are no
27 more known variables available for substitution, the process terminates.  Any
28 unknown variables at this point are assumed to be provided by OpenGL.
29
30 Variables can be defined in a number of scopes.  The scope of a variable
31 determines where its value is computed.  If a variable is referenced from a
32 scope that comes after the declaration scope, an interface variable is
33 automatically emitted.
34
35 Generated shaders are normally optimized by inlining variables with a single
36 reference into the expression referencing them.  This can result in expressions
37 of several hundreds of characters in length, so optimizations can be disabled
38 with the set_optimize() method for debugging purposes.
39
40 Custom variables can be injected to the generated shaders with the custom
41 member of the StandardFeatures struct.  The syntax is:
42
43   <custom> := [<decl> ...]
44   <decl>   := <scope> <type> <name> [= <expr>] ;
45   <scope>  := uniform | attribute | vertex | fragment
46   <type>   := (any GLSL type)
47   <name>   := (valid identifier)
48   <expr>   := (GLSL expression)
49
50 The custom variables should always include at least one override for a built-in
51 variable; otherwise they will be ignored as no built-in expression references
52 them.
53 */
54 class ProgramBuilder
55 {
56 public:
57         /**
58         Describes the features of a standard shader program.  All boolean features
59         default to false unless stated otherwise.
60         */
61         struct StandardFeatures
62         {
63                 class Loader: public DataFile::ObjectLoader<StandardFeatures>
64                 {
65                 public:
66                         Loader(StandardFeatures &);
67                 };
68
69                 /** Use a diffuse map texture. */
70                 bool texture;
71
72                 /** Use material properties if lighting is true, or vertex colors if
73                 lighting is false. */
74                 bool material;
75
76                 /** Use lighting to compute the brightness of surfaces. */
77                 bool lighting;
78
79                 /** Number of lights to use in lighting calculations.  Defaults to 1. */
80                 unsigned max_lights;
81
82                 /** Use a skylight component for ambient lighting. */
83                 bool skylight;
84
85                 bool fog;
86
87                 /** Use a specular lighting component. */
88                 bool specular;
89
90                 /** Use a normal map texture.  Only used if lighting is true. */
91                 bool normalmap;
92
93                 /** Use a shadow map.  Requires a ShadowMap effect or equivalent in the
94                 pipeline. */
95                 bool shadow;
96
97                 /** Use a reflection cube map.  Requires an EnvironmentMap effect or
98                 equivalend in the pipeline. */
99                 bool reflection;
100
101                 /** Clip primitives against user defined clip planes. */
102                 bool clipping;
103
104                 /** Number of clipping planes to process. */
105                 unsigned max_clip_planes;
106
107                 /** Force the use of legacy shaders conforming to GLSL 1.10.   Defaults
108                 to true if the version of GLSL is less than 1.30, false otherwise. */
109                 bool legacy;
110
111                 /** Custom variables to use in the shader. */
112                 std::string custom;
113
114                 StandardFeatures();
115
116                 std::string create_flags() const;
117         };
118
119 private:
120         enum VariableScope
121         {
122                 NO_SCOPE,
123                 TYPE,
124                 FUNCTION,
125                 UNIFORM,
126                 ATTRIBUTE,
127                 VERTEX,
128                 FRAGMENT
129         };
130
131         enum InterfaceFlags
132         {
133                 NO_INTERFACE = 0,
134                 INPUT = 1,
135                 OUTPUT = 2,
136                 GOAL = 4
137         };
138
139         struct VariableDefinition
140         {
141                 VariableScope scope;
142                 const char *name;
143                 const char *type;
144                 const char *expression;
145                 const char *flags;
146         };
147
148         struct ShaderVariable
149         {
150                 std::string name;
151                 const VariableDefinition *variable;
152                 const VariableDefinition *type;
153                 std::string resolved_name;
154                 std::string resolved_block;
155                 bool fuzzy_space;
156                 std::string resolved_space;
157                 bool array_sum;
158                 std::string array_subscript;
159                 unsigned array_size;
160                 std::list<ShaderVariable *> referenced_vars;
161                 std::list<ShaderVariable *> referenced_by;
162                 bool inlined;
163                 bool inline_parens;
164                 bool in_loop;
165
166                 ShaderVariable(const std::string &);
167
168                 void resolve(const VariableDefinition &);
169                 void resolve(ShaderVariable &);
170                 void resolve_type(const VariableDefinition &);
171                 void resolve_space(const std::string &);
172                 void resolve_array(const StandardFeatures &, unsigned = 0);
173                 void add_reference(ShaderVariable &);
174                 void update_reference(ShaderVariable &, ShaderVariable &);
175                 void check_inline(bool, bool);
176                 bool is_referenced_from(VariableScope) const;
177                 InterfaceFlags get_interface_flags(VariableScope) const;
178                 std::string create_type_declaration() const;
179                 std::string create_declaration(char = 0, bool = false) const;
180                 std::string create_replacement(VariableScope, const char * = 0) const;
181                 std::string create_expression(const char * = 0) const;
182         };
183
184         enum MatchType
185         {
186                 NO_MATCH,
187                 EXACT,
188                 FUZZY,
189                 ARRAY
190         };
191
192         StandardFeatures features;
193         std::list<VariableDefinition> custom_variables;
194         std::string feature_flags;
195         std::map<std::string, std::string> aliases;
196         bool optimize;
197
198         static const VariableDefinition standard_variables[];
199         static const char interfaces[];
200
201 public:
202         ProgramBuilder(const StandardFeatures &);
203
204         /// Enable or disable optimization.  Defaults to enabled.
205         void set_optimize(bool);
206
207         /// Create a new Program with the features associated with the builder.
208         Program *create_program() const;
209
210         /// Generate shaders and add them to an existing program.
211         void add_shaders(Program &) const;
212
213 private:
214         std::string create_source(const std::list<ShaderVariable *> &, VariableScope) const;
215         bool evaluate_flags(const char *) const;
216         static const char *unqualified_name(const char *);
217         static MatchType name_match(const char *, const char *, const char ** = 0);
218         static bool parse_identifier(const char *, unsigned &, unsigned &);
219         static std::vector<std::string> extract_identifiers(const char *);
220         static std::string replace_identifiers(const char *, const std::map<std::string, std::string> &, bool = false);
221         std::string create_expression(const ShaderVariable &, const char * = 0) const;
222 };
223
224 } // namespace GL
225 } // namespace Msp
226
227 #endif