1 /* Bump effect (not moving yet of course, I have many ideas on this to commit before it's ready) */
11 static int init(void);
12 static void destroy(void);
13 static void start(long trans_time);
14 static void draw(void);
16 static struct screen scr = {
29 #define NUM_BIG_LIGHTS 3
30 #define BIG_LIGHT_WIDTH 256
31 #define BIG_LIGHT_HEIGHT BIG_LIGHT_WIDTH
33 #define NUM_PARTICLES 64
34 #define PARTICLE_LIGHT_WIDTH 32
35 #define PARTICLE_LIGHT_HEIGHT 32
38 static unsigned long startingTime;
40 static unsigned char *heightmap;
41 static unsigned short *lightmap;
42 static int *bumpOffset;
44 static unsigned short *bigLight[NUM_BIG_LIGHTS];
45 static struct point bigLightPoint[NUM_BIG_LIGHTS];
47 static unsigned short *particleLight;
48 static struct point particlePoint[NUM_PARTICLES];
50 struct screen *bump_screen(void)
57 int i, j, x, y, c, r, g, b;
59 const int numBlurs = 3;
60 const int lightRadius = BIG_LIGHT_WIDTH / 2;
61 const int particleRadius = PARTICLE_LIGHT_WIDTH / 2;
63 const int bigLightSize = BIG_LIGHT_WIDTH * BIG_LIGHT_HEIGHT;
64 const int particleLightSize = PARTICLE_LIGHT_WIDTH * PARTICLE_LIGHT_HEIGHT;
65 const int fb_size = FB_WIDTH * FB_HEIGHT;
67 /* Just some parameters to temporary test the colors of 3 lights
68 * if every light uses it's own channel bits, it's better
70 const float rgbMul[9] = { 1.0f, 0.0f, 0.0f,
74 heightmap = malloc(sizeof(*heightmap) * fb_size);
75 lightmap = malloc(sizeof(*lightmap) * fb_size);
76 bumpOffset = malloc(sizeof(*bumpOffset) * fb_size);
78 for (i = 0; i < NUM_BIG_LIGHTS; i++)
79 bigLight[i] = malloc(sizeof(*bigLight[i]) * bigLightSize);
81 particleLight = malloc(sizeof(*particleLight) * particleLightSize);
83 memset(lightmap, 0, sizeof(*lightmap) * fb_size);
84 memset(bumpOffset, 0, sizeof(*bumpOffset) * fb_size);
85 memset(particlePoint, 0, sizeof(*particlePoint) * NUM_PARTICLES);
87 /* Create random junk */
88 for (i = 0; i < fb_size; i++)
89 heightmap[i] = rand() & 255;
92 for (j = 0; j < numBlurs; j++)
93 for (i = 0; i < fb_size; i++)
94 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;
96 /* Inclination precalculation */
98 for (y = 0; y < FB_HEIGHT; y++)
100 for (x = 0; x < FB_WIDTH; x++)
102 const float offsetPower = 0.75f;
105 dx = i < fb_size - 1 ? (int)((heightmap[i] - heightmap[i + 1]) * offsetPower) : 0;
106 dy = i < fb_size - FB_WIDTH ? (int)((heightmap[i] - heightmap[i + FB_WIDTH]) * offsetPower) : 0;
110 if (xp > FB_WIDTH - 1) xp = FB_WIDTH - 1;
114 if (yp > FB_HEIGHT - 1) yp = FB_HEIGHT - 1;
116 bumpOffset[i++] = yp * FB_WIDTH + xp;
120 /* Generate three lights */
122 for (y = 0; y < BIG_LIGHT_HEIGHT; y++)
124 int yc = y - (BIG_LIGHT_HEIGHT / 2);
125 for (x = 0; x < BIG_LIGHT_WIDTH; x++)
127 int xc = x - (BIG_LIGHT_WIDTH / 2);
128 float d = (float)sqrt(xc * xc + yc * yc);
129 float invDist = ((float)lightRadius - (float)sqrt(xc * xc + yc * yc)) / (float)lightRadius;
130 if (invDist < 0.0f) invDist = 0.0f;
132 c = (int)(invDist * 63);
137 for (j = 0; j < NUM_BIG_LIGHTS; j++)
139 bigLight[j][i] = ((int)(r * rgbMul[j * 3]) << 11) | ((int)(g * rgbMul[j * 3 + 1]) << 5) | (int)(b * rgbMul[j * 3 + 2]);
146 for (y = 0; y < PARTICLE_LIGHT_HEIGHT; y++)
148 int yc = y - (PARTICLE_LIGHT_HEIGHT / 2);
149 for (x = 0; x < PARTICLE_LIGHT_WIDTH; x++)
151 int xc = x - (PARTICLE_LIGHT_WIDTH / 2);
153 float invDist = ((float)particleRadius - (float)sqrt(xc * xc + yc * yc)) / (float)particleRadius;
154 if (invDist < 0.0f) invDist = 0.0f;
156 c = (int)(pow(invDist, 0.75f) * 63);
157 particleLight[i++] = ((c >> 1) << 11) | (c << 5) | (c >> 1);
164 static void destroy(void)
168 static void start(long trans_time)
170 startingTime = time_msec;
173 static void eraseArea(struct point *p, int width, int height)
180 int x1 = p->x + width;
181 int y1 = p->y + height;
185 if (x1 > FB_WIDTH) x1 = FB_WIDTH;
186 if (y1 > FB_HEIGHT) y1 = FB_HEIGHT;
190 dst = lightmap + y0 * FB_WIDTH + x0;
192 for (y = y0; y < y1; y++)
194 for (x = x0; x < x1; x++)
198 dst += FB_WIDTH - dx;
203 static void renderLight(struct point *p, int width, int height, unsigned short *light)
206 unsigned short *src, *dst;
210 int x1 = p->x + width;
211 int y1 = p->y + height;
228 if (x1 > FB_WIDTH) x1 = FB_WIDTH;
229 if (y1 > FB_HEIGHT) y1 = FB_HEIGHT;
233 dst = lightmap + y0 * FB_WIDTH + x0;
234 src = light + yl * width + xl;
236 for (y = y0; y < y1; y++)
238 for (x = x0; x < x1; x++)
242 dst += FB_WIDTH - dx;
247 static void eraseLights()
250 for (i = 0; i < NUM_BIG_LIGHTS; i++)
251 eraseArea(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT);
254 static void renderLights()
257 for (i = 0; i < NUM_BIG_LIGHTS; i++)
258 renderLight(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT, bigLight[i]);
261 static void renderParticles()
264 for (i = 0; i < NUM_PARTICLES; i++)
265 renderLight(&particlePoint[i], PARTICLE_LIGHT_WIDTH, PARTICLE_LIGHT_HEIGHT, particleLight);
268 static void animateLights()
271 float dt = (float)(time_msec - startingTime) / 1000.0f;
272 float tt = 1.0f - sin(dt);
273 float disperse = tt * 64.0f;
275 center.x = (FB_WIDTH >> 1) - (BIG_LIGHT_WIDTH / 2);
276 center.y = (FB_HEIGHT >> 1) - (BIG_LIGHT_HEIGHT / 2);
278 bigLightPoint[0].x = center.x + sin(1.2f * dt) * (144.0f + disperse);
279 bigLightPoint[0].y = center.y + sin(0.8f * dt) * (148.0f + disperse);
281 bigLightPoint[1].x = center.x + sin(1.5f * dt) * (156.0f + disperse);
282 bigLightPoint[1].y = center.y + sin(1.1f * dt) * (92.0f + disperse);
284 bigLightPoint[2].x = center.x + sin(2.0f * dt) * (112.0f + disperse);
285 bigLightPoint[2].y = center.y + sin(1.3f * dt) * (136.0f + disperse);
288 static void renderBump(unsigned short *vram)
291 for (i = 0; i < FB_WIDTH * FB_HEIGHT; i++)
293 unsigned short c = lightmap[bumpOffset[i]];
298 static void animateParticles()
302 float dt = (float)(time_msec - startingTime) / 2000.0f;
305 center.x = (FB_WIDTH >> 1) - (PARTICLE_LIGHT_WIDTH / 2);
306 center.y = (FB_HEIGHT >> 1) - (PARTICLE_LIGHT_HEIGHT / 2);
308 for (i = 0; i < NUM_PARTICLES; i++)
310 particlePoint[i].x = center.x + (sin(1.2f * (i*i*i + dt)) * 74.0f + sin(0.6f * (i + dt)) * 144.0f) * tt;
311 particlePoint[i].y = center.y + (sin(1.8f * (i + dt)) * 68.0f + sin(0.5f * (i*i + dt)) * 132.0f) * tt;
315 static void draw(void)
317 memset(lightmap, 0, FB_WIDTH * FB_HEIGHT * sizeof(*lightmap));
326 renderBump((unsigned short*)fb_pixels);