]> git.sesse.net Git - movit/blob - effect.cpp
Run include-what-you-use over all of movit. Some hand tuning.
[movit] / effect.cpp
1 #include <Eigen/Core>
2 #include <GL/glew.h>
3 #include <assert.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <utility>
7
8 #include "effect.h"
9 #include "util.h"
10
11 GLint get_uniform_location(GLuint glsl_program_num, const std::string &prefix, const std::string &key)
12 {
13         std::string name = prefix + "_" + key;
14         return glGetUniformLocation(glsl_program_num, name.c_str());
15 }
16
17 void set_uniform_int(GLuint glsl_program_num, const std::string &prefix, const std::string &key, int value)
18 {
19         GLint location = get_uniform_location(glsl_program_num, prefix, key);
20         if (location == -1) {
21                 return;
22         }
23         check_error();
24         glUniform1i(location, value);
25         check_error();
26 }
27
28 void set_uniform_float(GLuint glsl_program_num, const std::string &prefix, const std::string &key, float value)
29 {
30         GLint location = get_uniform_location(glsl_program_num, prefix, key);
31         if (location == -1) {
32                 return;
33         }
34         check_error();
35         glUniform1f(location, value);
36         check_error();
37 }
38
39 void set_uniform_vec2(GLuint glsl_program_num, const std::string &prefix, const std::string &key, const float *values)
40 {
41         GLint location = get_uniform_location(glsl_program_num, prefix, key);
42         if (location == -1) {
43                 return;
44         }
45         check_error();
46         glUniform2fv(location, 1, values);
47         check_error();
48 }
49
50 void set_uniform_vec3(GLuint glsl_program_num, const std::string &prefix, const std::string &key, const float *values)
51 {
52         GLint location = get_uniform_location(glsl_program_num, prefix, key);
53         if (location == -1) {
54                 return;
55         }
56         check_error();
57         glUniform3fv(location, 1, values);
58         check_error();
59 }
60
61 void set_uniform_vec4(GLuint glsl_program_num, const std::string &prefix, const std::string &key, const float *values)
62 {
63         GLint location = get_uniform_location(glsl_program_num, prefix, key);
64         if (location == -1) {
65                 return;
66         }
67         check_error();
68         glUniform4fv(location, 1, values);
69         check_error();
70 }
71
72 void set_uniform_vec4_array(GLuint glsl_program_num, const std::string &prefix, const std::string &key, const float *values, size_t num_values)
73 {
74         GLint location = get_uniform_location(glsl_program_num, prefix, key);
75         if (location == -1) {
76                 return;
77         }
78         check_error();
79         glUniform4fv(location, num_values, values);
80         check_error();
81 }
82
83 void set_uniform_mat3(GLuint glsl_program_num, const std::string &prefix, const std::string &key, const Eigen::Matrix3d& matrix)
84 {
85         GLint location = get_uniform_location(glsl_program_num, prefix, key);
86         if (location == -1) {
87                 return;
88         }
89         check_error();
90
91         // Convert to float (GLSL has no double matrices).
92         float matrixf[9];
93         for (unsigned y = 0; y < 3; ++y) {
94                 for (unsigned x = 0; x < 3; ++x) {
95                         matrixf[y + x * 3] = matrix(y, x);
96                 }
97         }
98
99         glUniformMatrix3fv(location, 1, GL_FALSE, matrixf);
100         check_error();
101 }
102
103 bool Effect::set_int(const std::string &key, int value)
104 {
105         if (params_int.count(key) == 0) {
106                 return false;
107         }
108         *params_int[key] = value;
109         return true;
110 }
111
112 bool Effect::set_float(const std::string &key, float value)
113 {
114         if (params_float.count(key) == 0) {
115                 return false;
116         }
117         *params_float[key] = value;
118         return true;
119 }
120
121 bool Effect::set_vec2(const std::string &key, const float *values)
122 {
123         if (params_vec2.count(key) == 0) {
124                 return false;
125         }
126         memcpy(params_vec2[key], values, sizeof(float) * 2);
127         return true;
128 }
129
130 bool Effect::set_vec3(const std::string &key, const float *values)
131 {
132         if (params_vec3.count(key) == 0) {
133                 return false;
134         }
135         memcpy(params_vec3[key], values, sizeof(float) * 3);
136         return true;
137 }
138
139 bool Effect::set_vec4(const std::string &key, const float *values)
140 {
141         if (params_vec4.count(key) == 0) {
142                 return false;
143         }
144         memcpy(params_vec4[key], values, sizeof(float) * 4);
145         return true;
146 }
147
148 void Effect::register_int(const std::string &key, int *value)
149 {
150         assert(params_int.count(key) == 0);
151         params_int[key] = value;
152 }
153
154 void Effect::register_float(const std::string &key, float *value)
155 {
156         assert(params_float.count(key) == 0);
157         params_float[key] = value;
158 }
159
160 void Effect::register_vec2(const std::string &key, float *values)
161 {
162         assert(params_vec2.count(key) == 0);
163         params_vec2[key] = values;
164 }
165
166 void Effect::register_vec3(const std::string &key, float *values)
167 {
168         assert(params_vec3.count(key) == 0);
169         params_vec3[key] = values;
170 }
171
172 void Effect::register_vec4(const std::string &key, float *values)
173 {
174         assert(params_vec4.count(key) == 0);
175         params_vec4[key] = values;
176 }
177
178 void Effect::register_1d_texture(const std::string &key, float *values, size_t size)
179 {
180         assert(params_tex_1d.count(key) == 0);
181
182         Texture1D tex;
183         tex.values = values;
184         tex.size = size;
185         tex.needs_update = false;
186         glGenTextures(1, &tex.texture_num);
187
188         glBindTexture(GL_TEXTURE_1D, tex.texture_num);
189         check_error();
190         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
191         check_error();
192         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
193         check_error();
194         glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE16F_ARB, size, 0, GL_LUMINANCE, GL_FLOAT, values);
195         check_error();
196
197         params_tex_1d[key] = tex;
198 }
199
200 void Effect::invalidate_1d_texture(const std::string &key)
201 {
202         assert(params_tex_1d.count(key) != 0);
203         params_tex_1d[key].needs_update = true;
204 }
205
206 // Output convenience uniforms for each parameter.
207 // These will be filled in per-frame.
208 std::string Effect::output_convenience_uniforms() const
209 {
210         std::string output = "";
211         for (std::map<std::string, float*>::const_iterator it = params_float.begin();
212              it != params_float.end();
213              ++it) {
214                 char buf[256];
215                 sprintf(buf, "uniform float PREFIX(%s);\n", it->first.c_str());
216                 output.append(buf);
217         }
218         for (std::map<std::string, float*>::const_iterator it = params_vec2.begin();
219              it != params_vec2.end();
220              ++it) {
221                 char buf[256];
222                 sprintf(buf, "uniform vec2 PREFIX(%s);\n", it->first.c_str());
223                 output.append(buf);
224         }
225         for (std::map<std::string, float*>::const_iterator it = params_vec3.begin();
226              it != params_vec3.end();
227              ++it) {
228                 char buf[256];
229                 sprintf(buf, "uniform vec3 PREFIX(%s);\n", it->first.c_str());
230                 output.append(buf);
231         }
232         for (std::map<std::string, float*>::const_iterator it = params_vec4.begin();
233              it != params_vec4.end();
234              ++it) {
235                 char buf[256];
236                 sprintf(buf, "uniform vec4 PREFIX(%s);\n", it->first.c_str());
237                 output.append(buf);
238         }
239         for (std::map<std::string, Texture1D>::const_iterator it = params_tex_1d.begin();
240              it != params_tex_1d.end();
241              ++it) {
242                 char buf[256];
243                 sprintf(buf, "uniform sampler1D PREFIX(%s);\n", it->first.c_str());
244                 output.append(buf);
245         }
246         return output;
247 }
248
249 void Effect::set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num)
250 {
251         for (std::map<std::string, float*>::const_iterator it = params_float.begin();
252              it != params_float.end();
253              ++it) {
254                 set_uniform_float(glsl_program_num, prefix, it->first, *it->second);
255         }
256         for (std::map<std::string, float*>::const_iterator it = params_vec2.begin();
257              it != params_vec2.end();
258              ++it) {
259                 set_uniform_vec2(glsl_program_num, prefix, it->first, it->second);
260         }
261         for (std::map<std::string, float*>::const_iterator it = params_vec3.begin();
262              it != params_vec3.end();
263              ++it) {
264                 set_uniform_vec3(glsl_program_num, prefix, it->first, it->second);
265         }
266         for (std::map<std::string, float*>::const_iterator it = params_vec4.begin();
267              it != params_vec4.end();
268              ++it) {
269                 set_uniform_vec4(glsl_program_num, prefix, it->first, it->second);
270         }
271
272         for (std::map<std::string, Texture1D>::iterator it = params_tex_1d.begin();
273              it != params_tex_1d.end();
274              ++it) {
275                 glActiveTexture(GL_TEXTURE0 + *sampler_num);
276                 check_error();
277                 glBindTexture(GL_TEXTURE_1D, it->second.texture_num);
278                 check_error();
279
280                 if (it->second.needs_update) {
281                         glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE16F_ARB, it->second.size, 0, GL_LUMINANCE, GL_FLOAT, it->second.values);
282                         check_error();
283                         it->second.needs_update = false;
284                 }
285
286                 set_uniform_int(glsl_program_num, prefix, it->first, *sampler_num);
287                 ++*sampler_num;
288         }
289 }
290
291 void Effect::clear_gl_state() {}