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