]> git.tdb.fi Git - libs/gl.git/blob - source/programbuilder.h
Eliminate conflicts with Windows headers
[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                 /** Use a specular lighting component. */
86                 bool specular;
87
88                 /** Use a normal map texture.  Only used if lighting is true. */
89                 bool normalmap;
90
91                 /** Use a shadow map.  Requires a ShadowMap effect or equivalent in the
92                 pipeline. */
93                 bool shadow;
94
95                 /** Use a reflection cube map.  Requires an EnvironmentMap effect or
96                 equivalend in the pipeline. */
97                 bool reflection;
98
99                 /** Force the use of legacy shaders conforming to GLSL 1.10.   Defaults
100                 to true if the version of GLSL is less than 1.30, false otherwise. */
101                 bool legacy;
102
103                 /** Custom variables to use in the shader. */
104                 std::string custom;
105
106                 StandardFeatures();
107
108                 std::string create_flags() const;
109         };
110
111 private:
112         enum VariableScope
113         {
114                 NO_SCOPE,
115                 TYPE,
116                 UNIFORM,
117                 ATTRIBUTE,
118                 VERTEX,
119                 FRAGMENT
120         };
121
122         enum InterfaceFlags
123         {
124                 NO_INTERFACE = 0,
125                 INPUT = 1,
126                 OUTPUT = 2,
127                 GOAL = 4
128         };
129
130         struct VariableDefinition
131         {
132                 VariableScope scope;
133                 const char *name;
134                 const char *type;
135                 const char *expression;
136                 const char *flags;
137         };
138
139         struct ShaderVariable
140         {
141                 std::string name;
142                 const VariableDefinition *variable;
143                 const VariableDefinition *type;
144                 std::string resolved_name;
145                 std::string resolved_block;
146                 bool fuzzy_space;
147                 std::string resolved_space;
148                 bool array_sum;
149                 std::string array_subscript;
150                 unsigned array_size;
151                 std::list<ShaderVariable *> referenced_vars;
152                 std::list<ShaderVariable *> referenced_by;
153                 bool inlined;
154                 bool inline_parens;
155                 bool in_loop;
156
157                 ShaderVariable(const std::string &);
158
159                 void resolve(const VariableDefinition &);
160                 void resolve(ShaderVariable &);
161                 void resolve_type(const VariableDefinition &);
162                 void resolve_space(const std::string &);
163                 void resolve_array(const StandardFeatures &, unsigned = 0);
164                 void add_reference(ShaderVariable &);
165                 void update_reference(ShaderVariable &, ShaderVariable &);
166                 void check_inline(bool, bool);
167                 bool is_referenced_from(VariableScope) const;
168                 InterfaceFlags get_interface_flags(VariableScope) const;
169                 std::string create_type_declaration() const;
170                 std::string create_declaration(char = 0, bool = false) const;
171                 std::string create_replacement(VariableScope, const char * = 0) const;
172                 std::string create_expression(const char * = 0) const;
173         };
174
175         enum MatchType
176         {
177                 NO_MATCH,
178                 EXACT,
179                 FUZZY,
180                 ARRAY
181         };
182
183         StandardFeatures features;
184         std::list<VariableDefinition> custom_variables;
185         std::string feature_flags;
186         std::map<std::string, std::string> aliases;
187         bool optimize;
188
189         static const VariableDefinition standard_variables[];
190         static const char interfaces[];
191
192 public:
193         ProgramBuilder(const StandardFeatures &);
194
195         /// Enable or disable optimization.  Defaults to enabled.
196         void set_optimize(bool);
197
198         /// Create a new Program with the features associated with the builder.
199         Program *create_program() const;
200
201         /// Generate shaders and add them to an existing program.
202         void add_shaders(Program &) const;
203
204 private:
205         std::string create_source(const std::list<ShaderVariable *> &, VariableScope) const;
206         bool evaluate_flags(const char *) const;
207         static const char *unqualified_name(const char *);
208         static MatchType name_match(const char *, const char *, const char ** = 0);
209         static bool parse_identifier(const char *, unsigned &, unsigned &);
210         static std::vector<std::string> extract_identifiers(const char *);
211         static std::string replace_identifiers(const char *, const std::map<std::string, std::string> &, bool = false);
212         std::string create_expression(const ShaderVariable &, const char * = 0) const;
213 };
214
215 } // namespace GL
216 } // namespace Msp
217
218 #endif