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