removed empty stop functions from bump and plasma to avoid delaying the
[dosdemo] / src / bump.c
1 // Bump effect (not moving yet of course, I have many ideas on this to commit before it's ready)
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <math.h>
7
8 #include "demo.h"
9 #include "screen.h"
10 #include "tinyfps.h"
11
12 static int init(void);
13 static void destroy(void);
14 static void start(long trans_time);
15 static void draw(void);
16
17 static struct screen scr = {
18         "bump",
19         init,
20         destroy,
21         start,
22         0,
23         draw
24 };
25
26 struct point {
27         int x, y;
28 };
29
30 #define NUM_BIG_LIGHTS 3
31 #define BIG_LIGHT_WIDTH 256
32 #define BIG_LIGHT_HEIGHT BIG_LIGHT_WIDTH
33
34 static unsigned long startingTime;
35
36 static unsigned char *heightmap;
37 static unsigned short *lightmap;
38 static int *bumpOffset;
39
40 static unsigned short *bigLight[NUM_BIG_LIGHTS];
41 static struct point bigLightPoint[NUM_BIG_LIGHTS];
42
43 struct screen *bump_screen(void)
44 {
45         return &scr;
46 }
47
48 static int init(void)
49 {
50         int i, j, x, y, c, r, g, b;
51
52         const int numBlurs = 3;
53         const int lightRadius = BIG_LIGHT_WIDTH / 2;
54
55         const int bigLightSize = BIG_LIGHT_WIDTH * BIG_LIGHT_HEIGHT;
56         const int fb_size = fb_width * fb_height;
57
58         // Just some parameters to temporary test the colors of 3 lights
59         // if every light uses it's own channel bits, it's better
60         const float rgbMul[9] = { 1.0f, 0.0f, 0.0f, 
61                                                                   0.0f, 1.0f, 0.0f,
62                                                                   0.0f, 0.0f, 1.0f};
63         initFpsFonts();
64
65         heightmap = malloc(sizeof(*heightmap) * fb_size);
66         lightmap = malloc(sizeof(*lightmap) * fb_size);
67         bumpOffset = malloc(sizeof(*bumpOffset) * fb_size);
68
69         for (i = 0; i < NUM_BIG_LIGHTS; i++)
70                 bigLight[i] = malloc(sizeof(*bigLight[i]) * bigLightSize);
71
72         memset(lightmap, 0, sizeof(*lightmap) * fb_size);
73         memset(bumpOffset, 0, sizeof(*bumpOffset) * fb_size);
74
75         // Create random junk
76         for (i = 0; i < fb_size; i++)
77                 heightmap[i] = rand() & 255;
78
79         // Blur to smooth
80         for (j = 0; j < numBlurs; j++)
81                 for (i = 0; i < fb_size; i++)
82                         heightmap[i] = (heightmap[abs((i - 1) % fb_size)] + heightmap[abs((i + 1) % fb_size)] + heightmap[abs((i - fb_width) % fb_size)] + heightmap[abs((i + fb_width) % fb_size)]) >> 2;
83
84         // Inclination precalculation
85         i = 0;
86         for (y = 0; y < fb_height; y++)
87         {
88                 for (x = 0; x < fb_width; x++)
89                 {
90                         const float offsetPower = 2.0f;
91                         int dx, dy, xp, yp;
92
93                         dx = i < fb_size - 1 ? (int)((heightmap[i] - heightmap[i + 1]) * offsetPower) : 0;
94                         dy = i < fb_size - fb_width ? (int)((heightmap[i] - heightmap[i + fb_width]) * offsetPower) : 0;
95
96                         xp = x + dx;
97                         if (xp < 0) xp = 0;
98                         if (xp > fb_width - 1) xp = fb_width - 1;
99
100                         yp = y + dy;
101                         if (yp < 0) yp = 0;
102                         if (yp > fb_height - 1) yp = fb_height - 1;
103
104                         bumpOffset[i++] = yp * fb_width + xp;
105                 }
106         }
107
108         // Generate three lights
109         i = 0;
110         for (y = 0; y < BIG_LIGHT_HEIGHT; y++)
111         {
112                 int yc = y - (BIG_LIGHT_HEIGHT / 2);
113                 for (x = 0; x < BIG_LIGHT_WIDTH; x++)
114                 {
115                         int xc = x - (BIG_LIGHT_WIDTH / 2);
116                         float d = (float)sqrt(xc * xc + yc * yc);
117                         float invDist = ((float)lightRadius - (float)sqrt(xc * xc + yc * yc)) / (float)lightRadius;
118                         if (invDist < 0.0f) invDist = 0.0f;
119
120                         c = (int)(invDist * 63);
121                         r = c >> 1;
122                         g = c;
123                         b = c >> 1;
124
125                         for (j = 0; j < NUM_BIG_LIGHTS; j++)
126                         {
127                                 bigLight[j][i] = ((int)(r * rgbMul[j * 3]) << 11) | ((int)(g * rgbMul[j * 3 + 1]) << 5) | (int)(b * rgbMul[j * 3 + 2]);
128                         }
129                         i++;
130                 }
131         }
132
133         return 0;
134 }
135
136 static void destroy(void)
137 {
138 }
139
140 static void start(long trans_time)
141 {
142         startingTime = time_msec;
143 }
144
145 static void eraseArea(struct point *p, int width, int height)
146 {
147         int x, y, dx;
148         unsigned short *dst;
149
150         int x0 = p->x;
151         int y0 = p->y;
152         int x1 = p->x + width;
153         int y1 = p->y + height;
154
155         if (x0 < 0) x0 = 0;
156         if (y0 < 0) y0 = 0;
157         if (x1 > fb_width) x1 = fb_width;
158         if (y1 > fb_height) y1 = fb_height;
159
160         dx = x1 - x0;
161
162         dst = lightmap + y0 * fb_width + x0;
163
164         for (y = y0; y < y1; y++)
165         {
166                 for (x = x0; x < x1; x++)
167                 {
168                         *dst++ = 0;
169                 }
170                 dst += fb_width - dx;
171         }
172 }
173
174
175 static void renderLight(struct point *p, int width, int height, unsigned short *light)
176 {
177         int x, y, dx;
178         unsigned short *src, *dst;
179
180         int x0 = p->x;
181         int y0 = p->y;
182         int x1 = p->x + width;
183         int y1 = p->y + height;
184
185         int xl = 0;
186         int yl = 0;
187
188         if (x0 < 0)
189         {
190                 xl = -x0;
191                 x0 = 0;
192         }
193
194         if (y0 < 0)
195         {
196                 yl = -y0;
197                 y0 = 0;
198         }
199
200         if (x1 > fb_width) x1 = fb_width;
201         if (y1 > fb_height) y1 = fb_height;
202
203         dx = x1 - x0;
204
205         dst = lightmap + y0 * fb_width + x0;
206         src = light + yl * width + xl;
207
208         for (y = y0; y < y1; y++)
209         {
210                 for (x = x0; x < x1; x++)
211                 {
212                         *dst++ |= *src++;
213                 }
214                 dst += fb_width - dx;
215                 src += width - dx;
216         }
217 }
218
219 static void eraseLights()
220 {
221         int i;
222         for (i = 0; i < NUM_BIG_LIGHTS; i++)
223                 eraseArea(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT);
224 }
225
226 static void renderLights()
227 {
228         int i;
229         for (i = 0; i < NUM_BIG_LIGHTS; i++)
230                 renderLight(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT, bigLight[i]);
231 }
232
233 static void animateLights()
234 {
235         struct point center;
236         float dt = (float)(time_msec - startingTime) / 1000.0f;
237
238         center.x = (fb_width >> 1) - (BIG_LIGHT_WIDTH / 2);
239         center.y = (fb_height >> 1) - (BIG_LIGHT_HEIGHT / 2);
240
241         bigLightPoint[0].x = center.x + sin(1.2f * dt) * 144.0f;
242         bigLightPoint[0].y = center.y + sin(0.8f * dt) * 148.0f;
243
244         bigLightPoint[1].x = center.x + sin(1.5f * dt) * 156.0f;
245         bigLightPoint[1].y = center.y + sin(1.1f * dt) * 92.0f;
246
247         bigLightPoint[2].x = center.x + sin(2.0f * dt) * 112.0f;
248         bigLightPoint[2].y = center.y + sin(1.3f * dt) * 136.0f;
249 }
250
251 static void renderBump(unsigned short *vram)
252 {
253         int i;
254         for (i = 0; i < fb_width * fb_height; i++)
255         {
256                 unsigned short c = lightmap[bumpOffset[i]];
257                 *vram++ = c;
258         }
259 }
260
261 static void draw(void)
262 {
263         eraseLights();
264         animateLights();
265         renderLights();
266         renderBump((unsigned short*)vmem_back);
267
268         drawFps((unsigned short*)vmem_back);
269
270         swap_buffers(0);
271 }