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