![]() |
|
Shader Puzzle aka Reverse Engineering cool effect |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
I recently came across a cool demo by SilverTES but sadly there is no source file with it, only a static exe and the shader source. I tried to recreate the effect using the latest code he posted in that thread, but all it does is draw an expanding white circle. The shockwave effect doesn't work with my source code. Funny thing is, they're using the same shader, so in theory only the parameters being passed to the shader are different. Here's the code I tried : 1// -----------------------------------------------------------------------
2// --- Includes ---
3// -----------------------------------------------------------------------
4
5#include <iostream>
6#include <allegro5/allegro.h>
7#include <allegro5/allegro_image.h>
8#include <allegro5/allegro_primitives.h>
9
10// -----------------------------------------------------------------------
11// --- Global variables ---
12// -----------------------------------------------------------------------
13
14ALLEGRO_KEYBOARD_STATE keyState;
15ALLEGRO_MOUSE_STATE mouseState;
16ALLEGRO_DISPLAY * windowDisplay(NULL);
17ALLEGRO_BITMAP * windowBuffer(NULL);
18
19ALLEGRO_EVENT_QUEUE * eventQueue(NULL);
20ALLEGRO_TIMER * framerateTimer(NULL);
21int framerate(0);
22
23// User data
24ALLEGRO_SHADER * myShader(NULL);
25const char * myShaderVertFileName("myShaderVert.glsl");
26const char * myShaderFragFileName("myShaderFrag.glsl");
27
28ALLEGRO_BITMAP * myImage(NULL);
29const char * myImageFileName("bg0.png");
30// Window setting
31int screenW(640);
32int screenH(360);
33int zoom(2);
34// Absolute mouse position
35int mouseXi(0);
36int mouseYi(0);
37// Relative mouse position
38float mouseXf(0);
39float mouseYf(0);
40// Window position in the desktop
41int xWindow(0);
42int yWindow(0);
43
44// -----------------------------------------------------------------------
45// --- Global Methods ---
46// -----------------------------------------------------------------------
47
48template <class M>
49int log (int error, M msg)
50{
51 std::cout << msg;
52
53 return error;
54}
55
56void setFramerate(int fps)
57{
58 eventQueue = al_create_event_queue();
59 framerate = fps;
60 framerateTimer = al_create_timer(1.000/framerate);
61
62 al_register_event_source (eventQueue,al_get_timer_event_source(framerateTimer));
63 al_start_timer(framerateTimer);
64}
65
66void drawGrid(int screenW, int screenH,
67 int sizeX, int sizeY,
68 ALLEGRO_COLOR color)
69{
70 for (int i(0); i<(screenW/sizeX); i++)
71 {
72 al_draw_line(i*sizeX+.5, .5, i*sizeX+.5, screenH+.5, color,0);
73 }
74
75 for (int i(0); i<(screenH/sizeY)+1; i++)
76 {
77 al_draw_line(.5, i*sizeY+.5, screenW+.5, i*sizeY+.5, color,0);
78 }
79}
80
81ALLEGRO_SHADER* create_shader(const char* fileNameVert, const char* fileNameFrag )
82{
83 ALLEGRO_SHADER* shader = al_create_shader(ALLEGRO_SHADER_GLSL);
84// if(!al_attach_shader_source(shader,
85// ALLEGRO_VERTEX_SHADER,
86// al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_VERTEX_SHADER)))
87 if(!al_attach_shader_source_file(shader, ALLEGRO_VERTEX_SHADER, fileNameVert))
88 {
89 printf("%s\n", al_get_shader_log(shader));
90 return NULL;
91 }
92 if(!al_attach_shader_source_file(shader, ALLEGRO_PIXEL_SHADER, fileNameFrag))
93 {
94 printf("%s\n", al_get_shader_log(shader));
95 return NULL;
96 }
97 if(!al_build_shader(shader))
98 {
99 printf("%s\n", al_get_shader_log(shader));
100 return NULL;
101 }
102 std::cout << " >>> "<< al_get_shader_log(shader) << " \n";
103
104 return shader;
105}
106
107// -----------------------------------------------------------------------
108// ---- INIT ---
109// -----------------------------------------------------------------------
110int init()
111{
112// Init Allegro 5
113 if (!al_init())
114 return log(1,"Unable to Init ALLEGRO_5 ! \n");
115
116// Init & Install : Modules & Addon
117 if (!al_install_keyboard())
118 return log(1,"Unable to Install Keyboard ! \n");
119
120 if (!al_install_mouse())
121 return log(1,"Unable to Install Keyboard ! \n");
122
123 if (!al_init_image_addon())
124 return log(1,"Unable to Init Image addon ! \n");
125
126 if (!al_init_primitives_addon())
127 return log(1,"Unable to Init Primitives addon ! \n");
128
129// Settings
130 al_set_new_display_flags(ALLEGRO_WINDOWED);
131 al_set_new_display_flags(ALLEGRO_OPENGL);
132 //al_set_new_display_flags(ALLEGRO_PROGRAMMABLE_PIPELINE | ALLEGRO_OPENGL);
133
134 setFramerate(60);
135
136// Create All
137 windowDisplay = al_create_display(screenW*zoom, screenH*zoom);
138 if (!windowDisplay)
139 return log(1,"Unable to Create display ! \n");
140
141 windowBuffer = al_create_bitmap(screenW, screenH);
142 if (!windowDisplay)
143 return log(1,"Unable to Create Buffer ! \n");
144
145 al_show_mouse_cursor(windowDisplay);
146
147 myImage = al_load_bitmap(myImageFileName);
148
149
150 myShader = create_shader(myShaderVertFileName,myShaderFragFileName);
151
152 if(!myShader)
153 return log(1," Error in create myShader !\n");
154
155 return log(0,"--- init OK !\n");
156}
157// -----------------------------------------------------------------------
158// --- DONE ---
159// -----------------------------------------------------------------------
160int done()
161{
162// Destroy All
163 al_destroy_bitmap(myImage);
164 al_destroy_event_queue(eventQueue);
165 al_destroy_timer(framerateTimer);
166 al_destroy_shader(myShader);
167 al_destroy_bitmap(windowBuffer);
168 al_destroy_display(windowDisplay);
169
170 return log(0,"--- done OK !\n");
171}
172// -----------------------------------------------------------------------
173// --- RUN ---
174// -----------------------------------------------------------------------
175int run()
176{
177
178 bool quit(false);
179
180 float centerX(0);
181 float centerY(0);
182 float radius(0);
183 float maxRadius(200);
184 float speed(0);
185
186 while (!quit)
187 {
188 // --- Update ---
189
190 ALLEGRO_EVENT event;
191 al_wait_for_event(eventQueue, &event);
192
193 // Keyboard Input !
194 al_get_keyboard_state(&keyState);
195 if (al_key_down(&keyState, ALLEGRO_KEY_ESCAPE))
196 quit = true;
197
198 // Mouse Input !
199 al_get_mouse_state(&mouseState);
200 al_get_window_position (windowDisplay, &xWindow, &yWindow);
201 al_get_mouse_cursor_position(&mouseXi, &mouseYi);
202 mouseXf = (float(mouseXi-xWindow)-2)/zoom;
203 mouseYf = (float(mouseYi-yWindow)-24)/zoom;
204
205 if (mouseState.buttons & 1)
206 {
207 centerX = mouseXf;
208 centerY = mouseYf;
209 radius = 0;
210 speed = 4;
211 }
212
213 // ShockWave Update !
214 radius += speed;
215 if (radius > maxRadius)
216 {
217 radius = 0;
218 speed = 0;
219 }
220
221 // --- Render ---
222
223 // clear windowbuffer !
224 al_set_target_bitmap(windowBuffer);
225 al_clear_to_color(al_map_rgb(0,25,40));
226
227 // Begin drawing !
228
229 // Use shader here before blit buffer to display !!
230 al_use_shader(myShader);
231 al_set_shader_sampler("texture", myImage, 0);
232
233 float center[2] = { centerX, centerY };
234 float shockParams[3] = {10.0, 0.8, 0.1};
235
236 al_set_shader_float("time", radius);
237 al_set_shader_float_vector("center", 2, ¢er[0], 1);
238 al_set_shader_float_vector("shockParams", 3, &shockParams[0], 1);
239
240 al_draw_bitmap(myImage, 0,0,0);
241
242 al_use_shader(NULL);
243
244 drawGrid(screenW, screenH,32,32,al_map_rgba(0,45,80,50));
245 al_draw_rectangle(0.5, 0.5,
246 screenW-.5, screenH-.5,
247 al_map_rgb(250,120,180),0);
248
249 al_draw_line(0, mouseYf, screenW, mouseYf, al_map_rgba(10,100,155,50), 0);
250 al_draw_line(mouseXf, 0, mouseXf, screenH, al_map_rgba(10,100,155,50), 0);
251
252 al_draw_circle(centerX, centerY, radius, al_map_rgba(250,200,210,50),0);
253
254
255 /// End drawing !
256
257 // Blit buffer to display !
258 al_set_target_backbuffer(windowDisplay);
259 al_clear_to_color(al_map_rgb(0,0,0));
260
261
262 al_draw_scaled_bitmap(windowBuffer,
263 0, 0, screenW, screenH,
264 0, 0, screenW*zoom, screenH*zoom,
265 0),
266
267
268 // Flip display !
269 al_flip_display();
270
271
272 }
273
274 return log(0,"--- run OK !\n");
275}
276// -----------------------------------------------------------------------
277// --- MAIN ---
278// -----------------------------------------------------------------------
279int main()
280{
281 if (init())
282 return log(1, "Error in init() \n");
283 if (run())
284 return log(1, "Error in run() \n");
285 if (done())
286 return log(1, "Error in done() \n");
287
288 return log(0,"--- Terminated normally ! \n");;
289}
Cookies and kudos to anyone who can help me figure this out. EDIT // ShockWave Update ! radius += speed; if (radius > maxRadius) { speed = -speed; } if (radius < 0) { radius = 0; speed = 0; }
The thread I'm referring to is here : The effect looks like this (it's much better in action) : It's a spherical distortion of some sort. Here's the vertex shader SilverTES used. (You can download them above) : 1#ifdef GL_ES
2precision mediump float;
3#endif
4
5uniform sampler2D tex; // 0
6uniform vec2 center; // Mouse position
7uniform float time; // effect elapsed time
8uniform vec3 shockParams; // 10.0, 0.8, 0.1
9
10uniform vec2 surface; // texture resolution
11
12void main()
13{
14 vec2 uv = gl_TexCoord[0].xy;
15 vec2 texCoord = uv;
16
17 //float square = min(surface.x,surface.y);
18 //vec2 position = vec2(center.x/square, center.y/square);
19
20 vec2 position = center/surface;
21 float dist = distance(uv, position);
22
23 //float dist = distance(vec2(uv.x,uv.y), vec2(position.x,position.y));
24
25 if ((dist <= (time + shockParams.z)) && (dist >= (time - shockParams.z)) )
26 {
27 float diff = (dist - time);
28 float powDiff = 1.0 - pow(abs(diff*shockParams.x), shockParams.y);
29 float diffTime = diff * powDiff;
30 vec2 diffUV = normalize(uv - position);
31 texCoord = uv + (diffUV * diffTime);
32 }
33
34 gl_FragColor = texture2D(tex, texCoord);
35}
UPDATE Here's the new code - I redid most of it. 1// -----------------------------------------------------------------------
2// --- Includes ---
3// -----------------------------------------------------------------------
4
5#include <iostream>
6#include <allegro5/allegro.h>
7#include <allegro5/allegro_image.h>
8#include <allegro5/allegro_primitives.h>
9#include <allegro5/allegro_opengl.h>
10
11#include <cmath>
12
13// -----------------------------------------------------------------------
14// --- Global variables ---
15// -----------------------------------------------------------------------
16
17ALLEGRO_DISPLAY * d(NULL);
18ALLEGRO_BITMAP * windowBuffer(NULL);
19
20ALLEGRO_EVENT_QUEUE* q(NULL);
21ALLEGRO_TIMER * t(NULL);
22
23
24ALLEGRO_SHADER * myShader(NULL);
25const char * myShaderVertFileName("myShaderVert.glsl");
26const char * myShaderFragFileName("myShaderFrag.glsl");
27
28ALLEGRO_BITMAP * myImage(NULL);
29const char * myImageFileName("bg0.png");
30// Window setting
31int screenW(800);
32int screenH(600);
33
34// -----------------------------------------------------------------------
35// --- Global Methods ---
36// -----------------------------------------------------------------------
37
38template <class M>
39int log (int error, M msg)
40{
41 std::cout << msg;
42
43 return error;
44}
45
46void drawGrid(int screenW, int screenH,
47 int sizeX, int sizeY,
48 ALLEGRO_COLOR color)
49{
50 for (int i(0); i<(screenW/sizeX); i++)
51 {
52 al_draw_line(i*sizeX+.5, .5, i*sizeX+.5, screenH+.5, color,0);
53 }
54
55 for (int i(0); i<(screenH/sizeY)+1; i++)
56 {
57 al_draw_line(.5, i*sizeY+.5, screenW+.5, i*sizeY+.5, color,0);
58 }
59}
60
61ALLEGRO_SHADER* create_shader(const char* fileNameVert, const char* fileNameFrag )
62{
63 ALLEGRO_SHADER* shader = al_create_shader(ALLEGRO_SHADER_GLSL);
64// if(!al_attach_shader_source(shader,
65// ALLEGRO_VERTEX_SHADER,
66// al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_VERTEX_SHADER)))
67 if(!al_attach_shader_source_file(shader, ALLEGRO_VERTEX_SHADER, fileNameVert))
68 {
69 printf("%s\n", al_get_shader_log(shader));
70 return NULL;
71 }
72 if(!al_attach_shader_source_file(shader, ALLEGRO_PIXEL_SHADER, fileNameFrag))
73 {
74 printf("%s\n", al_get_shader_log(shader));
75 return NULL;
76 }
77 if(!al_build_shader(shader))
78 {
79 printf("%s\n", al_get_shader_log(shader));
80 return NULL;
81 }
82 std::cout << " >>> "<< al_get_shader_log(shader) << " \n";
83
84 return shader;
85}
86
87// -----------------------------------------------------------------------
88// ---- INIT ---
89// -----------------------------------------------------------------------
90int init()
91{
92// Init Allegro 5
93 if (!al_init())
94 return log(1,"Unable to Init ALLEGRO_5 ! \n");
95
96// Init & Install : Modules & Addon
97 if (!al_install_keyboard())
98 return log(1,"Unable to Install Keyboard ! \n");
99
100 if (!al_install_mouse())
101 return log(1,"Unable to Install Keyboard ! \n");
102
103 if (!al_init_image_addon())
104 return log(1,"Unable to Init Image addon ! \n");
105
106 if (!al_init_primitives_addon())
107 return log(1,"Unable to Init Primitives addon ! \n");
108
109// Settings
110/// al_set_new_display_flags(ALLEGRO_PROGRAMMABLE_PIPELINE | ALLEGRO_OPENGL | ALLEGRO_WINDOWED);
111 al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_WINDOWED);
112
113// Create All
114 d = al_create_display(screenW, screenH);
115 if (!d)
116 return log(1,"Unable to Create display ! \n");
117
118 windowBuffer = al_create_bitmap(screenW, screenH);
119 myImage = al_create_bitmap(screenW, screenH);
120 if (!windowBuffer)
121 return log(1,"Unable to Create Buffer ! \n");
122
123 q = al_create_event_queue();
124 t = al_create_timer(1.0/60.0);
125
126 al_register_event_source(q , al_get_display_event_source(d));
127 al_register_event_source(q , al_get_mouse_event_source());
128 al_register_event_source(q , al_get_timer_event_source(t));
129 al_register_event_source(q , al_get_keyboard_event_source());
130
131 al_show_mouse_cursor(d);
132
133 ALLEGRO_BITMAP* image = al_load_bitmap(myImageFileName);
134 al_set_target_bitmap(myImage);
135 al_set_blender(ALLEGRO_ADD , ALLEGRO_ONE , ALLEGRO_ZERO);
136 al_draw_scaled_bitmap(image , 0 , 0 , al_get_bitmap_width(image) , al_get_bitmap_height(image) , 0 , 0 , screenW , screenH , 0);
137 al_set_blender(ALLEGRO_ADD , ALLEGRO_ONE , ALLEGRO_INVERSE_ALPHA);
138 al_destroy_bitmap(image);
139
140 myShader = create_shader(myShaderVertFileName,myShaderFragFileName);
141
142 if(!myShader)
143 return log(1," Error in create myShader !\n");
144
145 return log(0,"--- init OK !\n");
146}
147// -----------------------------------------------------------------------
148// --- DONE ---
149// -----------------------------------------------------------------------
150int done()
151{
152 al_uninstall_system();
153
154 return log(0,"--- done OK !\n");
155}
156// -----------------------------------------------------------------------
157// --- RUN ---
158// -----------------------------------------------------------------------
159int run()
160{
161
162 bool quit = false;
163 bool redraw = true;
164
165 float radius(0);
166 float maxRadius(300);
167 float speed(0);
168 float dt = 0.0f;
169
170 int mx = 0 , my = 0;
171
172 bool warp = false;
173
174 al_start_timer(t);
175
176 while (!quit)
177 {
178 // --- Update ---
179
180 ALLEGRO_EVENT ev;
181 al_wait_for_event(q, &ev);
182
183 // Keyboard Input !
184 if (ev.type == ALLEGRO_EVENT_KEY_DOWN && ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
185 quit = true;
186 }
187 if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
188 quit = true;
189 }
190 if (ev.type == ALLEGRO_EVENT_MOUSE_AXES) {
191 mx = ev.mouse.x;
192 my = ev.mouse.y;
193 }
194 if (ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN && ev.mouse.button & 1) {
195 // Mouse Input !
196 warp = true;
197 radius = 0;
198 speed = 5;
199 }
200
201 if (ev.type == ALLEGRO_EVENT_TIMER) {
202 redraw = true;
203 // ShockWave Update !
204 radius += speed;
205 if (radius > maxRadius)
206 {
207 speed = -speed;
208 }
209 if (radius < 0) {
210 radius = 0;
211 speed = 0;
212 warp = false;
213 }
214
215 dt = 2.0*M_PI*(radius/maxRadius);
216 }
217
218 if (redraw) {
219 redraw = false;
220 // --- Render ---
221
222 // clear windowbuffer !
223 al_set_target_bitmap(windowBuffer);
224 al_clear_to_color(al_map_rgb(0,0,255));
225
226 // Begin drawing !
227
228 // Use shader here before blit buffer to display !!
229 al_use_shader(myShader);
230 al_set_shader_sampler("tex", myImage, 0);
231
232 int tw = 0;
233 int th = 0;
234 al_get_opengl_texture_size(myImage , &tw , &th);
235
236 float dim[2] = {(float)al_get_bitmap_width(myImage) , (float)al_get_bitmap_height(myImage)};
237
238 float ms[2] = {(float)mx,(float)(screenH - my)};
239
240 float r = radius;
241
242 al_set_shader_bool("warp" , warp);
243 al_set_shader_float("radius", r);
244 al_set_shader_float("dt", dt);
245 al_set_shader_float_vector("mouse" , 2 , &ms[0] , 1);
246 al_set_shader_float_vector("dim", 2, &dim[0], 1);
247
248 al_draw_bitmap(myImage, 0,0,0);
249
250 al_use_shader(NULL);
251
252 drawGrid(screenW, screenH,32,32,al_map_rgba(0,45,80,50));
253 al_draw_rectangle(0.5, 0.5,
254 screenW-.5, screenH-.5,
255 al_map_rgb(250,120,180),0);
256
257
258
259 /// End drawing !
260
261 // Blit buffer to display !
262 al_set_target_backbuffer(d);
263 al_clear_to_color(al_map_rgb(0,0,0));
264
265
266 al_draw_bitmap(windowBuffer , 0 , 0 , 0);
267
268 // Flip display !
269 al_flip_display();
270 }
271
272
273 }
274
275 return log(0,"--- run OK !\n");
276}
277// -----------------------------------------------------------------------
278// --- MAIN ---
279// -----------------------------------------------------------------------
280int main()
281{
282 if (init())
283 return log(1, "Error in init() \n");
284 if (run())
285 return log(1, "Error in run() \n");
286 if (done())
287 return log(1, "Error in done() \n");
288
289 return log(0,"--- Terminated normally ! \n");;
290}
And here's the vertex shader : 1#version 110
2
3
4
5uniform sampler2D tex; // 0
6uniform float dt;
7uniform vec2 mouse; // Mouse position
8uniform vec2 dim;
9uniform float radius;
10uniform bool warp;
11
12void main()
13{
14 vec2 uv = gl_TexCoord[0].xy;
15 if (warp) {
16 /// gl_FragColor = texture2D(tex , uv);
17
18 vec2 uvP = vec2(uv.x*dim.x , uv.y*dim.y);
19
20 vec2 dist = mouse - uvP;
21 float theta = atan(dist.y , dist.x);
22 /// dist += (dist / (1.0 + (1.0 + cos(dist*dt/300.0))/2.0));
23 float d = distance(dist , vec2(0.0,0.0));
24
25 if ((d < (radius + 50.0)) && (d > (radius - 50.0))) {
26 float diff = d - radius;
27 diff = sin((diff + 50.0)*3.14159265*2.0/100.0);
28 dist /= diff;
29 uv = uv + vec2(dist.x/dim.x , dist.y/dim.y);
30 }
31
32
33 /// dist /= (1.0 + (1.0 + cos(dist*dt/300.0))/2.0);
34 }
35 gl_FragColor = texture2D(tex , uv);
36// dist = dist*(1.0f + .25*sin(dt));
37// float theta = atan(mouse.y - uv.y , mouse.x - uv.x);
38// uv = uv + dist*vec2(cos(theta) , sin(theta));
39}
40
41
42/**
43void main()
44{
45 vec2 uv = gl_TexCoord[0].xy;
46
47 vec2 texPixel = vec2(uv.x*dim.x , uv.y*dim.y);
48
49 vec2 position = center/surface;
50
51 position = vec2(position.x*dim.x , position.y*dim.y);
52
53 float dist = distance(texPixel, position);
54
55 vec2 diff = position - texPixel;
56 float theta = atan(diff.y , diff.x);
57
58 texPixel = uv + vec2(dist*cos(theta) , dist*sin(theta));
59 texPixel = vec2(texPixel.x/dim.x , texPixel.y/dim.y);
60 if ((dist <= (radius + shockParams.z)) && (dist >= (radius - shockParams.z)) )
61 {
62 float diff = (dist - radius);
63 float powDiff = 1.0 - pow(abs(diff*shockParams.x), shockParams.y);
64 float diffTime = diff * powDiff;
65 vec2 diffUV = normalize(uv - position);
66 texCoord = uv + (diffUV * diffTime);
67 }
68 gl_FragColor = texture2D(tex, texPixel);
69}
70
71//*/
EDIT Download a zip of the source and image and executables here ! My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Rodolfo Lam
Member #16,045
August 2015
|
This might be a very good example on the usage of the shaders and the programable pipeline in allegro. Nice job!
|
|