Split out some private utilities into effect_util.cpp, so we do not need to include...
[movit] / effect.cpp
1 #include <GL/glew.h>
2 #include <assert.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <utility>
6
7 #include "effect.h"
8 #include "effect_util.h"
9 #include "util.h"
10
11 bool Effect::set_int(const std::string &key, int value)
12 {
13         if (params_int.count(key) == 0) {
14                 return false;
15         }
16         *params_int[key] = value;
17         return true;
18 }
19
20 bool Effect::set_float(const std::string &key, float value)
21 {
22         if (params_float.count(key) == 0) {
23                 return false;
24         }
25         *params_float[key] = value;
26         return true;
27 }
28
29 bool Effect::set_vec2(const std::string &key, const float *values)
30 {
31         if (params_vec2.count(key) == 0) {
32                 return false;
33         }
34         memcpy(params_vec2[key], values, sizeof(float) * 2);
35         return true;
36 }
37
38 bool Effect::set_vec3(const std::string &key, const float *values)
39 {
40         if (params_vec3.count(key) == 0) {
41                 return false;
42         }
43         memcpy(params_vec3[key], values, sizeof(float) * 3);
44         return true;
45 }
46
47 bool Effect::set_vec4(const std::string &key, const float *values)
48 {
49         if (params_vec4.count(key) == 0) {
50                 return false;
51         }
52         memcpy(params_vec4[key], values, sizeof(float) * 4);
53         return true;
54 }
55
56 void Effect::register_int(const std::string &key, int *value)
57 {
58         assert(params_int.count(key) == 0);
59         params_int[key] = value;
60 }
61
62 void Effect::register_float(const std::string &key, float *value)
63 {
64         assert(params_float.count(key) == 0);
65         params_float[key] = value;
66 }
67
68 void Effect::register_vec2(const std::string &key, float *values)
69 {
70         assert(params_vec2.count(key) == 0);
71         params_vec2[key] = values;
72 }
73
74 void Effect::register_vec3(const std::string &key, float *values)
75 {
76         assert(params_vec3.count(key) == 0);
77         params_vec3[key] = values;
78 }
79
80 void Effect::register_vec4(const std::string &key, float *values)
81 {
82         assert(params_vec4.count(key) == 0);
83         params_vec4[key] = values;
84 }
85
86 void Effect::register_1d_texture(const std::string &key, float *values, size_t size)
87 {
88         assert(params_tex_1d.count(key) == 0);
89
90         Texture1D tex;
91         tex.values = values;
92         tex.size = size;
93         tex.needs_update = false;
94         glGenTextures(1, &tex.texture_num);
95
96         glBindTexture(GL_TEXTURE_1D, tex.texture_num);
97         check_error();
98         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
99         check_error();
100         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
101         check_error();
102         glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE16F_ARB, size, 0, GL_LUMINANCE, GL_FLOAT, values);
103         check_error();
104
105         params_tex_1d[key] = tex;
106 }
107
108 void Effect::invalidate_1d_texture(const std::string &key)
109 {
110         assert(params_tex_1d.count(key) != 0);
111         params_tex_1d[key].needs_update = true;
112 }
113
114 // Output convenience uniforms for each parameter.
115 // These will be filled in per-frame.
116 std::string Effect::output_convenience_uniforms() const
117 {
118         std::string output = "";
119         for (std::map<std::string, float*>::const_iterator it = params_float.begin();
120              it != params_float.end();
121              ++it) {
122                 char buf[256];
123                 sprintf(buf, "uniform float PREFIX(%s);\n", it->first.c_str());
124                 output.append(buf);
125         }
126         for (std::map<std::string, float*>::const_iterator it = params_vec2.begin();
127              it != params_vec2.end();
128              ++it) {
129                 char buf[256];
130                 sprintf(buf, "uniform vec2 PREFIX(%s);\n", it->first.c_str());
131                 output.append(buf);
132         }
133         for (std::map<std::string, float*>::const_iterator it = params_vec3.begin();
134              it != params_vec3.end();
135              ++it) {
136                 char buf[256];
137                 sprintf(buf, "uniform vec3 PREFIX(%s);\n", it->first.c_str());
138                 output.append(buf);
139         }
140         for (std::map<std::string, float*>::const_iterator it = params_vec4.begin();
141              it != params_vec4.end();
142              ++it) {
143                 char buf[256];
144                 sprintf(buf, "uniform vec4 PREFIX(%s);\n", it->first.c_str());
145                 output.append(buf);
146         }
147         for (std::map<std::string, Texture1D>::const_iterator it = params_tex_1d.begin();
148              it != params_tex_1d.end();
149              ++it) {
150                 char buf[256];
151                 sprintf(buf, "uniform sampler1D PREFIX(%s);\n", it->first.c_str());
152                 output.append(buf);
153         }
154         return output;
155 }
156
157 void Effect::set_gl_state(GLuint glsl_program_num, const std::string& prefix, unsigned *sampler_num)
158 {
159         for (std::map<std::string, float*>::const_iterator it = params_float.begin();
160              it != params_float.end();
161              ++it) {
162                 set_uniform_float(glsl_program_num, prefix, it->first, *it->second);
163         }
164         for (std::map<std::string, float*>::const_iterator it = params_vec2.begin();
165              it != params_vec2.end();
166              ++it) {
167                 set_uniform_vec2(glsl_program_num, prefix, it->first, it->second);
168         }
169         for (std::map<std::string, float*>::const_iterator it = params_vec3.begin();
170              it != params_vec3.end();
171              ++it) {
172                 set_uniform_vec3(glsl_program_num, prefix, it->first, it->second);
173         }
174         for (std::map<std::string, float*>::const_iterator it = params_vec4.begin();
175              it != params_vec4.end();
176              ++it) {
177                 set_uniform_vec4(glsl_program_num, prefix, it->first, it->second);
178         }
179
180         for (std::map<std::string, Texture1D>::iterator it = params_tex_1d.begin();
181              it != params_tex_1d.end();
182              ++it) {
183                 glActiveTexture(GL_TEXTURE0 + *sampler_num);
184                 check_error();
185                 glBindTexture(GL_TEXTURE_1D, it->second.texture_num);
186                 check_error();
187
188                 if (it->second.needs_update) {
189                         glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE16F_ARB, it->second.size, 0, GL_LUMINANCE, GL_FLOAT, it->second.values);
190                         check_error();
191                         it->second.needs_update = false;
192                 }
193
194                 set_uniform_int(glsl_program_num, prefix, it->first, *sampler_num);
195                 ++*sampler_num;
196         }
197 }
198
199 void Effect::clear_gl_state() {}