]> git.tdb.fi Git - libs/gl.git/blob - source/programbuilder.h
Appease the compiler with some extra copy-ctor's and operator='s
[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 normal_map;
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                 /** Use a geometry shader. */
108                 bool geometry;
109
110                 /** Force the use of legacy shaders conforming to GLSL 1.10.   Defaults
111                 to true if the version of GLSL is less than 1.30, false otherwise. */
112                 bool legacy;
113
114                 /** Custom variables to use in the shader. */
115                 std::string custom;
116
117                 StandardFeatures();
118
119                 std::string create_flags() const;
120         };
121
122 private:
123         enum VariableScope
124         {
125                 NO_SCOPE,
126                 TYPE,
127                 FUNCTION,
128                 UNIFORM,
129                 ATTRIBUTE,
130                 VERTEX,
131                 GEOMETRY,
132                 FRAGMENT,
133                 N_SCOPES
134         };
135
136         enum InterfaceFlags
137         {
138                 NO_INTERFACE = 0,
139                 INPUT = 1,
140                 OUTPUT = 2,
141                 GOAL = 4
142         };
143
144         struct VariableDefinition
145         {
146                 VariableScope scope;
147                 const char *name;
148                 const char *type;
149                 const char *expression;
150                 const char *flags;
151         };
152
153         struct ShaderVariable
154         {
155                 std::string name;
156                 const VariableDefinition *variable;
157                 const VariableDefinition *type;
158                 std::string resolved_name;
159                 std::string resolved_block;
160                 bool fuzzy_space;
161                 std::string resolved_space;
162                 bool array_sum;
163                 std::string array_subscript;
164                 unsigned array_size;
165                 std::list<ShaderVariable *> referenced_vars;
166                 std::list<ShaderVariable *> referenced_by;
167                 bool inlined;
168                 bool inline_parens;
169                 bool in_loop;
170
171                 ShaderVariable(const std::string &);
172
173                 void resolve(const VariableDefinition &);
174                 void resolve(ShaderVariable &);
175                 void resolve_type(const VariableDefinition &);
176                 void resolve_space(const std::string &);
177                 void resolve_array(const StandardFeatures &, unsigned = 0);
178                 void add_reference(ShaderVariable &);
179                 void update_reference(ShaderVariable &, ShaderVariable &);
180                 void check_inline(bool, bool);
181                 bool is_referenced_from(VariableScope) const;
182                 InterfaceFlags get_interface_flags(VariableScope) const;
183                 std::string create_type_declaration() const;
184                 std::string create_declaration(char = 0, bool = false) const;
185                 std::string create_replacement(VariableScope, unsigned, const char * = 0) const;
186                 std::string create_expression(unsigned, const char * = 0) const;
187         };
188
189         enum MatchType
190         {
191                 NO_MATCH,
192                 EXACT,
193                 FUZZY,
194                 ARRAY
195         };
196
197         StandardFeatures features;
198         std::list<VariableDefinition> custom_variables;
199         std::string feature_flags;
200         unsigned enabled_scopes;
201         std::map<std::string, std::string> aliases;
202         bool optimize;
203
204         static const VariableDefinition standard_variables[];
205         static const char interfaces[];
206
207 public:
208         ProgramBuilder(const StandardFeatures &);
209
210         /// Enable or disable optimization.  Defaults to enabled.
211         void set_optimize(bool);
212
213         /// Create a new Program with the features associated with the builder.
214         Program *create_program() const;
215
216         /// Generate shaders and add them to an existing program.
217         void add_shaders(Program &) const;
218
219 private:
220         std::string create_source(const std::list<ShaderVariable *> &, VariableScope) const;
221         bool evaluate_flags(const char *) const;
222         static const char *unqualified_name(const char *);
223         static MatchType name_match(const char *, const char *, const char ** = 0);
224         static bool parse_identifier(const char *, unsigned &, unsigned &);
225         static std::vector<std::string> extract_identifiers(const char *);
226         static std::string replace_identifiers(const char *, const std::map<std::string, std::string> &, bool = false);
227         static VariableScope previous_scope(VariableScope, unsigned);
228         std::string create_expression(const ShaderVariable &, const char * = 0) const;
229 };
230
231 } // namespace GL
232 } // namespace Msp
233
234 #endif