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
69 const float rgbMul[9] = { 1.0f, 0.0f, 0.0f,
73 heightmap = malloc(sizeof(*heightmap) * fb_size);
74 lightmap = malloc(sizeof(*lightmap) * fb_size);
75 bumpOffset = malloc(sizeof(*bumpOffset) * fb_size);
77 for (i = 0; i < NUM_BIG_LIGHTS; i++)
78 bigLight[i] = malloc(sizeof(*bigLight[i]) * bigLightSize);
80 particleLight = malloc(sizeof(*particleLight) * particleLightSize);
82 memset(lightmap, 0, sizeof(*lightmap) * fb_size);
83 memset(bumpOffset, 0, sizeof(*bumpOffset) * fb_size);
84 memset(particlePoint, 0, sizeof(*particlePoint) * NUM_PARTICLES);
87 for (i = 0; i < fb_size; i++)
88 heightmap[i] = rand() & 255;
91 for (j = 0; j < numBlurs; j++)
92 for (i = 0; i < fb_size; i++)
93 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;
95 // Inclination precalculation
97 for (y = 0; y < fb_height; y++)
99 for (x = 0; x < fb_width; x++)
101 const float offsetPower = 0.75f;
104 dx = i < fb_size - 1 ? (int)((heightmap[i] - heightmap[i + 1]) * offsetPower) : 0;
105 dy = i < fb_size - fb_width ? (int)((heightmap[i] - heightmap[i + fb_width]) * offsetPower) : 0;
109 if (xp > fb_width - 1) xp = fb_width - 1;
113 if (yp > fb_height - 1) yp = fb_height - 1;
115 bumpOffset[i++] = yp * fb_width + xp;
119 // Generate three lights
121 for (y = 0; y < BIG_LIGHT_HEIGHT; y++)
123 int yc = y - (BIG_LIGHT_HEIGHT / 2);
124 for (x = 0; x < BIG_LIGHT_WIDTH; x++)
126 int xc = x - (BIG_LIGHT_WIDTH / 2);
127 float d = (float)sqrt(xc * xc + yc * yc);
128 float invDist = ((float)lightRadius - (float)sqrt(xc * xc + yc * yc)) / (float)lightRadius;
129 if (invDist < 0.0f) invDist = 0.0f;
131 c = (int)(invDist * 63);
136 for (j = 0; j < NUM_BIG_LIGHTS; j++)
138 bigLight[j][i] = ((int)(r * rgbMul[j * 3]) << 11) | ((int)(g * rgbMul[j * 3 + 1]) << 5) | (int)(b * rgbMul[j * 3 + 2]);
145 for (y = 0; y < PARTICLE_LIGHT_HEIGHT; y++)
147 int yc = y - (PARTICLE_LIGHT_HEIGHT / 2);
148 for (x = 0; x < PARTICLE_LIGHT_WIDTH; x++)
150 int xc = x - (PARTICLE_LIGHT_WIDTH / 2);
152 float invDist = ((float)particleRadius - (float)sqrt(xc * xc + yc * yc)) / (float)particleRadius;
153 if (invDist < 0.0f) invDist = 0.0f;
155 c = (int)(pow(invDist, 0.75f) * 63);
156 particleLight[i++] = ((c >> 1) << 11) | (c << 5) | (c >> 1);
163 static void destroy(void)
167 static void start(long trans_time)
169 startingTime = time_msec;
172 static void eraseArea(struct point *p, int width, int height)
179 int x1 = p->x + width;
180 int y1 = p->y + height;
184 if (x1 > fb_width) x1 = fb_width;
185 if (y1 > fb_height) y1 = fb_height;
189 dst = lightmap + y0 * fb_width + x0;
191 for (y = y0; y < y1; y++)
193 for (x = x0; x < x1; x++)
197 dst += fb_width - dx;
202 static void renderLight(struct point *p, int width, int height, unsigned short *light)
205 unsigned short *src, *dst;
209 int x1 = p->x + width;
210 int y1 = p->y + height;
227 if (x1 > fb_width) x1 = fb_width;
228 if (y1 > fb_height) y1 = fb_height;
232 dst = lightmap + y0 * fb_width + x0;
233 src = light + yl * width + xl;
235 for (y = y0; y < y1; y++)
237 for (x = x0; x < x1; x++)
241 dst += fb_width - dx;
246 static void eraseLights()
249 for (i = 0; i < NUM_BIG_LIGHTS; i++)
250 eraseArea(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT);
253 static void renderLights()
256 for (i = 0; i < NUM_BIG_LIGHTS; i++)
257 renderLight(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT, bigLight[i]);
260 static void renderParticles()
263 for (i = 0; i < NUM_PARTICLES; i++)
264 renderLight(&particlePoint[i], PARTICLE_LIGHT_WIDTH, PARTICLE_LIGHT_HEIGHT, particleLight);
267 static void animateLights()
270 float dt = (float)(time_msec - startingTime) / 1000.0f;
271 float tt = 1.0f - sin(dt);
272 float disperse = tt * 64.0f;
274 center.x = (fb_width >> 1) - (BIG_LIGHT_WIDTH / 2);
275 center.y = (fb_height >> 1) - (BIG_LIGHT_HEIGHT / 2);
277 bigLightPoint[0].x = center.x + sin(1.2f * dt) * (144.0f + disperse);
278 bigLightPoint[0].y = center.y + sin(0.8f * dt) * (148.0f + disperse);
280 bigLightPoint[1].x = center.x + sin(1.5f * dt) * (156.0f + disperse);
281 bigLightPoint[1].y = center.y + sin(1.1f * dt) * (92.0f + disperse);
283 bigLightPoint[2].x = center.x + sin(2.0f * dt) * (112.0f + disperse);
284 bigLightPoint[2].y = center.y + sin(1.3f * dt) * (136.0f + disperse);
287 static void renderBump(unsigned short *vram)
290 for (i = 0; i < fb_width * fb_height; i++)
292 unsigned short c = lightmap[bumpOffset[i]];
297 static void animateParticles()
301 float dt = (float)(time_msec - startingTime) / 2000.0f;
304 center.x = (fb_width >> 1) - (PARTICLE_LIGHT_WIDTH / 2);
305 center.y = (fb_height >> 1) - (PARTICLE_LIGHT_HEIGHT / 2);
307 for (i = 0; i < NUM_PARTICLES; i++)
309 particlePoint[i].x = center.x + (sin(1.2f * (i*i*i + dt)) * 74.0f + sin(0.6f * (i + dt)) * 144.0f) * tt;
310 particlePoint[i].y = center.y + (sin(1.8f * (i + dt)) * 68.0f + sin(0.5f * (i*i + dt)) * 132.0f) * tt;
314 static void draw(void)
316 memset(lightmap, 0, fb_width * fb_height * sizeof(*lightmap));
325 renderBump((unsigned short*)vmem_back);