revamped sound engine
[fishladder.git] / fishladder_resources.h
1 // FONTS
2 /*
3 vg_tex2d tex_ubuntu = { .path = "textures/ubuntu.qoi" };
4
5 static struct ui_sdf_char characters_Ubuntu[] = {
6 {62911, 23039, 64063, 27647, 9, 9, 18, 18, 7},
7 {3519, 23039, 4991, 33279, 7, 31, 23, 40, 9},
8 {50815, 23039, 52543, 29695, 7, 33, 27, 26, 13},
9 {22783, 12543, 25087, 22783, 7, 31, 36, 40, 21},
10 {19647, 0, 21695, 11775, 7, 34, 32, 46, 18},
11 {36095, 0, 38783, 10495, 7, 31, 42, 41, 27},
12 {41343, 0, 43775, 10495, 8, 31, 38, 41, 21},
13 {52543, 23039, 53887, 29695, 7, 33, 21, 26, 7},
14 {7551, 0, 9215, 12543, 6, 34, 26, 49, 10},
15 {9215, 0, 10879, 12543, 9, 34, 26, 49, 10},
16 {43135, 23039, 45119, 30975, 8, 31, 31, 31, 15},
17 {32703, 23039, 34815, 31743, 7, 26, 33, 34, 18},
18 {49343, 23039, 50815, 29951, 8, 12, 23, 27, 8},
19 {61247, 23039, 62911, 28415, 8, 20, 26, 21, 9},
20 {57599, 23039, 59071, 28671, 7, 13, 23, 22, 8},
21 {0, 0, 2047, 12543, 10, 34, 32, 49, 12},
22 {50623, 0, 52735, 10495, 7, 32, 33, 41, 18},
23 {1791, 23039, 3519, 33279, 6, 31, 27, 40, 18},
24 {61183, 0, 63231, 10495, 7, 32, 32, 41, 18},
25 {63231, 0, 65279, 10495, 7, 32, 32, 41, 18},
26 {38655, 12543, 40831, 22783, 8, 31, 34, 40, 18},
27 {0, 12543, 2047, 23039, 7, 31, 32, 41, 18},
28 {55807, 12543, 57855, 22783, 7, 31, 32, 40, 18},
29 {47359, 12543, 49471, 22783, 7, 31, 33, 40, 18},
30 {52735, 0, 54847, 10495, 7, 31, 33, 41, 18},
31 {49471, 12543, 51583, 22783, 7, 31, 33, 40, 18},
32 {28543, 23039, 30015, 31999, 7, 25, 23, 35, 8},
33 {4991, 23039, 6463, 33279, 8, 26, 23, 40, 8},
34 {38911, 23039, 41023, 31487, 7, 26, 33, 33, 18},
35 {47231, 23039, 49343, 29951, 7, 23, 33, 27, 18},
36 {41023, 23039, 43135, 31487, 7, 26, 33, 33, 18},
37 {4095, 12543, 6015, 23039, 8, 31, 30, 41, 13},
38 {21695, 0, 24511, 11519, 7, 31, 44, 45, 30},
39 {13055, 12543, 15551, 22783, 9, 31, 39, 40, 21},
40 {40831, 12543, 43007, 22783, 6, 31, 34, 40, 20},
41 {43775, 0, 46079, 10495, 7, 31, 36, 41, 20},
42 {25087, 12543, 27391, 22783, 6, 31, 36, 40, 23},
43 {51583, 12543, 53695, 22783, 6, 31, 33, 40, 18},
44 {57855, 12543, 59903, 22783, 6, 31, 32, 40, 17},
45 {46079, 0, 48383, 10495, 7, 31, 36, 41, 21},
46 {29695, 12543, 31935, 22783, 6, 31, 35, 40, 22},
47 {6463, 23039, 7807, 33279, 6, 31, 21, 40, 8},
48 {61951, 12543, 63935, 22783, 9, 31, 31, 40, 16},
49 {31935, 12543, 34175, 22783, 6, 31, 35, 40, 20},
50 {59903, 12543, 61951, 22783, 6, 31, 32, 40, 16},
51 {10367, 12543, 13055, 22783, 7, 31, 42, 40, 28},
52 {27391, 12543, 29695, 22783, 6, 31, 36, 40, 23},
53 {38783, 0, 41343, 10495, 7, 31, 40, 41, 25},
54 {43007, 12543, 45183, 22783, 6, 31, 34, 40, 19},
55 {17087, 0, 19647, 11775, 7, 31, 40, 46, 25},
56 {48383, 0, 50623, 10495, 6, 31, 35, 41, 20},
57 {54847, 0, 56959, 10495, 8, 32, 33, 41, 17},
58 {34175, 12543, 36415, 22783, 8, 31, 35, 40, 18},
59 {36415, 12543, 38655, 22783, 6, 31, 35, 40, 22},
60 {15551, 12543, 18047, 22783, 9, 31, 39, 40, 21},
61 {7423, 12543, 10367, 22783, 8, 31, 46, 40, 29},
62 {18047, 12543, 20415, 22783, 8, 31, 37, 40, 20},
63 {20415, 12543, 22783, 22783, 9, 31, 37, 40, 19},
64 {45183, 12543, 47359, 22783, 8, 31, 34, 40, 18},
65 {10879, 0, 12479, 12543, 6, 34, 25, 49, 10},
66 {2047, 0, 4095, 12543, 10, 34, 32, 49, 12},
67 {12479, 0, 14079, 12543, 9, 34, 25, 49, 10},
68 {45119, 23039, 47231, 30719, 7, 31, 33, 30, 18},
69 {59071, 23039, 61247, 28415, 9, 6, 34, 21, 15},
70 {53887, 23039, 55423, 29183, 7, 34, 24, 24, 12},
71 {18879, 23039, 20863, 31999, 8, 26, 31, 35, 16},
72 {24511, 0, 26623, 11007, 6, 34, 33, 43, 19},
73 {20863, 23039, 22847, 31999, 7, 26, 31, 35, 15},
74 {26623, 0, 28735, 11007, 7, 34, 33, 43, 19},
75 {12607, 23039, 14719, 31999, 7, 26, 33, 35, 18},
76 {32767, 0, 34559, 11007, 6, 34, 28, 43, 12},
77 {2047, 12543, 4095, 23039, 7, 26, 32, 41, 18},
78 {30783, 0, 32767, 11007, 6, 34, 31, 43, 18},
79 {6015, 12543, 7423, 23039, 7, 32, 22, 41, 8},
80 {15423, 0, 17087, 12031, 11, 32, 26, 47, 8},
81 {28735, 0, 30783, 11007, 6, 34, 32, 43, 16},
82 {34559, 0, 36095, 11007, 7, 34, 24, 43, 8},
83 {7807, 23039, 10431, 31999, 6, 26, 41, 35, 27},
84 {22847, 23039, 24831, 31999, 6, 26, 31, 35, 18},
85 {10431, 23039, 12607, 31999, 7, 26, 34, 35, 19},
86 {56959, 0, 59071, 10495, 6, 26, 33, 41, 19},
87 {59071, 0, 61183, 10495, 7, 26, 33, 41, 19},
88 {26751, 23039, 28543, 31999, 6, 26, 28, 35, 12},
89 {24831, 23039, 26751, 31999, 8, 26, 30, 35, 14},
90 {0, 23039, 1791, 33279, 7, 31, 28, 40, 13},
91 {16831, 23039, 18879, 31999, 7, 25, 32, 35, 18},
92 {34815, 23039, 36927, 31743, 8, 25, 33, 34, 16},
93 {30015, 23039, 32703, 31743, 8, 25, 42, 34, 25},
94 {14719, 23039, 16831, 31999, 8, 26, 33, 35, 16},
95 {53695, 12543, 55807, 22783, 9, 25, 33, 40, 16},
96 {36927, 23039, 38911, 31743, 8, 25, 31, 34, 15},
97 {4095, 0, 5823, 12543, 8, 34, 27, 49, 10},
98 {14079, 0, 15423, 12543, 6, 34, 21, 49, 9},
99 {5823, 0, 7551, 12543, 9, 34, 27, 49, 10},
100 {55423, 23039, 57599, 28927, 8, 21, 34, 23, 18},
101 };
102
103 static struct ui_sdf_font font_Ubuntu = { "Ubuntu", 32, 1024, 256, characters_Ubuntu, &tex_ubuntu };
104 */
105
106 // TEXTURES
107 // ===========================================================================================================
108
109 vg_tex2d tex_tile_data = { .path = "textures/tileset.qoi" };
110 vg_tex2d tex_tile_detail = { .path = "textures/tile_overlays.qoi" };
111 vg_tex2d tex_wood = { .path = "textures/wood.qoi" };
112 vg_tex2d tex_ball_noise = { .path = "textures/bnoise.qoi" };
113 vg_tex2d tex_monofur = { .path = "textures/ascii.qoi", .flags = VG_TEXTURE_NO_MIP };
114 vg_tex2d tex_unkown = { .path = "textures/unkown.qoi" };
115 vg_tex2d tex_buttons = { .path = "textures/buttons.qoi" };
116
117 vg_tex2d *texture_list[] = { &tex_tile_detail, &tex_tile_data, &tex_wood, &tex_ball_noise, &tex_monofur, &tex_unkown, &tex_buttons };
118
119 // AUDIO
120 // ===========================================================================================================
121
122 sfx_vol_control audio_volume_sfx = { .val = 1.0f, .name = "Sound effects" };
123 sfx_vol_control audio_volume_music = { .val = 1.0f, .name = "Music" };
124
125 sfx_system audio_system_sfx =
126 {
127 .vol = 1.f,
128 .ch = 1,
129 .vol_src = &audio_volume_sfx,
130 .name = "sfx"
131 };
132
133 sfx_set audio_tile_mod =
134 {
135 .sources = "\
136 sound/mod_01.ogg\0\
137 sound/mod_02.ogg\0\
138 sound/mod_03.ogg\0\
139 sound/mod_04.ogg\0\
140 sound/mod_05.ogg\0\
141 sound/mod_06.ogg\0",
142 .flags = 0
143 };
144
145 sfx_set audio_splitter =
146 {
147 .sources = "\
148 sound/splitter_01.ogg\0"
149 };
150
151 sfx_set audio_rolls =
152 {
153 .sources = "\
154 sound/rolling_01.ogg\0\
155 sound/rolling_02.ogg\0"
156 };
157
158 sfx_set audio_random =
159 {
160 .sources = "\
161 sound/random_01.ogg\0\
162 sound/random_02.ogg\0\
163 sound/random_03.ogg\0\
164 sound/random_04.ogg\0\
165 sound/random_05.ogg\0\
166 sound/random_06.ogg\0\
167 sound/random_07.ogg\0\
168 sound/random_08.ogg\0"
169 };
170
171 sfx_set audio_clicks =
172 {
173 .sources = "\
174 sound/click_a.ogg\0\
175 sound/click_b.ogg\0\
176 sound/click_c.ogg\0"
177 };
178
179 sfx_set audio_tones =
180 {
181 .sources = "\
182 sound/y0.ogg\0\
183 sound/y1.ogg\0\
184 sound/y2.ogg\0\
185 sound/y3.ogg\0\
186 sound/y4.ogg\0\
187 sound/y5.ogg\0\
188 sound/y6.ogg\0\
189 sound/y7.ogg\0\
190 sound/y8.ogg\0"
191 };
192
193 // One two or three layers of rolling noise
194 sfx_system audio_system_balls_rolling =
195 {
196 .vol = 0.7f, .ch = 1, .vol_src = &audio_volume_sfx,
197 .name = "Balls Rolling", .flags = SFX_FLAG_REPEAT | SFX_FLAG_PERSISTENT
198 };
199
200 // Various oneshots
201 sfx_system audio_system_balls_switching =
202 {
203 .vol = 0.2f, .ch = 1, .vol_src = &audio_volume_sfx,
204 .name = "Balls Switching"
205 };
206
207 // Gameplay critical sounds eg. splitter sound rocking
208 sfx_system audio_system_balls_important =
209 {
210 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
211 .name = "Balls Gameplay"
212 };
213
214 // Suplemental sounds
215 sfx_system audio_system_balls_extra =
216 {
217 .vol = 0.27f, .ch = 1, .vol_src = &audio_volume_sfx,
218 .name = "Balls Extra"
219 };
220
221 sfx_system audio_system_ui =
222 {
223 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
224 .name = "UI"
225 };
226
227 ui_colourset ui_fl_colours = {
228 .main = 0xff807373,
229 .hover = 0xff918484,
230 .active = 0xffad9f9e
231 };
232
233 ui_colourset ui_fl_colours_inactive = {
234 .main = 0xff655958,
235 .hover = 0xff655958,
236 .active = 0xff655958
237 };
238
239 static void resource_load_main(void)
240 {
241 // Textures // UI
242 vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
243 ui_global_ctx.colours_main = &ui_fl_colours;
244 gui_reset_colours();
245
246 // Audio
247 sfx_set_init( &audio_tile_mod, NULL );
248 sfx_set_init( &audio_splitter, NULL );
249 sfx_set_init( &audio_rolls, NULL );
250 sfx_set_init( &audio_random, NULL );
251 sfx_set_init( &audio_clicks, NULL );
252 sfx_set_init( &audio_tones, NULL );
253 }
254
255 static void resource_free_main(void)
256 {
257 vg_tex2d_free( texture_list, vg_list_size( texture_list ) );
258
259 sfx_set_free( &audio_tile_mod );
260 sfx_set_free( &audio_splitter );
261 sfx_set_free( &audio_rolls );
262 sfx_set_free( &audio_random );
263 sfx_set_free( &audio_clicks );
264 sfx_set_free( &audio_tones );
265 }
266
267 // SHADERS
268 // ===========================================================================================================
269
270 SHADER_DEFINE( shader_tile_colour,
271
272 // VERTEX
273 "layout (location=0) in vec2 a_co;"
274 "uniform mat3 uPv;"
275 "uniform vec3 uOffset;"
276 ""
277 "void main()"
278 "{"
279 "gl_Position = vec4( uPv * vec3( a_co * uOffset.z + uOffset.xy, 1.0 ), 1.0 );"
280 "}",
281
282 // FRAGMENT
283 "out vec4 FragColor;"
284 "uniform vec4 uColour;"
285 ""
286 "void main()"
287 "{"
288 "FragColor = uColour;"
289 "}"
290 ,
291 UNIFORMS({ "uPv", "uOffset", "uColour" })
292 )
293
294 SHADER_DEFINE( shader_ball,
295 // VERTEX
296 "layout (location=0) in vec2 a_co;"
297 "uniform vec3 uOffset;"
298 "uniform mat3 uPv;"
299 ""
300 "out vec4 aTexCoords;"
301 ""
302 "void main()"
303 "{"
304 // Vertex transform
305 "vec3 worldpos = vec3( (a_co * 0.5 - 0.25) * uOffset.z + uOffset.xy, 1.0 );"
306 "gl_Position = vec4( uPv * worldpos, 1.0 );"
307
308 // Create texture coords
309 "aTexCoords = vec4( a_co, worldpos.xy );"
310 "}",
311
312 // FRAGMENT
313 "out vec4 FragColor;"
314 ""
315 "uniform sampler2D uTexMain;"
316 "uniform vec3 uColour;"
317 "uniform vec2 uTexOffset;"
318 ""
319 "in vec4 aTexCoords;"
320 ""
321 "void main()"
322 "{"
323 "vec2 center_coords = aTexCoords.xy - 0.5;"
324 "vec2 center_coords_sqr = center_coords*center_coords;"
325 "float circle_factor = smoothstep( 0.07, 0.0625, center_coords_sqr.x+center_coords_sqr.y );"
326
327 "float bulge_amt = center_coords_sqr.x+center_coords_sqr.y;"
328 "vec2 warped_coords = aTexCoords.zw+uTexOffset - center_coords;"
329 "vec4 noise_sample = texture( uTexMain, warped_coords );"
330
331 "float rim_light = (center_coords_sqr.x+center_coords_sqr.y)*15.0;"
332
333 "vec2 shadow_coords = center_coords + vec2(0.02,0.07);"
334 "vec2 shadow_coords_sqr = shadow_coords*shadow_coords;"
335 "float shadow = exp(-((shadow_coords_sqr.x+shadow_coords_sqr.y)-0.0125)*15.0);"
336
337 "vec3 marble_comp = uColour*0.9 + (noise_sample.x*0.7+pow(rim_light,3.0)*2.0) * 0.1;"
338 "vec4 colour_comp = mix( vec4(0.74,0.53,0.34,shadow), vec4(marble_comp,1.0), circle_factor );"
339
340 "FragColor = colour_comp;"
341 "}"
342 ,
343 UNIFORMS({ "uTexMain", "uColour", "uOffset", "uPv", "uTexOffset" })
344 )
345
346 SHADER_DEFINE( shader_tile_main,
347 // VERTEX
348 "layout (location=0) in vec2 a_co;"
349 "uniform vec4 uOffset;" // Tile x/y, uv x/y
350 "uniform mat3 uPv;"
351 "uniform mat2 uSubTransform;"
352 ""
353 "out vec4 aTexCoords;"
354 "out vec2 aWorldCoords;"
355 ""
356 "vec2 hash22(vec2 p)"
357 "{"
358 "vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));"
359 "p3 += dot(p3, p3.yzx+33.33);"
360 "return fract((p3.xx+p3.yz)*p3.zy);"
361 "}"
362 ""
363 "void main()"
364 "{"
365 // Vertex transform
366 "vec2 subtransform = uSubTransform * (a_co-0.5) + 0.5;"
367 "vec3 worldpos = vec3( subtransform + uOffset.xy, 1.0 );"
368 "gl_Position = vec4( uPv * worldpos, 1.0 );"
369
370 // Create texture coords
371 "vec2 random_offset = floor(hash22(uOffset.xy) * 4.0) * 0.25;"
372 "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
373 "aTexCoords = vec4((edge_safe_coords + uOffset.zw) * 0.25, edge_safe_coords * 0.25 + random_offset );"
374 "aWorldCoords = worldpos.xy;"
375 "}",
376
377 // FRAGMENT
378 "out vec4 FragColor;"
379 ""
380 "uniform sampler2D uTexGlyphs;"
381 "uniform sampler2D uTexWood;"
382 "uniform float uGhost;"
383 "uniform float uForeground;"
384 "uniform vec2 uMousePos;"
385 "uniform vec4 uColour;"
386 ""
387 "in vec4 aTexCoords;"
388 "in vec2 aWorldCoords;"
389 ""
390 "void main()"
391 "{"
392 "vec3 shadowing_colour = vec3( 0.93, 0.88536, 0.8184 ) * 0.97;"
393 "vec4 glyph = texture( uTexGlyphs, aTexCoords.xy );"
394 "vec4 wood = texture( uTexWood, aTexCoords.zw );"
395 "vec4 wood_secondary = texture( uTexWood, aTexCoords.zw + 0.25 );"
396 "vec3 wood_comp = mix( wood_secondary.rgb * shadowing_colour, wood.rgb, clamp( glyph.b * 2.0 - 1.0, 0.0, 1.0 ) );"
397
398 "vec3 shadows = mix( vec3( 0.85, 0.7344, 0.561 ), vec3(1.0,1.0,1.0), glyph.r );"
399
400 "vec4 output_regular = vec4( wood_comp * shadows, mix( glyph.a, glyph.b, uForeground ) );"
401
402 "float ghost_dist = clamp( 1.5 - distance(uMousePos, aWorldCoords), 0.0, 1.0 );"
403 "vec4 output_ghost = vec4( 1.0, 1.0, 1.0, glyph.g * ghost_dist );"
404
405 "FragColor = mix( output_regular, output_ghost, uGhost ) * uColour;"
406 "}"
407 ,
408 UNIFORMS({ "uPv", "uOffset", "uTexGlyphs", "uTexWood", "uSubTransform", "uGhost", "uMousePos", "uColour", "uForeground" })
409 )
410
411 SHADER_DEFINE( shader_background,
412 // VERTEX
413 "layout (location=0) in vec2 a_co;"
414 "uniform mat3 uPv;"
415 "uniform vec3 uOffset;"
416 ""
417 "out vec2 aTexCoords;"
418 ""
419 "void main()"
420 "{"
421 "vec2 world_pos = a_co * uOffset.z + uOffset.xy;"
422 "gl_Position = vec4( uPv * vec3( world_pos, 1.0 ), 1.0 );"
423 "aTexCoords = a_co;"
424 "}",
425
426 // FRAGMENT
427 "out vec4 FragColor;"
428 ""
429 "uniform sampler2D uTexMain;"
430 "uniform sampler2D uSamplerNoise;"
431 "uniform float uVariance;"
432 ""
433 "in vec2 aTexCoords;"
434 ""
435 "void main()"
436 "{"
437 "float ao_accum = 0.0;"
438 "for( int i=0; i<10; ++i )"
439 "{"
440 "vec2 random_noise = (texture( uSamplerNoise, aTexCoords * 20.0 + float(i) * 0.2 ).xy - vec2( 0.5, 0.5 )) * uVariance;"
441 "vec4 background = texture( uTexMain, aTexCoords + random_noise );"
442 "ao_accum += background.r * clamp((1.0 - length( random_noise )), 0.0, 1.0);"
443 "}"
444 "ao_accum *= 0.15;"
445
446 "vec4 data_this_tile = texture( uTexMain, aTexCoords );"
447
448 "ao_accum -= data_this_tile.r;"
449
450 "vec3 colour_main = mix( vec3( 0.369768, 0.3654, 0.42 ),vec3( 0.275, 0.388, 0.553 ), data_this_tile.g );"
451
452 "vec2 square_coords = fract( aTexCoords * 64.0 );"
453 "vec2 grid_coords = abs( square_coords - 0.5 );"
454 "float edge_contrast = (1.0-ao_accum*0.2);"
455
456 "float gridline = step( 0.49, max(grid_coords.x,grid_coords.y) );"
457 "float gridline_fadeout = min(max(edge_contrast-1.0, 0.0)*40.0 + data_this_tile.g,10.0);"
458
459 "FragColor = vec4( colour_main * edge_contrast + gridline * 0.02 * gridline_fadeout, 1.0 );"
460 "}"
461 ,
462 UNIFORMS({ "uPv", "uOffset", "uTexMain", "uVariance", "uSamplerNoise" })
463 )
464
465 SHADER_DEFINE( shader_wire,
466 // VERTEX
467 "layout (location=0) in vec2 a_co;"
468 "uniform vec3 uStart;"
469 "uniform vec3 uEnd;"
470 "uniform mat3 uPv;"
471 "uniform float uCurve;"
472 ""
473 "out vec2 aTexCoords;"
474 ""
475 "vec3 sample_curve_time( float t )"
476 "{"
477 "vec3 line_coord = mix( uStart, uEnd, t );"
478
479 "float curve_amt = 1.0-(pow((t*2.0-1.0),2.0));"
480 "return vec3( line_coord.x, line_coord.y - curve_amt*uCurve, line_coord.z );"
481 "}"
482 ""
483 "void main()"
484 "{"
485 // Vertex transform
486 "vec3 p0 = sample_curve_time( a_co.x );"
487 "vec3 p1 = sample_curve_time( a_co.x + 0.025 );"
488
489 "vec2 line_tangent = normalize(p1.xy-p0.xy);"
490 "vec2 line_normal = vec2( -line_tangent.y, line_tangent.x );"
491
492 "vec2 worldfinal = p0.xy + line_normal*a_co.y*p0.z;"
493
494 "gl_Position = vec4( uPv * vec3(worldfinal, 1.0), 1.0 );"
495
496 // Create texture coords (todo: include stretch adjusted coords?)
497 "aTexCoords = vec2( a_co.x, a_co.y + 0.5 );"
498 "}",
499
500 // FRAGMENT
501 "out vec4 FragColor;"
502 ""
503 "uniform sampler2D uTexMain;"
504 "uniform vec4 uColour;"
505 "uniform float uTime;"
506 "uniform float uGlow;"
507 ""
508 "in vec2 aTexCoords;"
509 ""
510 "void main()"
511 "{"
512 // Compute shadowing
513 "float shadow = 1.0 - abs(aTexCoords.y - 0.5) * 2.0;"
514 "float masking = smoothstep( 0.5, 0.8, shadow );"
515
516 "vec3 colour_comp = mix( vec3(0.0,0.0,0.0), uColour.rgb, masking );"
517
518 "float flow_thing = fract( aTexCoords.x + uTime );"
519 "vec3 final_comp = colour_comp + flow_thing * uGlow;"
520
521 "FragColor = vec4( final_comp, max( shadow* 0.2, masking ) * uColour.a );"
522 "}"
523 ,
524 UNIFORMS({ "uPv", "uColour", "uTexMain", "uStart", "uEnd", "uCurve", "uTime", "uGlow" })
525 )
526
527 SHADER_DEFINE( shader_buttons,
528 // VERTEX
529 "layout (location=0) in vec2 a_co;"
530 "uniform vec4 uOffset;" // Tile x/y, uv x/y
531 "uniform mat3 uPv;"
532 ""
533 "out vec2 aTexCoords;"
534 ""
535 "void main()"
536 "{"
537 // Vertex transform
538 "vec3 worldpos = vec3( a_co + uOffset.xy, 1.0 );"
539 "gl_Position = vec4( uPv * worldpos, 1.0 );"
540
541 // Create texture coords
542 "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
543 "aTexCoords = (edge_safe_coords + uOffset.zw) * 0.25;"
544 "}",
545
546 // FRAGMENT
547 "out vec4 FragColor;"
548 ""
549 "uniform sampler2D uTexMain;"
550 "uniform vec4 uColour;" // rgb, light amount
551 ""
552 "in vec2 aTexCoords;"
553 ""
554 "void main()"
555 "{"
556 "vec4 glyph = texture( uTexMain, aTexCoords.xy );"
557
558 "FragColor = vec4( uColour.rgb * (mix(glyph.r, glyph.g, uColour.a)+0.02)*2.6 + glyph.b * 0.4, glyph.a );"
559 "}"
560 ,
561 UNIFORMS({ "uPv", "uOffset", "uTexMain", "uColour" })
562 )
563
564
565 void vg_register(void)
566 {
567 SHADER_INIT( shader_tile_colour );
568 SHADER_INIT( shader_tile_main );
569 SHADER_INIT( shader_ball );
570 SHADER_INIT( shader_background );
571 SHADER_INIT( shader_wire );
572 SHADER_INIT( shader_buttons );
573 }
574
575 /*
576 0000 0 | 0001 1 | 0010 2 | 0011 3
577 | | | | |
578 X | X= | X | X=
579 | | |
580 0100 4 | 0101 5 | 0110 6 | 0111 7
581 | | | | |
582 =X | =X= | =X | =X=
583 | | |
584 1000 8 | 1001 9 | 1010 10 | 1011 11
585 | | | | |
586 X | X= | X | X=
587 | | | | | | |
588 1100 12 | 1101 13 | 1110 14 | 1111 15
589 | | | | |
590 =X | =X= | =X | =X=
591 | | | | | | |
592 */
593
594 float const MESH_NUMBER_0[] = {
595 #include "fonts/numbers/n0.h"
596 };
597
598 float const MESH_NUMBER_1[] = {
599 #include "fonts/numbers/n1.h"
600 };
601
602 float const MESH_NUMBER_2[] = {
603 #include "fonts/numbers/n2.h"
604 };
605
606 float const MESH_NUMBER_3[] = {
607 #include "fonts/numbers/n3.h"
608 };
609
610 float const MESH_NUMBER_4[] = {
611 #include "fonts/numbers/n4.h"
612 };
613
614 float const MESH_NUMBER_5[] = {
615 #include "fonts/numbers/n5.h"
616 };
617
618 float const MESH_NUMBER_6[] = {
619 #include "fonts/numbers/n6.h"
620 };
621
622 float const MESH_NUMBER_7[] = {
623 #include "fonts/numbers/n7.h"
624 };
625
626 float const MESH_NUMBER_8[] = {
627 #include "fonts/numbers/n8.h"
628 };
629
630 float const MESH_NUMBER_9[] = {
631 #include "fonts/numbers/n9.h"
632 };
633
634 float const MESH_NUMBERS_BUFFER[] =
635 {
636 #include "fonts/numbers/n0.h"
637 #include "fonts/numbers/n1.h"
638 #include "fonts/numbers/n2.h"
639 #include "fonts/numbers/n3.h"
640 #include "fonts/numbers/n4.h"
641 #include "fonts/numbers/n5.h"
642 #include "fonts/numbers/n6.h"
643 #include "fonts/numbers/n7.h"
644 #include "fonts/numbers/n8.h"
645 #include "fonts/numbers/n9.h"
646 };
647
648 #define MESH_NUMBER_DIVISOR 6
649
650 u32 const MESH_NUMBERS_OFFSETS[][2] =
651 {
652 {
653 0,
654 vg_list_size( MESH_NUMBER_0 ) / MESH_NUMBER_DIVISOR
655 },
656 {
657 vg_list_size( MESH_NUMBER_0 ) / MESH_NUMBER_DIVISOR,
658 vg_list_size( MESH_NUMBER_1 ) / MESH_NUMBER_DIVISOR
659 },
660 {
661 (
662 vg_list_size( MESH_NUMBER_0 ) +
663 vg_list_size( MESH_NUMBER_1 )
664 ) / MESH_NUMBER_DIVISOR,
665 vg_list_size( MESH_NUMBER_2 ) / MESH_NUMBER_DIVISOR
666 },
667 {
668 (
669 vg_list_size( MESH_NUMBER_0 ) +
670 vg_list_size( MESH_NUMBER_1 ) +
671 vg_list_size( MESH_NUMBER_2 )
672 ) / MESH_NUMBER_DIVISOR,
673 vg_list_size( MESH_NUMBER_3 ) / MESH_NUMBER_DIVISOR
674 },
675 {
676 (
677 vg_list_size( MESH_NUMBER_0 ) +
678 vg_list_size( MESH_NUMBER_1 ) +
679 vg_list_size( MESH_NUMBER_2 ) +
680 vg_list_size( MESH_NUMBER_3 )
681 ) / MESH_NUMBER_DIVISOR,
682 vg_list_size( MESH_NUMBER_4 ) / MESH_NUMBER_DIVISOR
683 },
684 {
685 (
686 vg_list_size( MESH_NUMBER_0 ) +
687 vg_list_size( MESH_NUMBER_1 ) +
688 vg_list_size( MESH_NUMBER_2 ) +
689 vg_list_size( MESH_NUMBER_3 ) +
690 vg_list_size( MESH_NUMBER_4 )
691 ) / MESH_NUMBER_DIVISOR,
692 vg_list_size( MESH_NUMBER_5 ) / MESH_NUMBER_DIVISOR
693 },
694 {
695 (
696 vg_list_size( MESH_NUMBER_0 ) +
697 vg_list_size( MESH_NUMBER_1 ) +
698 vg_list_size( MESH_NUMBER_2 ) +
699 vg_list_size( MESH_NUMBER_3 ) +
700 vg_list_size( MESH_NUMBER_4 ) +
701 vg_list_size( MESH_NUMBER_5 )
702 ) / MESH_NUMBER_DIVISOR,
703 vg_list_size( MESH_NUMBER_6 ) / MESH_NUMBER_DIVISOR
704 },
705 {
706 (
707 vg_list_size( MESH_NUMBER_0 ) +
708 vg_list_size( MESH_NUMBER_1 ) +
709 vg_list_size( MESH_NUMBER_2 ) +
710 vg_list_size( MESH_NUMBER_3 ) +
711 vg_list_size( MESH_NUMBER_4 ) +
712 vg_list_size( MESH_NUMBER_5 ) +
713 vg_list_size( MESH_NUMBER_6 )
714 ) / MESH_NUMBER_DIVISOR,
715 vg_list_size( MESH_NUMBER_7 ) / MESH_NUMBER_DIVISOR
716 },
717 {
718 (
719 vg_list_size( MESH_NUMBER_0 ) +
720 vg_list_size( MESH_NUMBER_1 ) +
721 vg_list_size( MESH_NUMBER_2 ) +
722 vg_list_size( MESH_NUMBER_3 ) +
723 vg_list_size( MESH_NUMBER_4 ) +
724 vg_list_size( MESH_NUMBER_5 ) +
725 vg_list_size( MESH_NUMBER_6 ) +
726 vg_list_size( MESH_NUMBER_7 )
727 ) / MESH_NUMBER_DIVISOR,
728 vg_list_size( MESH_NUMBER_8 ) / MESH_NUMBER_DIVISOR
729 },
730 {
731 (
732 vg_list_size( MESH_NUMBER_0 ) +
733 vg_list_size( MESH_NUMBER_1 ) +
734 vg_list_size( MESH_NUMBER_2 ) +
735 vg_list_size( MESH_NUMBER_3 ) +
736 vg_list_size( MESH_NUMBER_4 ) +
737 vg_list_size( MESH_NUMBER_5 ) +
738 vg_list_size( MESH_NUMBER_6 ) +
739 vg_list_size( MESH_NUMBER_7 ) +
740 vg_list_size( MESH_NUMBER_8 )
741 ) / MESH_NUMBER_DIVISOR,
742 vg_list_size( MESH_NUMBER_9 ) / MESH_NUMBER_DIVISOR
743 }
744 };
745
746 struct cmp_level
747 {
748 const char *map_name;
749 const char *title;
750 const char *description;
751
752 int unlocked;
753 int completed_score;
754
755 int _unlock, _linked; // When completed, unlock this level
756 struct cmp_level *unlock, *linked;
757
758 int serial_id;
759 int is_tutorial;
760
761 SteamLeaderboard_t steam_leaderboard;
762 };
763
764 static struct cmp_level cmp_levels_tutorials[] =
765 {
766 // r1
767 {
768 .serial_id = 0,
769 .title = "PRINCIPLE 1",
770 .map_name = "cmp_t01",
771 .description =
772 "Utilize basic transport methods",
773
774 ._unlock = 1,
775 .is_tutorial = 1
776 },
777 // r1
778 {
779 .serial_id = 1,
780 .title = "PRINCIPLE 2",
781 .map_name = "cmp_t02",
782 .description =
783 "Utilize the twisty turny(TM) piece to split the marble\n"
784 "stream into two",
785
786 ._unlock = 2,
787 .is_tutorial = 1,
788 },
789 // r1
790 {
791 .serial_id = 2,
792 .title = "PRINCIPLE 3",
793 .map_name = "cmp_t03",
794 .description =
795 "Merge transport into one path",
796
797 ._unlock = 12,
798 .is_tutorial = 1
799 },
800 // r1
801 {
802 .serial_id = 12,
803 .title = "PRINCIPLE 4",
804 .map_name = "cmp_t04",
805 .description =
806 "Some stages require multiple runs to succeed in order to\n"
807 "pass",
808
809 ._unlock = 6,
810 .is_tutorial = 1
811 }
812 };
813
814 static struct cmp_level cmp_levels_basic[] =
815 {
816 // r2 GM
817 {
818 .serial_id = 6,
819 .title = "PATCH",
820 .map_name = "cmp_b04",
821 .description =
822 "For some reason, the division module our intern built\n"
823 "for us is sending twice as many yellows as needed. Send\n"
824 "the excess to be recycled!",
825
826 ._unlock = 7,
827 ._linked = 3
828 },
829 // r1 GM
830 {
831 .serial_id = 3,
832 .title = "SUBDIVISION 1",
833 .map_name = "cmp_b01",
834 .description =
835 "Sometimes getting the desired amount takes dividing up\n"
836 "the input and recombining it.",
837
838 ._linked = 4,
839 ._unlock = 5
840 },
841 // r1 GM
842 {
843 .serial_id = 4,
844 .title = "SUBDIVISION 2",
845 .map_name = "cmp_b02",
846 .description =
847 "",
848
849 ._unlock = 7
850 },
851 // r1 GM
852 {
853 .serial_id = 5,
854 .title = "RESTRUCTURE",
855 .map_name = "cmp_b03",
856 .description =
857 "It is possible to swap these values using simple\n"
858 "division and addition.",
859
860 ._unlock = 8
861 },
862 // r2 GM
863 {
864 .serial_id = 7,
865 .title = "PATTERNS 1",
866 .map_name = "cmp_b05",
867 .description =
868 "Replicate the pattern",
869
870 ._linked = 8
871 },
872 // r2 GM
873 {
874 .serial_id = 8,
875 .title = "PATTERNS 2",
876 .map_name = "cmp_b06",
877 .description =
878 "Replicate MORE",
879
880 ._unlock = 15
881 },
882 // r2 GM
883 {
884 .serial_id = 15,
885 .title = "PRINCIPLE 5",
886 .map_name = "cmp_b10",
887 .description =
888 "The sharp engineers among you may have already spotted\n"
889 "and utilized this part of the system\n"
890 "\n"
891 "We forgot to include the relevant principle tasks as\n"
892 "of your training package, you will now be tasked to\n"
893 "complete them",
894
895 ._unlock = 16,
896 .is_tutorial = 1
897 },
898 // r2 GM
899 {
900 .serial_id = 16,
901 .title = "ROUTING PROBLEM",
902 .map_name = "cmp_routing",
903 .description =
904 "Things can get a little chaotic on tight boards, do your\n"
905 "best to utilize principle 5 to get the job done\n",
906
907 ._linked = 9
908 },
909 // r2 GM
910 {
911 .serial_id = 9,
912 .title = "MIGHTY CONSUMER",
913 .map_name = "cmp_b07",
914 .description =
915 "Build a greedy system",
916
917 ._linked = 10,
918 ._unlock = 11
919 },
920 {
921 .serial_id = 10,
922 .title = "SHIFT",
923 .map_name = "cmp_b08",
924 .description =
925 "",
926
927 ._unlock = 17
928 },
929 // r2 GM
930 {
931 .serial_id = 11,
932 .title = "REVERSE",
933 .map_name = "cmp_b09",
934 .description =
935 "Reverse the incoming order. Always length 4",
936
937 ._unlock = 17
938 },
939 // r2 GM
940 {
941 .serial_id = 17,
942 .title = "PRINCIPLE 6",
943 .map_name = "cmp_b11",
944 .description =
945 "Usually the splitter piece will flip flop between left\n"
946 "and right, however it can be forced to only rotate in\n"
947 "one direction if trigger wires are attached.\n"
948 "\n"
949 "Right click and drag from a regular block, and attach it\n"
950 "to a splitter. This creates a trigger.\n"
951 "The default state is left, and once a marble hits the\n"
952 "trigger it will switch to rotating that direction.",
953
954 ._unlock = 18,
955 .is_tutorial = 1
956 },
957 // r2 GM
958 {
959 .serial_id = 18,
960 .title = "NOT GATE",
961 .map_name = "cmp_not",
962 .description =
963 "Test your knowledge of triggers, build an 'NOT GATE'\n"
964 "emulated by marble logic.",
965
966 ._linked = 19,
967 ._unlock = 20
968 },
969 // r2 GM
970 {
971 .serial_id = 19,
972 .title = "AND GATE",
973 .map_name = "cmp_and",
974 .description =
975 "A slightly more complicated gate, but shouldn't be\n"
976 "too difficult for your skillset.",
977
978 ._unlock = 20
979 },
980 // r2 GM
981 {
982 .serial_id = 20,
983 .title = "QUALIFICATION PROJECT",
984 .map_name = "cmp_xor",
985 .description =
986 "Significantly more complicated than an AND or NOT gate,\n"
987 "but possible.",
988
989 ._unlock = 13
990 }
991 };
992
993 static struct cmp_level cmp_levels_grad[] =
994 {
995 // r2
996 {
997 .serial_id = 13,
998 .title = "SORT",
999 .map_name = "cmp_i01",
1000 .description =
1001 "Devise a scheme to filter and sort the inputs. If you\n"
1002 "believe you lack the tools required to solve this one,\n"
1003 "take a harder look at the inputs.",
1004 ._linked = 14
1005
1006 },
1007 // r2
1008 {
1009 .serial_id = 14,
1010 .title = "THIRDS",
1011 .map_name = "cmp_i02",
1012 .description =
1013 "Split the inputs up into a third of their values\n"
1014 "\n"
1015 "Is this possible? -HG",
1016 ._linked = 21
1017
1018 },
1019 // r2 GM
1020 {
1021 .serial_id = 21,
1022 .title = "SIMPLE ADDITION",
1023 .map_name = "cmp_grad",
1024 .description =
1025 "Take the amount of yellows coming in, and add them\n"
1026 "together. Send your result using the stream of blues.",
1027
1028 ._linked = 22
1029 },
1030 // r2 GM
1031 {
1032 .serial_id = 22,
1033 .title = "SECRET CODE",
1034 .map_name = "cmp_secret",
1035 .description =
1036 ""
1037 }
1038 };
1039
1040 #define NUM_CAMPAIGN_LEVELS (vg_list_size( cmp_levels_tutorials ) + vg_list_size( cmp_levels_basic ) + vg_list_size( cmp_levels_grad ))
1041
1042 static struct serializable_set
1043 {
1044 struct cmp_level *pack;
1045 int count;
1046 }
1047 career_serializable[] =
1048 {
1049 {
1050 .pack = cmp_levels_tutorials,
1051 .count = vg_list_size( cmp_levels_tutorials )
1052 },
1053 {
1054 .pack = cmp_levels_basic,
1055 .count = vg_list_size( cmp_levels_basic )
1056 },
1057 {
1058 .pack = cmp_levels_grad,
1059 .count = vg_list_size( cmp_levels_grad )
1060 }
1061 };
1062
1063 // Setup pointers and that
1064 static void career_local_data_init(void)
1065 {
1066 struct cmp_level *level_ptrs[ NUM_CAMPAIGN_LEVELS ];
1067
1068 // COllect pointers
1069 for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
1070 {
1071 struct serializable_set *set = &career_serializable[i];
1072
1073 for( int j = 0; j < set->count; j ++ )
1074 level_ptrs[ set->pack[j].serial_id ] = &set->pack[j];
1075 }
1076
1077 // Apply
1078 for( int i = 0; i < vg_list_size( career_serializable ); i ++ )
1079 {
1080 struct serializable_set *set = &career_serializable[i];
1081
1082 for( int j = 0; j < set->count; j ++ )
1083 {
1084 struct cmp_level *lvl = &set->pack[j];
1085 lvl->unlock = lvl->_unlock? level_ptrs[ lvl->_unlock ]: NULL;
1086 lvl->linked = lvl->_linked? level_ptrs[ lvl->_linked ]: NULL;
1087 }
1088 }
1089 }