Vital
Loading...
Searching...
No Matches
shaders.cpp
Go to the documentation of this file.
1#include "shaders.h"
2
3#include "JuceHeader.h"
4
5#include "open_gl_component.h"
6#include "synth_constants.h"
7
8#if JUCE_OPENGL_ES || OPENGL_ES
9 #define HIGHP "highp"
10 #define MEDIUMP "mediump"
11 #define LOWP "lowp"
12#else
13 #define HIGHP
14 #define MEDIUMP
15 #define LOWP
16#endif
17
18#define FILTER_RESPONSE_UNIFORMS \
19 "uniform " MEDIUMP " float midi_cutoff;\n" \
20 "uniform " MEDIUMP " float resonance;\n" \
21 "uniform " MEDIUMP " float drive;\n" \
22 "uniform " MEDIUMP " float mix;\n" \
23 "uniform " MEDIUMP " float db24;\n" \
24 "uniform " MEDIUMP " float stage0;\n" \
25 "uniform " MEDIUMP " float stage1;\n" \
26 "uniform " MEDIUMP " float stage2;\n" \
27 "uniform " MEDIUMP " float stage3;\n" \
28 "uniform " MEDIUMP " float stage4;\n"
29
30#define FILTER_RESPONSE_CONSTANTS \
31 "const " MEDIUMP " float kMinMidiNote = 8.0;\n" \
32 "const " MEDIUMP " float kPi = 3.14159265359;\n" \
33 "const " MEDIUMP " float kMaxMidiNote = 137.0;\n" \
34 "const " MEDIUMP " float kMidi0Frequency = 8.1757989156;\n" \
35 "const " MEDIUMP " float kMinDb = -30.0;\n" \
36 "const " MEDIUMP " float kMaxDb = 20.0;\n" \
37
38#define RESPONSE_TOOLS \
39 "vec2 complexMultiply(vec2 a, vec2 b) {\n" \
40 " return vec2(a.x * b.x - a.y * b.y, a.y * b.x + a.x * b.y);\n" \
41 "}\n" \
42 "vec2 complexReciprocal(vec2 num) {\n" \
43 " " MEDIUMP " vec2 conjugate = vec2(num.x, -num.y);\n" \
44 " " MEDIUMP " vec2 denominator = complexMultiply(num, conjugate);\n" \
45 " return vec2(conjugate.x / denominator.x, conjugate.y / denominator.x);\n" \
46 "}\n" \
47 "vec2 complexDivide(vec2 a, vec2 b) {\n" \
48 " " MEDIUMP " vec2 conjugate = vec2(b.x, -b.y);\n" \
49 " " MEDIUMP " vec2 num = complexMultiply(a, conjugate);\n" \
50 " " MEDIUMP " vec2 den = complexMultiply(b, conjugate);\n" \
51 " return vec2(num.x / den.x, num.y / den.x);\n" \
52 "}\n" \
53 "vec2 onePoleInvertResponse(float cutoff) {\n" \
54 " return vec2(1.0, cutoff);\n" \
55 "}\n" \
56 "vec2 onePoleResponse(float cutoff) {\n" \
57 " return complexReciprocal(vec2(1.0, cutoff));\n" \
58 "}\n" \
59 "float magnitudeToDb(float magnitude) {\n" \
60 " return 8.685889638065037 * log(magnitude);\n" \
61 "}\n" \
62 "float getCutoffRatio(float x, float midi_cutoff) {\n" \
63 " " MEDIUMP " float percent = 0.5 * (x + 1.0);\n" \
64 " " MEDIUMP " float midi_note = kMinMidiNote + percent * (kMaxMidiNote - kMinMidiNote);\n" \
65 " return pow(2.0, min((midi_note - midi_cutoff) / 12.0, 8.0));\n" \
66 "}\n" \
67 "float getFrequencyForX(float x) {\n" \
68 " " MEDIUMP " float percent = 0.5 * (x + 1.0);\n" \
69 " " MEDIUMP " float midi_note = kMinMidiNote + percent * (kMaxMidiNote - kMinMidiNote);\n" \
70 " return kMidi0Frequency * pow(2.0, midi_note / 12.0);\n" \
71 "}\n" \
72 "float getYForResponse(vec2 response) {\n" \
73 " " MEDIUMP " float magnitude_response = length(response);\n" \
74 " " MEDIUMP " float db = magnitudeToDb(magnitude_response);\n" \
75 " return 2.0 * (db - kMinDb) / (kMaxDb - kMinDb) - 1.0;\n" \
76 "}\n" \
77 "vec4 computePosition(vec4 start_position, vec2 response) {\n" \
78 " " MEDIUMP " vec4 result = start_position;\n" \
79 " result.y = getYForResponse(response);\n" \
80 " return result;\n" \
81 "}\n"
82
83namespace {
84 const char* kImageVertexShader =
85 "attribute " MEDIUMP " vec4 position;\n"
86 "attribute " MEDIUMP " vec2 tex_coord_in;\n"
87 "\n"
88 "varying " MEDIUMP " vec2 tex_coord_out;\n"
89 "\n"
90 "void main() {\n"
91 " tex_coord_out = tex_coord_in;\n"
92 " gl_Position = vec4(position.xy, 1.0, 1.0);\n"
93 "}\n";
94
95 const char* kImageFragmentShader =
96 "varying " MEDIUMP " vec2 tex_coord_out;\n"
97 "\n"
98 "uniform sampler2D image;\n"
99 "\n"
100 "void main() {\n"
101 " gl_FragColor = texture2D(image, tex_coord_out);\n"
102 "}\n";
103
104 const char* kTintedImageFragmentShader =
105 "varying " MEDIUMP " vec2 tex_coord_out;\n"
106 "\n"
107 "uniform sampler2D image;\n"
108 "uniform " MEDIUMP " vec4 color;\n"
109 "\n"
110 "void main() {\n"
111 " " MEDIUMP " vec4 image_color = texture2D(image, tex_coord_out);\n"
112 " image_color.r *= color.r;\n"
113 " image_color.g *= color.g;\n"
114 " image_color.b *= color.b;\n"
115 " image_color.a *= color.a;\n"
116 " gl_FragColor = image_color;\n"
117 "}\n";
118
119 const char* kPassthroughVertexShader =
120 "attribute " MEDIUMP " vec4 position;\n"
121 "attribute " MEDIUMP " vec2 dimensions;\n"
122 "attribute " MEDIUMP " vec2 coordinates;\n"
123 "attribute " MEDIUMP " vec4 shader_values;\n"
124 "\n"
125 "varying " MEDIUMP " vec2 dimensions_out;\n"
126 "varying " MEDIUMP " vec2 coordinates_out;\n"
127 "varying " MEDIUMP " vec4 shader_values_out;\n"
128 "\n"
129 "void main() {\n"
130 " dimensions_out = dimensions;\n"
131 " coordinates_out = coordinates;\n"
132 " shader_values_out = shader_values;\n"
133 " gl_Position = position;\n"
134 "}\n";
135
136 const char* kScaleVertexShader =
137 "attribute " MEDIUMP " vec4 position;\n"
138 "uniform " MEDIUMP " vec2 scale;\n"
139 "\n"
140 "void main() {\n"
141 " gl_Position = position;\n"
142 " gl_Position.x = gl_Position.x * scale.x;\n"
143 " gl_Position.y = gl_Position.y * scale.y;\n"
144 " gl_Position.z = 0.0;\n"
145 " gl_Position.a = 1.0;\n"
146 "}\n";
147
148 const char* kRotaryModulationVertexShader =
149 "attribute " MEDIUMP " vec4 position;\n"
150 "attribute " MEDIUMP " vec2 coordinates;\n"
151 "attribute " MEDIUMP " vec4 range;\n"
152 "attribute " MEDIUMP " float meter_radius;\n"
153 "\n"
154 "varying " MEDIUMP " vec2 coordinates_out;\n"
155 "varying " MEDIUMP " vec4 range_out;\n"
156 "varying " MEDIUMP " float meter_radius_out;\n"
157 "\n"
158 "void main() {\n"
159 " coordinates_out = coordinates;\n"
160 " range_out = range;\n"
161 " meter_radius_out = meter_radius;\n"
162 " gl_Position = position;\n"
163 "}\n";
164
165 const char* kLinearModulationVertexShader =
166 "attribute " MEDIUMP " vec4 position;\n"
167 "attribute " MEDIUMP " vec2 coordinates;\n"
168 "attribute " MEDIUMP " vec4 range;\n"
169 "\n"
170 "varying " MEDIUMP " vec2 coordinates_out;\n"
171 "varying " MEDIUMP " vec4 range_out;\n"
172 "\n"
173 "void main() {\n"
174 " coordinates_out = coordinates;\n"
175 " range_out = range;\n"
176 " gl_Position = position;\n"
177 "}\n";
178
179 const char* kGainMeterVertexShader =
180 "attribute " MEDIUMP " vec4 position;\n"
181 "\n"
182 "varying " MEDIUMP " vec2 position_out;\n"
183 "\n"
184 "void main() {\n"
185 " gl_Position = position;\n"
186 " position_out = position.xz;\n"
187 "}\n";
188
189 const char* kGainMeterFragmentShader =
190 "varying " MEDIUMP " vec2 position_out;\n"
191 "uniform " MEDIUMP " vec4 color_from;\n"
192 "uniform " MEDIUMP " vec4 color_to;\n"
193 "void main() {\n"
194 " " MEDIUMP " float t = (position_out.x + 1.0) / 2.0;\n"
195 " gl_FragColor = color_to * t + color_from * (1.0 - t);\n"
196 "}\n";
197
198 const char* kAnalogFilterResponseVertexShader =
199 "in " MEDIUMP " vec2 position;\n"
200 "out " MEDIUMP " float response_out;\n"
204 "\n"
205 "void main() {\n"
206 " " MEDIUMP " vec2 one_pole = onePoleResponse(getCutoffRatio(position.x, midi_cutoff));\n"
207 " " MEDIUMP " vec2 low = complexMultiply(one_pole, one_pole);\n"
208 " " MEDIUMP " vec2 band = one_pole - low;\n"
209 " " MEDIUMP " vec2 high = vec2(1.0, 0.0) - one_pole - band;\n"
210 " " MEDIUMP " vec2 two_stage_pre = stage3 * low + stage1 * band + stage4 * high;\n"
211 " " MEDIUMP " vec2 two_stage = stage0 * low + stage1 * band + stage2 * high;\n"
212 " " MEDIUMP " vec2 feedback = complexMultiply(one_pole, vec2(1.0, 0.0) - one_pole);\n"
213 " " MEDIUMP " vec2 denominator_pre = vec2(1.0, 0.0) - feedback;\n"
214 " " MEDIUMP " vec2 denominator = vec2(1.0, 0.0) - resonance * feedback;\n"
215 " " MEDIUMP " vec2 response_pre = complexDivide(two_stage_pre, denominator_pre);\n"
216 " " MEDIUMP " vec2 response_res = complexDivide(two_stage, denominator);\n"
217 " " MEDIUMP " vec2 response = drive * response_res;\n"
218 " response = response + db24 * (complexMultiply(response_pre, response) - response);\n"
219 " response = mix * response + vec2(1.0 - mix, 0.0);\n"
220 " response_out = getYForResponse(response);\n"
221 "}\n";
222
223 const char* kCombFilterResponseVertexShader =
224 "in " MEDIUMP " vec2 position;\n"
225 "out " MEDIUMP " float response_out;\n"
229 "const " MEDIUMP " float kMaxCycles = 6.0;\n"
230 "\n"
231 "void main() {\n"
232 " " MEDIUMP " float ratio = getCutoffRatio(position.x, midi_cutoff);\n"
233 " " MEDIUMP " float ratio_diff = getCutoffRatio(position.x + 0.02, midi_cutoff) - ratio;\n"
234 " " MEDIUMP " float max_step = step(kMaxCycles, ratio);\n"
235 " " MEDIUMP " vec2 tick = resonance * vec2(cos(2.0 * kPi * ratio), -sin(2.0 * kPi * ratio));\n"
236 " " MEDIUMP " vec2 low_pass = onePoleResponse(getCutoffRatio(position.x, stage2));\n"
237 " " MEDIUMP " vec2 high_pass = vec2(1.0, 0.0) - low_pass;\n"
238 " " MEDIUMP " vec2 one_pole = stage0 * low_pass + stage1 * high_pass;\n"
239 " " MEDIUMP " vec2 high_pass2 = vec2(1.0, 0.0) - onePoleResponse(getCutoffRatio(position.x, stage3));\n"
240 " " MEDIUMP " vec2 filter_input = vec2(1.0 - 0.5 * abs(resonance), 0.0);\n"
241 " " MEDIUMP " filter_input = complexMultiply(complexMultiply(filter_input, one_pole), high_pass2);\n"
242 " " MEDIUMP " vec2 denominator = vec2(1.0, 0.0) - complexMultiply(complexMultiply(tick, one_pole), high_pass2);\n"
243 " " MEDIUMP " float round_value = complexMultiply(one_pole, high_pass2).x * abs(resonance);\n"
244 " " MEDIUMP " vec2 denominator_round = vec2(1.0 - round_value, 0.0);\n"
245 " " MEDIUMP " vec2 denominator_round_down = vec2(1.0 + round_value, 0.0);\n"
246 " " MEDIUMP " float max_step_mult = 1.0 - position.y;\n"
247 " " MEDIUMP " vec2 max_step_denominator = max_step_mult * denominator_round + (1.0 - max_step_mult) * denominator_round_down;\n"
248 " denominator = max_step * max_step_denominator + (1.0 - max_step) * denominator;\n"
249 " " MEDIUMP " float denominator_round_step = 1.0 - max(max_step, step(ratio_diff, length(denominator)));\n"
250 " denominator = denominator_round_step * denominator_round + (1.0 - denominator_round_step) * denominator;\n"
251 " " MEDIUMP " vec2 response = complexDivide(drive * filter_input, denominator);\n"
252 " response = mix * response + vec2(1.0 - mix, 0.0);\n"
253 " response_out = getYForResponse(response);\n"
254 "}\n";
255
256 const char* kPositiveFlangeFilterResponseVertexShader =
257 "in " MEDIUMP " vec2 position;\n"
258 "out " MEDIUMP " float response_out;\n"
262 "const " MEDIUMP " float kMaxCycles = 8.0;\n"
263 "\n"
264 "void main() {\n"
265 " " MEDIUMP " float ratio = getCutoffRatio(position.x, midi_cutoff);\n"
266 " " MEDIUMP " float ratio_diff = getCutoffRatio(position.x + 0.02, midi_cutoff) - ratio;\n"
267 " " MEDIUMP " float max_step = step(kMaxCycles, ratio);\n"
268 " " MEDIUMP " vec2 delay = vec2(cos(2.0 * kPi * ratio), -sin(2.0 * kPi * ratio));\n"
269 " " MEDIUMP " vec2 tick = resonance * delay;\n"
270 " " MEDIUMP " vec2 low_pass = onePoleResponse(getCutoffRatio(position.x, stage2));\n"
271 " " MEDIUMP " vec2 high_pass = vec2(1.0, 0.0) - low_pass;\n"
272 " " MEDIUMP " vec2 one_pole = stage0 * low_pass + stage1 * high_pass;\n"
273 " " MEDIUMP " vec2 high_pass2 = vec2(1.0, 0.0) - onePoleResponse(getCutoffRatio(position.x, stage3));\n"
274 " " MEDIUMP " vec2 filter_input = vec2(0.70710678119, 0.0);\n"
275 " " MEDIUMP " vec2 delay_input = complexMultiply(complexMultiply(filter_input, one_pole), high_pass2);\n"
276 " " MEDIUMP " vec2 denominator = vec2(1.0, 0.0) - tick;\n"
277 " " MEDIUMP " vec2 round_value = complexMultiply(one_pole, high_pass2) * resonance;\n"
278 " " MEDIUMP " vec2 denominator_round = complexMultiply(delay, vec2(1.0, 0.0) - round_value);\n"
279 " " MEDIUMP " vec2 denominator_round_down = complexMultiply(-delay, vec2(1.0, 0.0) + round_value);\n"
280 " " MEDIUMP " float max_step_mult = 1.0 - position.y;\n"
281 " " MEDIUMP " vec2 max_step_denominator = max_step_mult * denominator_round + (1.0 - max_step_mult) * denominator_round_down;\n"
282 " denominator = max_step * max_step_denominator + (1.0 - max_step) * denominator;\n"
283 " " MEDIUMP " float denominator_round_step = 1.0 - max(max_step, step(ratio_diff, length(denominator)));\n"
284 " denominator = denominator_round_step * denominator_round + (1.0 - denominator_round_step) * denominator;\n"
285 " " MEDIUMP " vec2 response = filter_input * drive + complexMultiply(complexDivide(delay_input, denominator), delay);\n"
286 " response = mix * response + vec2(1.0 - mix, 0.0);\n"
287 " response_out = getYForResponse(response);\n"
288 "}\n";
289
290 const char* kNegativeFlangeFilterResponseVertexShader =
291 "in " MEDIUMP " vec2 position;\n"
292 "out " MEDIUMP " float response_out;\n"
296 "const " MEDIUMP " float kMaxCycles = 8.0;\n"
297 "\n"
298 "void main() {\n"
299 " " MEDIUMP " float ratio = getCutoffRatio(position.x, midi_cutoff + 12.0);\n"
300 " " MEDIUMP " float max_step = step(kMaxCycles, ratio);\n"
301 " " MEDIUMP " vec2 delay = vec2(cos(2.0 * kPi * ratio), -sin(2.0 * kPi * ratio));\n"
302 " " MEDIUMP " vec2 tick = -resonance * delay;\n"
303 " " MEDIUMP " vec2 low_pass = onePoleResponse(getCutoffRatio(position.x, stage2));\n"
304 " " MEDIUMP " vec2 high_pass = vec2(1.0, 0.0) - low_pass;\n"
305 " " MEDIUMP " vec2 one_pole = stage0 * low_pass + stage1 * high_pass;\n"
306 " " MEDIUMP " vec2 high_pass2 = vec2(1.0, 0.0) - onePoleResponse(getCutoffRatio(position.x, stage3));\n"
307 " " MEDIUMP " vec2 filter_input = vec2(0.70710678119, 0.0);\n"
308 " " MEDIUMP " vec2 delay_input = complexMultiply(complexMultiply(filter_input, one_pole), high_pass2);\n"
309 " " MEDIUMP " vec2 denominator = vec2(1.0, 0.0) - complexMultiply(tick, complexMultiply(one_pole, high_pass2));\n"
310 " " MEDIUMP " vec2 round_value = -complexMultiply(one_pole, high_pass2) * resonance;\n"
311 " " MEDIUMP " vec2 denominator_round = complexMultiply(delay, vec2(1.0, 0.0) - round_value);\n"
312 " " MEDIUMP " vec2 denominator_round_down = complexMultiply(-delay, vec2(1.0, 0.0) + round_value);\n"
313 " " MEDIUMP " float max_step_mult = 1.0 - position.y;\n"
314 " " MEDIUMP " vec2 max_step_denominator = max_step_mult * denominator_round + (1.0 - max_step_mult) * denominator_round_down;\n"
315 " denominator = max_step * max_step_denominator + (1.0 - max_step) * denominator;\n"
316 " " MEDIUMP " vec2 response = filter_input * drive - complexMultiply(complexDivide(delay_input, denominator), delay);\n"
317 " response = mix * response + vec2(1.0 - mix, 0.0);\n"
318 " response_out = getYForResponse(response);\n"
319 "}\n";
320
321 const char* kDigitalFilterResponseVertexShader =
322 "in " MEDIUMP " vec2 position;\n"
323 "out " MEDIUMP " float response_out;\n"
327 "\n"
328 "void main() {\n"
329 " " MEDIUMP " float g = getCutoffRatio(position.x, midi_cutoff);\n"
330 " " MEDIUMP " vec2 g2 = vec2(g * g, 0.0);\n"
331 " " MEDIUMP " vec2 denominator = g2 + vec2(0.0, g * resonance) + vec2(-1.0, 0.0);\n"
332 " " MEDIUMP " vec2 numerator = -stage0 * vec2(1.0, 0.0) + stage1 * vec2(0.0, g) + stage2 * g2;\n"
333 " " MEDIUMP " vec2 numerator_pre = -stage3 * vec2(1.0, 0.0) + stage1 * vec2(0.0, g) + stage4 * g2;\n"
334 " " MEDIUMP " vec2 response = complexDivide(numerator, denominator);\n"
335 " " MEDIUMP " vec2 pre_denominator = g2 + vec2(0.0, g) + vec2(-1.0, 0.0);\n"
336 " " MEDIUMP " vec2 pre_response = complexDivide(numerator_pre, pre_denominator);\n"
337 " response = response + db24 * (complexMultiply(response, pre_response) - response);\n"
338 " response *= drive;\n"
339 " response = mix * response + vec2(1.0 - mix, 0.0);\n"
340 " response_out = getYForResponse(response);\n"
341 "}\n";
342
343 const char* kDiodeFilterResponseVertexShader =
344 "in " MEDIUMP " vec2 position;\n"
345 "out " MEDIUMP " float response_out;\n"
349 "\n"
350 "void main() {\n"
351 " " MEDIUMP " float ratio = getCutoffRatio(position.x, midi_cutoff);\n"
352 " " MEDIUMP " vec2 one_pole = onePoleResponse(ratio);\n"
353 " " MEDIUMP " vec2 high_pass_one_pole = onePoleResponse(ratio / stage0);\n"
354 " " MEDIUMP " vec2 high = vec2(1.0, 0.0) - high_pass_one_pole * 2.0 + complexMultiply(high_pass_one_pole, high_pass_one_pole);\n"
355 " " MEDIUMP " vec2 high_feedback = complexMultiply(high_pass_one_pole, vec2(1.0, 0.0) - high_pass_one_pole);\n"
356 " " MEDIUMP " vec2 high_denominator = vec2(1.0, 0.0) - high_feedback;\n"
357 " " MEDIUMP " vec2 high_pass_response = complexDivide(high, high_denominator);\n"
358 " high_pass_response = vec2(1.0, 0.0) + db24 * (high_pass_response + vec2(-1.0, 0.0));\n"
359 " " MEDIUMP " vec2 loop = complexMultiply(one_pole, one_pole);\n"
360 " " MEDIUMP " vec2 series = 0.125 * complexMultiply(loop, loop);\n"
361 " " MEDIUMP " vec2 chain = complexDivide(series, vec2(1.0, 0.0) + series - loop);"
362 " " MEDIUMP " vec2 numerator = drive * chain;\n"
363 " " MEDIUMP " vec2 denominator = vec2(1.0, 0.0) + resonance * chain;\n"
364 " " MEDIUMP " vec2 response = complexDivide(numerator, denominator);\n"
365 " response = mix * response + vec2(1.0 - mix, 0.0);\n"
366 " response = complexMultiply(response, high_pass_response);\n"
367 " response_out = getYForResponse(response);\n"
368 "}\n";
369
370 const char* kDirtyFilterResponseVertexShader =
371 "in " MEDIUMP " vec2 position;\n"
372 "out " MEDIUMP " float response_out;\n"
376 "\n"
377 "void main() {\n"
378 " " MEDIUMP " vec2 one_pole = onePoleResponse(getCutoffRatio(position.x, midi_cutoff));\n"
379 " " MEDIUMP " vec2 low = complexMultiply(one_pole, one_pole);\n"
380 " " MEDIUMP " vec2 band = one_pole - low;\n"
381 " " MEDIUMP " vec2 high = vec2(1.0, 0.0) - one_pole - band;\n"
382 " " MEDIUMP " vec2 two_stage_pre = stage3 * low + stage1 * band + stage4 * high;\n"
383 " " MEDIUMP " vec2 two_stage = stage0 * low + stage1 * band + stage2 * high;\n"
384 " " MEDIUMP " vec2 feedback = complexMultiply(one_pole, vec2(1.0, 0.0) - one_pole);\n"
385 " " MEDIUMP " vec2 denominator_pre = vec2(1.0, 0.0) - feedback;\n"
386 " " MEDIUMP " vec2 denominator = vec2(1.0 / resonance, 0.0) - feedback;\n"
387 " " MEDIUMP " vec2 resonance_loop = complexDivide(band, denominator);\n"
388 " " MEDIUMP " vec2 response_pre = complexDivide(two_stage_pre, denominator_pre);\n"
389 " " MEDIUMP " vec2 response_res = complexMultiply(two_stage, vec2(1.0, 0.0) + resonance_loop);\n"
390 " " MEDIUMP " vec2 response = drive * response_res;\n"
391 " response = response + db24 * (complexMultiply(response_pre, response) - response);\n"
392 " response = mix * response + vec2(1.0 - mix, 0.0);\n"
393 " response_out = getYForResponse(response);\n"
394 "}\n";
395
396 const char* kFormantFilterResponseVertexShader =
397 "in " MEDIUMP " vec2 position;\n"
398 "out " MEDIUMP " float response_out;\n"
402 "uniform " MEDIUMP " vec4 formant_cutoff;\n"
403 "uniform " MEDIUMP " vec4 formant_resonance;\n"
404 "uniform " MEDIUMP " vec4 low;\n"
405 "uniform " MEDIUMP " vec4 band;\n"
406 "uniform " MEDIUMP " vec4 high;\n"
407 "uniform " MEDIUMP " float sample_rate;\n"
408 "\n"
409 "void main() {\n"
410 " " MEDIUMP " float g0 = getCutoffRatio(position.x, formant_cutoff[0]);\n"
411 " " MEDIUMP " vec2 g0_sqr = vec2(g0 * g0, 0.0);\n"
412 " " MEDIUMP " vec2 denominator0 = g0_sqr + vec2(0.0, g0 * formant_resonance[0]) + vec2(-1.0, 0.0);\n"
413 " " MEDIUMP " vec2 numerator0 = -low[0] * vec2(1.0, 0.0) + band[0] * vec2(0.0, g0) + high[0] * g0_sqr;\n"
414 " " MEDIUMP " vec2 response0 = complexDivide(numerator0, denominator0);\n"
415 " " MEDIUMP " float g1 = getCutoffRatio(position.x, formant_cutoff[1]);\n"
416 " " MEDIUMP " vec2 g1_sqr = vec2(g1 * g1, 0.0);\n"
417 " " MEDIUMP " vec2 denominator1 = g1_sqr + vec2(0.0, g1 * formant_resonance[1]) + vec2(-1.0, 0.0);\n"
418 " " MEDIUMP " vec2 numerator1 = -low[1] * vec2(1.0, 0.0) + band[1] * vec2(0.0, g1) + high[1] * g1_sqr;\n"
419 " " MEDIUMP " vec2 response1 = complexDivide(numerator1, denominator1);\n"
420 " " MEDIUMP " float g2 = getCutoffRatio(position.x, formant_cutoff[2]);\n"
421 " " MEDIUMP " vec2 g2_sqr = vec2(g2 * g2, 0.0);\n"
422 " " MEDIUMP " vec2 denominator2 = g2_sqr + vec2(0.0, g2 * formant_resonance[2]) + vec2(-1.0, 0.0);\n"
423 " " MEDIUMP " vec2 numerator2 = -low[2] * vec2(1.0, 0.0) + band[2] * vec2(0.0, g2) + high[2] * g2_sqr;\n"
424 " " MEDIUMP " vec2 response2 = complexDivide(numerator2, denominator2);\n"
425 " " MEDIUMP " float g3 = getCutoffRatio(position.x, formant_cutoff[3]);\n"
426 " " MEDIUMP " vec2 g3_sqr = vec2(g3 * g3, 0.0);\n"
427 " " MEDIUMP " vec2 denominator3 = g3_sqr + vec2(0.0, g3 * formant_resonance[3]) + vec2(-1.0, 0.0);\n"
428 " " MEDIUMP " vec2 numerator3 = -low[3] * vec2(1.0, 0.0) + band[3] * vec2(0.0, g3) + high[3] * g3_sqr;\n"
429 " " MEDIUMP " vec2 response3 = complexDivide(numerator3, denominator3);\n"
430 " " MEDIUMP " vec2 response = response0 + response1 + response2 + response3;\n"
431 " response = mix * response + vec2(1.0 - mix, 0.0);\n"
432 " response_out = getYForResponse(response);\n"
433 "}\n";
434
435 const char* kLadderFilterResponseVertexShader =
436 "in " MEDIUMP " vec2 position;\n"
437 "out " MEDIUMP " float response_out;\n"
441 "\n"
442 "void main() {\n"
443 " " MEDIUMP " vec2 one_pole_invert = onePoleInvertResponse(getCutoffRatio(position.x, midi_cutoff));\n"
444 " " MEDIUMP " vec2 two_pole_invert = complexMultiply(one_pole_invert, one_pole_invert);\n"
445 " " MEDIUMP " vec2 three_pole_invert = complexMultiply(one_pole_invert, two_pole_invert);\n"
446 " " MEDIUMP " vec2 four_pole_invert = complexMultiply(one_pole_invert, three_pole_invert);\n"
447 " " MEDIUMP " vec2 numerator = drive * (stage0 * four_pole_invert + stage1 * three_pole_invert + \n"
448 " stage2 * two_pole_invert + stage3 * one_pole_invert + \n"
449 " vec2(stage4, 0.0));\n"
450 " " MEDIUMP " vec2 denominator = four_pole_invert + vec2(resonance, 0.0);\n"
451 " " MEDIUMP " vec2 response = complexDivide(numerator, denominator);\n"
452 " response = mix * response + vec2(1.0 - mix, 0.0);\n"
453 " response_out = getYForResponse(response);\n"
454 "}\n";
455
456 const char* kPhaserFilterResponseVertexShader =
457 "in " MEDIUMP " vec2 position;\n"
458 "out " MEDIUMP " float response_out;\n"
462 "\n"
463 "void main() {\n"
464 " " MEDIUMP " float g = getCutoffRatio(position.x, midi_cutoff);\n"
465 " " MEDIUMP " vec2 one_pole = onePoleResponse(g);\n"
466 " " MEDIUMP " vec2 all_pass = vec2(1.0, 0.0) - 2.0 * one_pole;\n"
467 " " MEDIUMP " vec2 half_peak = complexMultiply(all_pass, all_pass);\n"
468 " " MEDIUMP " vec2 peak1 = complexMultiply(half_peak, half_peak);\n"
469 " " MEDIUMP " vec2 peak3 = complexMultiply(peak1, peak1);\n"
470 " " MEDIUMP " vec2 peak5 = complexMultiply(peak3, peak1);\n"
471 " " MEDIUMP " vec2 chain = stage0 * peak1 + stage1 * peak3 + stage2 * peak5;\n"
472 " " MEDIUMP " float invert_mult = 1.0 - 2.0 * db24;\n"
473 " " MEDIUMP " vec2 feedback_chain = complexMultiply(chain, onePoleResponse(0.05 * g));\n"
474 " feedback_chain = complexMultiply(feedback_chain, vec2(1.0, 0.0) - onePoleResponse(20.0 * g));\n"
475 " " MEDIUMP " vec2 denominator = vec2(1.0, 0.0) - invert_mult * resonance * feedback_chain;\n"
476 " " MEDIUMP " vec2 phase_response = complexDivide(chain, denominator);\n"
477 " " MEDIUMP " vec2 response = vec2(0.5, 0.0) + 0.5 * invert_mult * phase_response;"
478 " response = mix * response + vec2(1.0 - mix, 0.0);\n"
479 " response_out = getYForResponse(response);\n"
480 "}\n";
481
482 const char* kEqFilterResponseVertexShader =
483 "in " MEDIUMP " float position;\n"
484 "out " MEDIUMP " float response_out;\n"
485 "uniform " MEDIUMP " vec3 midi_cutoff;\n"
486 "uniform " MEDIUMP " vec3 resonance;\n"
487 "uniform " MEDIUMP " vec3 low_amount;\n"
488 "uniform " MEDIUMP " vec3 band_amount;\n"
489 "uniform " MEDIUMP " vec3 high_amount;\n"
490 "const " MEDIUMP " float kMinMidiNote = 8.0;\n"
491 "const " MEDIUMP " float kSampleRate = 100000.0;\n"
492 "const " MEDIUMP " float kPi = 3.14159265359;\n"
493 "const " MEDIUMP " float kMaxMidiNote = 136.0;\n"
494 "const " MEDIUMP " float kMidi0Frequency = 8.1757989156;\n"
495 "const " MEDIUMP " float kMinDb = -1.0;\n"
496 "const " MEDIUMP " float kMaxDb = 1.0;\n"
498 "\n"
499 "void main() {\n"
500 " " MEDIUMP " float g0 = getCutoffRatio(position, midi_cutoff[0]);\n"
501 " " MEDIUMP " vec2 g0_sqr = vec2(g0 * g0, 0.0);\n"
502 " " MEDIUMP " vec2 denominator0 = g0_sqr + vec2(0.0, g0 * resonance[0]) + vec2(-1.0, 0.0);\n"
503 " " MEDIUMP " vec2 numerator0 = -low_amount[0] * vec2(1.0, 0.0) + band_amount[0] * vec2(0.0, g0) + high_amount[0] * g0_sqr;\n"
504 " " MEDIUMP " float g1 = getCutoffRatio(position, midi_cutoff[1]);\n"
505 " " MEDIUMP " vec2 g1_sqr = vec2(g1 * g1, 0.0);\n"
506 " " MEDIUMP " vec2 denominator1 = g1_sqr + vec2(0.0, g1 * resonance[1]) + vec2(-1.0, 0.0);\n"
507 " " MEDIUMP " vec2 numerator1 = -low_amount[1] * vec2(1.0, 0.0) + band_amount[1] * vec2(0.0, g1) + high_amount[1] * g1_sqr;\n"
508 " " MEDIUMP " float g2 = getCutoffRatio(position, midi_cutoff[2]);\n"
509 " " MEDIUMP " vec2 g2_sqr = vec2(g2 * g2, 0.0);\n"
510 " " MEDIUMP " vec2 denominator2 = g2_sqr + vec2(0.0, g2 * resonance[2]) + vec2(-1.0, 0.0);\n"
511 " " MEDIUMP " vec2 numerator2 = -low_amount[2] * vec2(1.0, 0.0) + band_amount[2] * vec2(0.0, g2) + high_amount[2] * g2_sqr;\n"
512 " " MEDIUMP " vec2 numerator = complexMultiply(numerator0, complexMultiply(numerator1, numerator2));\n"
513 " " MEDIUMP " vec2 denominator = complexMultiply(denominator0, complexMultiply(denominator1, denominator2));\n"
514 " " MEDIUMP " vec2 response = complexDivide(numerator, denominator);\n"
515 " response_out = getYForResponse(response);\n"
516 "}\n";
517
518 const char* kColorFragmentShader =
519 "uniform " MEDIUMP " vec4 color;\n"
520 "void main() {\n"
521 " gl_FragColor = color;\n"
522 "}\n";
523
524 const char* kFadeSquareFragmentShader =
525 "uniform " MEDIUMP " vec4 color;\n"
526 "varying " MEDIUMP " vec2 dimensions_out;\n"
527 "varying " MEDIUMP " vec2 coordinates_out;\n"
528 "varying " MEDIUMP " vec4 shader_values_out;\n"
529 "void main() {\n"
530 " float alpha1 = clamp((dimensions_out.x - abs(coordinates_out.x) * dimensions_out.x) * 0.5, 0.0, 1.0);\n"
531 " float alpha2 = clamp((dimensions_out.y - abs(coordinates_out.y) * dimensions_out.y) * 0.5, 0.0, 1.0);\n"
532 " gl_FragColor = color;\n"
533 " gl_FragColor.a = color.a * alpha1 * alpha2 * shader_values_out.x;\n"
534 "}\n";
535
536 const char* kCircleFragmentShader =
537 "uniform " MEDIUMP " vec4 color;\n"
538 "varying " MEDIUMP " vec2 dimensions_out;\n"
539 "varying " MEDIUMP " vec2 coordinates_out;\n"
540 "void main() {\n"
541 " float delta_center = length(coordinates_out) * 0.5 * dimensions_out.x;\n"
542 " float alpha = clamp(dimensions_out.x * 0.5 - delta_center, 0.0, 1.0);\n"
543 " gl_FragColor = color;\n"
544 " gl_FragColor.a = color.a * alpha;\n"
545 "}\n";
546
547 const char* kRingFragmentShader =
548 "uniform " MEDIUMP " vec4 color;\n"
549 "uniform " MEDIUMP " vec4 alt_color;\n"
550 "varying " MEDIUMP " vec2 dimensions_out;\n"
551 "uniform " MEDIUMP " float thickness;\n"
552 "varying " MEDIUMP " vec2 coordinates_out;\n"
553 "void main() {\n"
554 " float full_radius = 0.5 * dimensions_out.x;\n"
555 " float delta_center = length(coordinates_out) * full_radius;\n"
556 " float alpha_out = clamp(full_radius - delta_center, 0.0, 1.0);\n"
557 " float alpha_in = clamp(delta_center - full_radius + thickness + 1.0, 0.0, 1.0);\n"
558 " gl_FragColor = color * alpha_in + (1.0 - alpha_in) * alt_color;\n"
559 " gl_FragColor.a = gl_FragColor.a * alpha_out;\n"
560 "}\n";
561
562 const char* kRoundedCornerFragmentShader =
563 "uniform " MEDIUMP " vec4 color;\n"
564 "varying " MEDIUMP " vec2 dimensions_out;\n"
565 "varying " MEDIUMP " vec2 coordinates_out;\n"
566 "void main() {\n"
567 " float delta_center = length(coordinates_out * dimensions_out);\n"
568 " float alpha = clamp(delta_center - dimensions_out.x + 0.5, 0.0, 1.0);\n"
569 " gl_FragColor = color;\n"
570 " gl_FragColor.a = color.a * alpha;\n"
571 "}\n";
572
573 const char* kRoundedRectangleFragmentShader =
574 "uniform " MEDIUMP " vec4 color;\n"
575 "varying " MEDIUMP " vec2 dimensions_out;\n"
576 "varying " MEDIUMP " vec2 coordinates_out;\n"
577 "uniform " MEDIUMP " float rounding;\n"
578 "void main() {\n"
579 " vec2 center_offset = abs(coordinates_out) * dimensions_out - dimensions_out;\n"
580 " float delta_center = length(max(center_offset + vec2(rounding, rounding), vec2(0.0, 0.0)));\n"
581 " float alpha = clamp((rounding - delta_center) * 0.5 + 0.5, 0.0, 1.0);\n"
582 " gl_FragColor = color;\n"
583 " gl_FragColor.a = color.a * alpha;\n"
584 "}\n";
585
586 const char* kDiamondFragmentShader =
587 "uniform " MEDIUMP " vec4 color;\n"
588 "uniform " MEDIUMP " vec4 alt_color;\n"
589 "varying " MEDIUMP " vec2 dimensions_out;\n"
590 "uniform " MEDIUMP " float thickness;\n"
591 "varying " MEDIUMP " vec2 coordinates_out;\n"
592 "void main() {\n"
593 " float full_radius = 0.5 * dimensions_out.x;\n"
594 " float delta_center = (abs(coordinates_out.x) + abs(coordinates_out.y)) * full_radius;\n"
595 " float alpha_out = clamp(full_radius - delta_center, 0.0, 1.0);\n"
596 " float alpha_in = clamp(delta_center - full_radius + thickness + 1.0, 0.0, 1.0);\n"
597 " gl_FragColor = color * alpha_in + (1.0 - alpha_in) * alt_color;\n"
598 " gl_FragColor.a = gl_FragColor.a * alpha_out;\n"
599 "}\n";
600
601 const char* kRoundedRectangleBorderFragmentShader =
602 "uniform " MEDIUMP " vec4 color;\n"
603 "varying " MEDIUMP " vec2 dimensions_out;\n"
604 "varying " MEDIUMP " vec2 coordinates_out;\n"
605 "uniform " MEDIUMP " float rounding;\n"
606 "uniform " MEDIUMP " float thickness;\n"
607 "uniform " MEDIUMP " float alpha_mult;\n"
608 "void main() {\n"
609 " vec2 center_offset = abs(coordinates_out) * dimensions_out - dimensions_out;\n"
610 " float delta_center = length(max(center_offset + vec2(rounding, rounding), vec2(0.0, 0.0)));\n"
611 " float inside_rounding = rounding + 2.0 * thickness;\n"
612 " float delta_center_inside = length(max(center_offset + vec2(inside_rounding, inside_rounding), vec2(0.0, 0.0)));\n"
613 " float border_delta = (rounding - delta_center) * 0.5;\n"
614 " float inside_border_delta = (rounding - delta_center_inside) * 0.5;\n"
615 " float alpha = clamp(border_delta + 0.5, 0.0, 1.0) * clamp(-inside_border_delta + 0.5, 0.0, 1.0);\n"
616 " gl_FragColor = color;\n"
617 " gl_FragColor.a = color.a * alpha_mult * alpha;\n"
618 "}\n";
619
620 const char* kRotarySliderFragmentShader =
621 "uniform " MEDIUMP " vec4 color;\n"
622 "uniform " MEDIUMP " vec4 alt_color;\n"
623 "uniform " MEDIUMP " vec4 thumb_color;\n"
624 "varying " MEDIUMP " vec2 dimensions_out;\n"
625 "uniform " MEDIUMP " float thickness;\n"
626 "uniform " MEDIUMP " float thumb_amount;\n"
627 "uniform " MEDIUMP " float start_pos;\n"
628 "uniform " MEDIUMP " float max_arc;\n"
629 "varying " MEDIUMP " vec4 shader_values_out;\n"
630 "varying " MEDIUMP " vec2 coordinates_out;\n"
631 "void main() {\n"
632 " " MEDIUMP " float rads = atan(coordinates_out.x, coordinates_out.y);\n"
633 " float full_radius = 0.5 * dimensions_out.x;\n"
634 " float delta_center = length(coordinates_out) * full_radius;\n"
635 " float center_arc = full_radius - thickness * 0.5 - 0.5;\n"
636 " float delta_arc = delta_center - center_arc;\n"
637 " float distance_arc = abs(delta_arc);\n"
638 " float dist_curve_left = max(center_arc * (rads - max_arc), 0.0);\n"
639 " float dist_curve = max(center_arc * (-rads - max_arc), dist_curve_left);\n"
640 " float alpha = clamp(thickness * 0.5 - length(vec2(distance_arc, dist_curve)) + 0.5, 0.0, 1.0);\n"
641 " float delta_rads = rads - shader_values_out.x;\n"
642 " float color_step1 = step(0.0, delta_rads);\n"
643 " float color_step2 = step(0.0, start_pos - rads);\n"
644 " float color_step = abs(color_step2 - color_step1);\n"
645 " gl_FragColor = alt_color * color_step + color * (1.0 - color_step);\n"
646 " gl_FragColor.a = gl_FragColor.a * alpha;\n"
647 " float thumb_length = full_radius * thumb_amount;\n"
648 " float thumb_x = sin(delta_rads) * delta_center;\n"
649 " float thumb_y = cos(delta_rads) * delta_center - center_arc;\n"
650 " float adjusted_thumb_y = min(thumb_y + thumb_length, 0.0);\n"
651 " float outside_arc_step = step(0.0, thumb_y);\n"
652 " float thumb_y_distance = thumb_y * outside_arc_step + adjusted_thumb_y * (1.0 - outside_arc_step);\n"
653 " float thumb_distance = length(vec2(thumb_x, thumb_y_distance));\n"
654 " float thumb_alpha = clamp(thickness * 0.5 - thumb_distance + 0.5, 0.0, 1.0);\n"
655 " gl_FragColor = gl_FragColor * (1.0 - thumb_alpha) + thumb_color * thumb_alpha;\n"
656 "}\n";
657
658 const char* kRotaryModulationFragmentShader =
659 "varying " MEDIUMP " vec2 coordinates_out;\n"
660 "varying " MEDIUMP " vec2 dimensions_out;\n"
661 "varying " MEDIUMP " vec4 shader_values_out;\n"
662 "uniform " MEDIUMP " float thickness;\n"
663 "uniform " MEDIUMP " vec4 color;\n"
664 "uniform " MEDIUMP " vec4 alt_color;\n"
665 "uniform " MEDIUMP " vec4 mod_color;\n"
666 "uniform " MEDIUMP " float alpha_mult;\n"
667 "uniform " MEDIUMP " float start_pos;\n"
668 "const " MEDIUMP " float kPi = 3.14159265359;\n" \
669 "\n"
670 "void main() {\n"
671 " " MEDIUMP " float full_radius = dimensions_out.x * 0.5;\n"
672 " " MEDIUMP " float dist = length(coordinates_out) * full_radius;\n"
673 " " MEDIUMP " float inner_radius = full_radius - thickness;\n"
674 " " MEDIUMP " float dist_outer_amp = clamp((full_radius - dist) * 0.5 + 0.5, 0.0, 1.0);\n"
675 " " MEDIUMP " float dist_amp = dist_outer_amp * clamp((dist - inner_radius) * 0.5 + 0.5, 0.0, 1.0);\n"
676 " " MEDIUMP " float rads = mod(atan(coordinates_out.x, coordinates_out.y) + kPi + start_pos, 2.0 * kPi) - kPi;\n"
677 " " MEDIUMP " float rads_amp_low = clamp(full_radius * 0.5 * (rads - shader_values_out.x) + 1.0, 0.0, 1.0);\n"
678 " " MEDIUMP " float rads_amp_high = clamp(full_radius * 0.5 * (shader_values_out.y - rads) + 1.0, 0.0, 1.0);\n"
679 " " MEDIUMP " float rads_amp_low_stereo = clamp(full_radius * 0.5 * (rads - shader_values_out.z) + 0.5, 0.0, 1.0);\n"
680 " " MEDIUMP " float rads_amp_high_stereo = clamp(full_radius * 0.5 * (shader_values_out.a - rads) + 0.5, 0.0, 1.0);\n"
681 " " MEDIUMP " float alpha = rads_amp_low * rads_amp_high;\n"
682 " " MEDIUMP " float alpha_stereo = rads_amp_low_stereo * rads_amp_high_stereo;\n"
683 " " MEDIUMP " float alpha_center = min(alpha, alpha_stereo);\n"
684 " " MEDIUMP " vec4 color_left = (alpha - alpha_center) * color;\n"
685 " " MEDIUMP " vec4 color_right = (alpha_stereo - alpha_center) * alt_color;\n"
686 " " MEDIUMP " vec4 color_center = alpha_center * mod_color;\n"
687 " " MEDIUMP " vec4 out_color = color * (1.0 - alpha_stereo) + alt_color * alpha_stereo;\n"
688 " out_color = out_color * (1.0 - alpha_center) + color_center * alpha_center;\n"
689 " out_color.a = max(alpha, alpha_stereo) * alpha_mult * dist_amp;\n"
690 " gl_FragColor = out_color;\n"
691 "}\n";
692
693 const char* kHorizontalSliderFragmentShader =
694 "uniform " MEDIUMP " vec4 color;\n"
695 "uniform " MEDIUMP " vec4 alt_color;\n"
696 "uniform " MEDIUMP " vec4 thumb_color;\n"
697 "varying " MEDIUMP " vec2 dimensions_out;\n"
698 "uniform " MEDIUMP " float thickness;\n"
699 "uniform " MEDIUMP " float thumb_amount;\n"
700 "uniform " MEDIUMP " float start_pos;\n"
701 "uniform " MEDIUMP " float rounding;\n"
702 "varying " MEDIUMP " vec4 shader_values_out;\n"
703 "varying " MEDIUMP " vec2 coordinates_out;\n"
704 "void main() {\n"
705 " vec2 position = coordinates_out * dimensions_out;\n"
706 " vec2 center_offset = abs(position) - vec2(dimensions_out.x, thickness);\n"
707 " float delta_center = length(max(center_offset + vec2(rounding, rounding), vec2(0.0, 0.0)));\n"
708 " float alpha = clamp((rounding - delta_center) * 0.5 + 0.5, 0.0, 1.0);\n"
709 " float adjusted_value = shader_values_out.x * 2.0 - 1.0;\n"
710 " float delta_pos = coordinates_out.x - adjusted_value;\n"
711 " float color_step1 = step(0.001, delta_pos);\n"
712 " float color_step2 = step(0.001, start_pos - coordinates_out.x);\n"
713 " float color_step = abs(color_step2 - color_step1);\n"
714 " gl_FragColor = alt_color * color_step + color * (1.0 - color_step);\n"
715 " gl_FragColor.a = gl_FragColor.a * alpha;\n"
716 " vec2 thumb_center_offset = abs(position - vec2(adjusted_value * dimensions_out.x, 0.0)) - vec2(thumb_amount, thickness);\n"
717 " float thumb_delta_center = length(max(thumb_center_offset + vec2(rounding, rounding), vec2(0.0, 0.0)));\n"
718 " float thumb_alpha = clamp((rounding - thumb_delta_center) * 0.5 + 0.5, 0.0, 1.0) * alpha;\n"
719 " gl_FragColor = gl_FragColor * (1.0 - thumb_alpha) + thumb_color * thumb_alpha;\n"
720 "}\n";
721
722 const char* kVerticalSliderFragmentShader =
723 "uniform " MEDIUMP " vec4 color;\n"
724 "uniform " MEDIUMP " vec4 alt_color;\n"
725 "uniform " MEDIUMP " vec4 thumb_color;\n"
726 "varying " MEDIUMP " vec2 dimensions_out;\n"
727 "uniform " MEDIUMP " float thickness;\n"
728 "uniform " MEDIUMP " float thumb_amount;\n"
729 "uniform " MEDIUMP " float start_pos;\n"
730 "uniform " MEDIUMP " float rounding;\n"
731 "varying " MEDIUMP " vec4 shader_values_out;\n"
732 "varying " MEDIUMP " vec2 coordinates_out;\n"
733 "void main() {\n"
734 " vec2 position = coordinates_out * dimensions_out;\n"
735 " vec2 center_offset = abs(position) - vec2(thickness, dimensions_out.y);\n"
736 " float delta_center = length(max(center_offset + vec2(rounding, rounding), vec2(0.0, 0.0)));\n"
737 " float alpha = clamp((rounding - delta_center) * 0.5 + 0.5, 0.0, 1.0);\n"
738 " float adjusted_value = shader_values_out.x * 2.0 - 1.0;\n"
739 " float delta_pos = coordinates_out.y - adjusted_value;\n"
740 " float color_step1 = step(0.001, delta_pos);\n"
741 " float color_step2 = step(0.001, start_pos - coordinates_out.y);\n"
742 " float color_step = abs(color_step2 - color_step1);\n"
743 " gl_FragColor = color * color_step + alt_color * (1.0 - color_step);\n"
744 " gl_FragColor.a = gl_FragColor.a * alpha;\n"
745 " vec2 thumb_center_offset = abs(position - vec2(0.0, adjusted_value * dimensions_out.y)) - vec2(thickness, thumb_amount);\n"
746 " float thumb_delta_center = length(max(thumb_center_offset + vec2(rounding, rounding), vec2(0.0, 0.0)));\n"
747 " float thumb_alpha = clamp((rounding - thumb_delta_center) * 0.5 + 0.5, 0.0, 1.0) * alpha;\n"
748 " gl_FragColor = gl_FragColor * (1.0 - thumb_alpha) + thumb_color * thumb_alpha;\n"
749 "}\n";
750
751 const char* kLinearModulationFragmentShader =
752 "varying " MEDIUMP " vec2 coordinates_out;\n"
753 "varying " MEDIUMP " vec4 shader_values_out;\n"
754 "uniform " MEDIUMP " vec4 color;\n"
755 "uniform " MEDIUMP " vec4 alt_color;\n"
756 "uniform " MEDIUMP " vec4 mod_color;\n"
757 "\n"
758 "void main() {\n"
759 " " MEDIUMP " float position = coordinates_out.x * 0.5 + 0.5;\n"
760 " " MEDIUMP " float dist1 = clamp(200.0 * (position - shader_values_out.x), 0.0, 1.0);\n"
761 " " MEDIUMP " float dist2 = clamp(200.0 * (shader_values_out.y - position), 0.0, 1.0);\n"
762 " " MEDIUMP " float stereo_dist1 = clamp(200.0 * (position - shader_values_out.z), 0.0, 1.0);\n"
763 " " MEDIUMP " float stereo_dist2 = clamp(200.0 * (shader_values_out.a - position), 0.0, 1.0);\n"
764 " " MEDIUMP " float alpha = dist1 * dist2;\n"
765 " " MEDIUMP " float alpha_stereo = stereo_dist1 * stereo_dist2;\n"
766 " " MEDIUMP " float alpha_center = min(alpha, alpha_stereo);\n"
767 " " MEDIUMP " vec4 color_left = (alpha - alpha_center) * color;\n"
768 " " MEDIUMP " vec4 color_right = (alpha_stereo - alpha_center) * alt_color;\n"
769 " " MEDIUMP " vec4 color_center = alpha_center * mod_color;\n"
770 " " MEDIUMP " vec4 color = color_left + color_right + color_center;\n"
771 " color.a = max(alpha, alpha_stereo);\n"
772 " gl_FragColor = color;\n"
773 "}\n";
774
775 const char* kModulationKnobFragmentShader =
776 "uniform " MEDIUMP " vec4 color;\n"
777 "uniform " MEDIUMP " vec4 alt_color;\n"
778 "uniform " MEDIUMP " vec4 mod_color;\n"
779 "uniform " MEDIUMP " vec4 background_color;\n"
780 "uniform " MEDIUMP " vec4 thumb_color;\n"
781 "varying " MEDIUMP " vec2 dimensions_out;\n"
782 "uniform " MEDIUMP " float thickness;\n"
783 "uniform " MEDIUMP " float alpha_mult;\n"
784 "varying " MEDIUMP " vec4 shader_values_out;\n"
785 "varying " MEDIUMP " vec2 coordinates_out;\n"
786 "void main() {\n"
787 " float rads = atan(coordinates_out.x, -coordinates_out.y);\n"
788 " float full_radius = 0.5 * dimensions_out.x;\n"
789 " float delta_center = length(coordinates_out) * full_radius;\n"
790 " float circle_alpha = clamp(full_radius - delta_center, 0.0, 1.0);\n"
791 " float delta_rads = rads - shader_values_out.x;\n"
792 " float color_amount = clamp(delta_rads * max(delta_center, 1.0) * 1.6, 0.0, 1.0);\n"
793 " gl_FragColor = alt_color * color_amount + color * (1.0 - color_amount);\n"
794 " gl_FragColor.a = gl_FragColor.a * circle_alpha;\n"
795 " float center_arc = full_radius - thickness * 0.5 - 0.5;\n"
796 " float delta_arc = delta_center - center_arc;\n"
797 " float distance_arc = abs(delta_arc);\n"
798 " float thumb_alpha = clamp(thickness * 0.5 - distance_arc + 0.5, 0.0, 1.0);\n"
799 " gl_FragColor = gl_FragColor * (1.0 - thumb_alpha) + thumb_color * thumb_alpha;\n"
800 " float mod_alpha1 = clamp(full_radius * 0.48 - delta_center, 0.0, 1.0) * mod_color.a;\n"
801 " float mod_alpha2 = clamp(full_radius * 0.35 - delta_center, 0.0, 1.0) * mod_color.a;\n"
802 " gl_FragColor = gl_FragColor * (1.0 - mod_alpha1) + background_color * mod_alpha1;\n"
803 " gl_FragColor = gl_FragColor * (1.0 - mod_alpha2) + mod_color * mod_alpha2;\n"
804 " gl_FragColor.a = gl_FragColor.a * alpha_mult;\n"
805 "}\n";
806
807 const char* kFilterFragmentShader =
808 "uniform " MEDIUMP " vec4 color_from;\n"
809 "uniform " MEDIUMP " vec4 color_to;\n"
810 "uniform " MEDIUMP " float line_width;\n"
811 "uniform " MEDIUMP " float boost;\n"
812 "varying " MEDIUMP " float depth_out;\n"
813 "varying " MEDIUMP " float distance;\n"
814 "void main() {\n"
815 " " MEDIUMP " vec4 color = color_to * distance + color_from * (1.0 - distance);\n"
816 " " MEDIUMP " float dist_from_edge = min(depth_out, 1.0 - depth_out);\n"
817 " " MEDIUMP " float mult = 1.0 + boost * max(dist_from_edge - 2.0 / line_width, 0.0);\n"
818 " " MEDIUMP " vec4 result = mult * color;\n"
819 " " MEDIUMP " float scale = line_width * dist_from_edge;\n"
820 " result.a = scale / 2.0;\n"
821 " gl_FragColor = result;\n"
822 "}\n";
823
824 const char* kLineFragmentShader =
825 "uniform " MEDIUMP " vec4 color;\n"
826 "uniform " MEDIUMP " float line_width;\n"
827 "uniform " MEDIUMP " float boost;\n"
828 "varying " MEDIUMP " float depth_out;\n"
829 "void main() {\n"
830 " " MEDIUMP " float dist_from_edge = min(depth_out, 1.0 - depth_out);\n"
831 " " MEDIUMP " float mult = 1.0 + boost * max(dist_from_edge - 2.0 / line_width, 0.0);\n"
832 " " MEDIUMP " vec4 result = mult * color;\n"
833 " " MEDIUMP " float scale = line_width * dist_from_edge;\n"
834 " result.a = result.a * scale / 2.0;\n"
835 " gl_FragColor = result;\n"
836 "}\n";
837
838 const char* kFillFragmentShader =
839 "uniform " MEDIUMP " vec4 color_from;\n"
840 "uniform " MEDIUMP " vec4 color_to;\n"
841 "varying " MEDIUMP " float boost;\n"
842 "varying " MEDIUMP " float distance;\n"
843 "void main() {\n"
844 " " MEDIUMP " float delta = abs(distance);\n"
845 " " MEDIUMP " vec4 base_color = color_to * delta + color_from * (1.0 - delta);\n"
846 " gl_FragColor = base_color;\n"
847 " gl_FragColor.a = (boost + 1.0) * base_color.a;\n"
848 "}\n";
849
850 const char* kLineVertexShader =
851 "attribute " MEDIUMP " vec4 position;\n"
852 "uniform " MEDIUMP " vec2 scale;\n"
853 "out " MEDIUMP " float depth_out;\n"
854 "\n"
855 "void main() {\n"
856 " depth_out = position.z;\n"
857 " gl_Position = position;\n"
858 " gl_Position.x = position.x * scale.x;\n"
859 " gl_Position.y = position.y * scale.y;\n"
860 " gl_Position.z = 0.0;\n"
861 " gl_Position.w = 1.0;\n"
862 "}\n";
863
864 const char* kFillVertexShader =
865 "attribute " MEDIUMP " vec4 position;\n"
866 "uniform " MEDIUMP " vec2 scale;\n"
867 "uniform " MEDIUMP " float center_position;\n"
868 "uniform " MEDIUMP " float boost_amount;\n"
869 "out " MEDIUMP " float distance;\n"
870 "out " MEDIUMP " float boost;\n"
871 "\n"
872 "void main() {\n"
873 " distance = (position.y - center_position) / (1.0 - center_position);\n"
874 " boost = boost_amount * position.z;\n"
875 " gl_Position = position;\n"
876 " gl_Position.x = gl_Position.x * scale.x;\n"
877 " gl_Position.y = gl_Position.y * scale.y;\n"
878 " gl_Position.z = 0.0;\n"
879 " gl_Position.a = 1.0;\n"
880 "}\n";
881
882 const char* kBarFragmentShader =
883 "uniform " MEDIUMP " vec4 color;\n"
884 "varying " MEDIUMP " vec2 corner_out;\n"
885 "varying " MEDIUMP " vec2 size;\n"
886 "void main() {\n"
887 " " MEDIUMP " float alpha_x = min(corner_out.x * size.x, (1.0 - corner_out.x) * size.x);\n"
888 " " MEDIUMP " float alpha_y = min(corner_out.y * size.y, (1.0 - corner_out.y) * size.y);\n"
889 " gl_FragColor = color;\n"
890 " gl_FragColor.a = gl_FragColor.a * min(1.0, min(alpha_x, alpha_y));\n"
891 "}\n";
892
893 const char* kBarHorizontalVertexShader =
894 "attribute " MEDIUMP " vec4 position;\n"
895 "attribute " MEDIUMP " vec2 corner;\n"
896 "uniform " MEDIUMP " float offset;\n"
897 "uniform " MEDIUMP " float scale;\n"
898 "uniform " MEDIUMP " float width_percent;\n"
899 "uniform " MEDIUMP " vec2 dimensions;\n"
900 "out " MEDIUMP " vec2 corner_out;\n"
901 "out " MEDIUMP " vec2 size;\n"
902 "void main()\n"
903 "{\n"
904 " gl_Position = position;\n"
905 " size.x = position.z * dimensions.x / 2.0;\n"
906 " size.y = width_percent * dimensions.y / 2.0;\n"
907 " gl_Position.x = scale * (position.x + 1.0) - 1.0;\n"
908 " corner_out = corner;\n"
909 " gl_Position = gl_Position + vec4(0.0, offset - width_percent * corner.y, 0.0, 0.0);\n"
910 " gl_Position.z = 0.0;\n"
911 " gl_Position.w = 1.0;\n"
912 "}\n";
913
914 const char* kBarVerticalVertexShader =
915 "attribute " MEDIUMP " vec4 position;\n"
916 "attribute " MEDIUMP " vec2 corner;\n"
917 "uniform " MEDIUMP " float offset;\n"
918 "uniform " MEDIUMP " float scale;\n"
919 "uniform " MEDIUMP " float width_percent;\n"
920 "uniform " MEDIUMP " vec2 dimensions;\n"
921 "out " MEDIUMP " vec2 corner_out;\n"
922 "out " MEDIUMP " vec2 size;\n"
923 "void main()\n"
924 "{\n"
925 " gl_Position = position;\n"
926 " size.x = width_percent * dimensions.x / 2.0;\n"
927 " size.y = position.z * dimensions.y / 2.0;\n"
928 " gl_Position.x = scale * (position.x + 1.0) - 1.0;\n"
929 " corner_out = corner;\n"
930 " gl_Position = gl_Position + vec4(offset + width_percent * corner.x, 0.0, 0.0, 0.0);\n"
931 " gl_Position.z = 0.0;\n"
932 " gl_Position.w = 1.0;\n"
933 "}\n";
934
935 inline String translateFragmentShader(const String& code) {
936 #if OPENGL_ES
937 return String("#version 300 es\n") + "out mediump vec4 fragColor;\n" +
938 code.replace("varying", "in").replace("texture2D", "texture").replace("gl_FragColor", "fragColor");
939 #else
940 return OpenGLHelpers::translateFragmentShaderToV3(code);
941 #endif
942 }
943
944 inline String translateVertexShader(const String& code) {
945 #if OPENGL_ES
946 return String("#version 300 es\n") + code.replace("attribute", "in").replace("varying", "out");
947 #else
948 return OpenGLHelpers::translateVertexShaderToV3(code);
949 #endif
950 }
951} // namespace
952
953OpenGLShaderProgram* Shaders::getShaderProgram(VertexShader vertex_shader, FragmentShader fragment_shader,
954 const GLchar** varyings) {
955 int shader_program_index = vertex_shader * kNumFragmentShaders + fragment_shader;
956 if (shader_programs_.count(shader_program_index))
957 return shader_programs_.at(shader_program_index).get();
958
959 shader_programs_[shader_program_index] = std::make_unique<OpenGLShaderProgram>(*open_gl_context_);
960 OpenGLShaderProgram* result = shader_programs_[shader_program_index].get();
961 GLuint program_id = result->getProgramID();
962 open_gl_context_->extensions.glAttachShader(program_id, getVertexShaderId(vertex_shader));
963 open_gl_context_->extensions.glAttachShader(program_id, getFragmentShaderId(fragment_shader));
964 if (varyings)
965 open_gl_context_->extensions.glTransformFeedbackVaryings(program_id, 1, varyings, GL_INTERLEAVED_ATTRIBS);
966
967 result->link();
968 return result;
969}
970
971const char* Shaders::getVertexShader(VertexShader shader) {
972 switch (shader) {
973 case kImageVertex:
974 return kImageVertexShader;
976 return kPassthroughVertexShader;
977 case kScaleVertex:
978 return kScaleVertexShader;
980 return kRotaryModulationVertexShader;
982 return kLinearModulationVertexShader;
983 case kGainMeterVertex:
984 return kGainMeterVertexShader;
986 return kAnalogFilterResponseVertexShader;
988 return kCombFilterResponseVertexShader;
990 return kPositiveFlangeFilterResponseVertexShader;
992 return kNegativeFlangeFilterResponseVertexShader;
994 return kDigitalFilterResponseVertexShader;
996 return kDiodeFilterResponseVertexShader;
998 return kDirtyFilterResponseVertexShader;
1000 return kFormantFilterResponseVertexShader;
1002 return kLadderFilterResponseVertexShader;
1004 return kPhaserFilterResponseVertexShader;
1006 return kEqFilterResponseVertexShader;
1007 case kLineVertex:
1008 return kLineVertexShader;
1009 case kFillVertex:
1010 return kFillVertexShader;
1012 return kBarHorizontalVertexShader;
1013 case kBarVerticalVertex:
1014 return kBarVerticalVertexShader;
1015 default:
1016 VITAL_ASSERT(false);
1017 return nullptr;
1018 }
1019}
1020
1021const char* Shaders::getFragmentShader(FragmentShader shader) {
1022 switch (shader) {
1023 case kImageFragment:
1024 return kImageFragmentShader;
1026 return kTintedImageFragmentShader;
1027 case kGainMeterFragment:
1028 return kGainMeterFragmentShader;
1030 return kFilterFragmentShader;
1031 case kLineFragment:
1032 return kLineFragmentShader;
1033 case kFillFragment:
1034 return kFillFragmentShader;
1035 case kBarFragment:
1036 return kBarFragmentShader;
1037 case kColorFragment:
1038 return kColorFragmentShader;
1040 return kFadeSquareFragmentShader;
1041 case kCircleFragment:
1042 return kCircleFragmentShader;
1043 case kRingFragment:
1044 return kRingFragmentShader;
1045 case kDiamondFragment:
1046 return kDiamondFragmentShader;
1048 return kRoundedCornerFragmentShader;
1050 return kRoundedRectangleFragmentShader;
1052 return kRoundedRectangleBorderFragmentShader;
1054 return kRotarySliderFragmentShader;
1056 return kRotaryModulationFragmentShader;
1058 return kHorizontalSliderFragmentShader;
1060 return kVerticalSliderFragmentShader;
1062 return kLinearModulationFragmentShader;
1064 return kModulationKnobFragmentShader;
1065 default:
1066 VITAL_ASSERT(false);
1067 return nullptr;
1068 }
1069}
1070
1071bool Shaders::checkShaderCorrect(OpenGLExtensionFunctions& extensions, GLuint shader_id) const {
1072 GLint status = GL_FALSE;
1073 extensions.glGetShaderiv(shader_id, GL_COMPILE_STATUS, &status);
1074
1075 if (status != GL_FALSE)
1076 return true;
1077
1078 GLchar info[16384];
1079 GLsizei info_length = 0;
1080 extensions.glGetShaderInfoLog(shader_id, sizeof(info), &info_length, info);
1081 DBG(String(info, (size_t)info_length));
1082 return false;
1083}
1084
1085GLuint Shaders::createVertexShader(OpenGLExtensionFunctions& extensions, VertexShader shader) const {
1086 GLuint shader_id = extensions.glCreateShader(GL_VERTEX_SHADER);
1087 String code_string = translateVertexShader(getVertexShader(shader));
1088 const GLchar* code = code_string.toRawUTF8();
1089 extensions.glShaderSource(shader_id, 1, &code, nullptr);
1090 extensions.glCompileShader(shader_id);
1091
1092 VITAL_ASSERT(checkShaderCorrect(extensions, shader_id));
1093 return shader_id;
1094}
1095
1096GLuint Shaders::createFragmentShader(OpenGLExtensionFunctions& extensions, FragmentShader shader) const {
1097 GLuint shader_id = extensions.glCreateShader(GL_FRAGMENT_SHADER);
1098 String code_string = translateFragmentShader(getFragmentShader(shader));
1099 const GLchar* code = code_string.toRawUTF8();
1100 extensions.glShaderSource(shader_id, 1, &code, nullptr);
1101 extensions.glCompileShader(shader_id);
1102
1103 VITAL_ASSERT(checkShaderCorrect(extensions, shader_id));
1104 return shader_id;
1105}
1106
1107Shaders::Shaders(OpenGLContext& open_gl_context) : open_gl_context_(&open_gl_context),
1108 vertex_shader_ids_(), fragment_shader_ids_() { }
VertexShader
An enumeration of all available vertex shaders.
Definition shaders.h:27
@ kRotaryModulationVertex
Definition shaders.h:31
@ kDirtyFilterResponseVertex
Definition shaders.h:40
@ kImageVertex
Definition shaders.h:28
@ kBarVerticalVertex
Definition shaders.h:48
@ kDigitalFilterResponseVertex
Definition shaders.h:38
@ kDiodeFilterResponseVertex
Definition shaders.h:39
@ kAnalogFilterResponseVertex
Definition shaders.h:34
@ kFormantFilterResponseVertex
Definition shaders.h:41
@ kPhaserFilterResponseVertex
Definition shaders.h:43
@ kFillVertex
Definition shaders.h:46
@ kLineVertex
Definition shaders.h:45
@ kScaleVertex
Definition shaders.h:30
@ kGainMeterVertex
Definition shaders.h:33
@ kLadderFilterResponseVertex
Definition shaders.h:42
@ kEqFilterResponseVertex
Definition shaders.h:44
@ kPositiveFlangeFilterResponseVertex
Definition shaders.h:36
@ kBarHorizontalVertex
Definition shaders.h:47
@ kPassthroughVertex
Definition shaders.h:29
@ kCombFilterResponseVertex
Definition shaders.h:35
@ kLinearModulationVertex
Definition shaders.h:32
@ kNegativeFlangeFilterResponseVertex
Definition shaders.h:37
FragmentShader
An enumeration of all available fragment shaders.
Definition shaders.h:58
@ kHorizontalSliderFragment
Definition shaders.h:73
@ kLinearModulationFragment
Definition shaders.h:75
@ kFadeSquareFragment
Definition shaders.h:64
@ kNumFragmentShaders
Definition shaders.h:80
@ kRotarySliderFragment
Definition shaders.h:71
@ kRoundedCornerFragment
Definition shaders.h:68
@ kLineFragment
Definition shaders.h:77
@ kModulationKnobFragment
Definition shaders.h:76
@ kImageFragment
Definition shaders.h:59
@ kRotaryModulationFragment
Definition shaders.h:72
@ kRoundedRectangleBorderFragment
Definition shaders.h:70
@ kDiamondFragment
Definition shaders.h:67
@ kGainMeterFragment
Definition shaders.h:61
@ kVerticalSliderFragment
Definition shaders.h:74
@ kBarFragment
Definition shaders.h:79
@ kRoundedRectangleFragment
Definition shaders.h:69
@ kFilterResponseFragment
Definition shaders.h:62
@ kRingFragment
Definition shaders.h:66
@ kFillFragment
Definition shaders.h:78
@ kTintedImageFragment
Definition shaders.h:60
@ kColorFragment
Definition shaders.h:63
@ kCircleFragment
Definition shaders.h:65
GLuint getVertexShaderId(VertexShader shader)
Retrieves the OpenGL shader ID for a given vertex shader.
Definition shaders.h:94
GLuint getFragmentShaderId(FragmentShader shader)
Retrieves the OpenGL shader ID for a given fragment shader.
Definition shaders.h:105
Shaders(OpenGLContext &open_gl_context)
Constructs a Shaders object associated with an OpenGLContext.
Definition shaders.cpp:1107
OpenGLShaderProgram * getShaderProgram(VertexShader vertex_shader, FragmentShader fragment_shader, const GLchar **varyings=nullptr)
Retrieves or creates an OpenGLShaderProgram from a given vertex and fragment shader pair.
Definition shaders.cpp:953
#define VITAL_ASSERT(x)
Definition common.h:11
#define FILTER_RESPONSE_UNIFORMS
Definition shaders.cpp:18
#define FILTER_RESPONSE_CONSTANTS
Definition shaders.cpp:30
#define MEDIUMP
Definition shaders.cpp:14
#define RESPONSE_TOOLS
Definition shaders.cpp:38