]> git.tdb.fi Git - libs/gl.git/blob - source/programbuilder.h
Improve documentation for a number of classes
[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                 PASSTHROUGH = INPUT|OUTPUT,
128                 GOAL = 4
129         };
130
131         struct VariableDefinition
132         {
133                 VariableScope scope;
134                 const char *name;
135                 const char *type;
136                 const char *expression;
137                 const char *flags;
138         };
139
140         struct ShaderVariable
141         {
142                 std::string name;
143                 const VariableDefinition *variable;
144                 const VariableDefinition *type;
145                 std::string resolved_name;
146                 std::string resolved_block;
147                 bool fuzzy_space;
148                 std::string resolved_space;
149                 bool array_sum;
150                 std::string array_subscript;
151                 unsigned array_size;
152                 std::list<ShaderVariable *> referenced_vars;
153                 std::list<ShaderVariable *> referenced_by;
154                 bool inlined;
155                 bool inline_parens;
156                 bool in_loop;
157
158                 ShaderVariable(const std::string &);
159
160                 void resolve(const VariableDefinition &);
161                 void resolve(ShaderVariable &);
162                 void resolve_type(const VariableDefinition &);
163                 void resolve_space(const std::string &);
164                 void resolve_array(const StandardFeatures &, unsigned = 0);
165                 void add_reference(ShaderVariable &);
166                 void update_reference(ShaderVariable &, ShaderVariable &);
167                 void check_inline(bool, bool);
168                 bool is_referenced_from(VariableScope) const;
169                 InterfaceFlags get_interface_flags(VariableScope) const;
170                 std::string create_type_declaration() const;
171                 std::string create_declaration(char = 0, bool = false) const;
172                 std::string create_replacement(VariableScope, const char * = 0) const;
173                 std::string create_expression(const char * = 0) const;
174         };
175
176         enum MatchType
177         {
178                 NO_MATCH,
179                 EXACT,
180                 FUZZY,
181                 ARRAY
182         };
183
184         StandardFeatures features;
185         std::list<VariableDefinition> custom_variables;
186         std::string feature_flags;
187         std::map<std::string, std::string> aliases;
188         bool optimize;
189
190         static const VariableDefinition standard_variables[];
191         static const char interfaces[];
192
193 public:
194         ProgramBuilder(const StandardFeatures &);
195
196         /// Enable or disable optimization.  Defaults to enabled.
197         void set_optimize(bool);
198
199         /// Create a new Program with the features associated with the builder.
200         Program *create_program() const;
201
202         /// Generate shaders and add them to an existing program.
203         void add_shaders(Program &) const;
204
205 private:
206         std::string create_source(const std::list<ShaderVariable *> &, VariableScope) const;
207         bool evaluate_flags(const char *) const;
208         static const char *unqualified_name(const char *);
209         static MatchType name_match(const char *, const char *, const char ** = 0);
210         static bool parse_identifier(const char *, unsigned &, unsigned &);
211         static std::vector<std::string> extract_identifiers(const char *);
212         static std::string replace_identifiers(const char *, const std::map<std::string, std::string> &, bool = false);
213         std::string create_expression(const ShaderVariable &, const char * = 0) const;
214 };
215
216 } // namespace GL
217 } // namespace Msp
218
219 #endif