1 // Bump effect (not moving yet of course, I have many ideas on this to commit before it's ready)
12 static int init(void);
13 static void destroy(void);
14 static void start(long trans_time);
15 static void stop(long trans_time);
16 static void draw(void);
18 static struct screen scr = {
31 #define LIGHT_WIDTH 128
32 #define LIGHT_HEIGHT LIGHT_WIDTH
34 static unsigned long startingTime;
36 static unsigned char *heightmap;
37 static unsigned short *lightmap;
38 static int *bumpOffset;
40 static unsigned short *lightR;
41 static unsigned short *lightG;
42 static unsigned short *lightB;
43 static struct point pointR, pointG, pointB;
45 //#define FUNKY_COLORS
48 struct screen *bump_screen(void)
55 int i, j, x, y, c, r, g, b;
57 const int numBlurs = 3;
58 const int lightRadius = LIGHT_WIDTH / 2;
60 const int lightSize = LIGHT_WIDTH * LIGHT_HEIGHT;
61 const int fb_size = fb_width * fb_height;
63 // Just some parameters to temporary test the colors of 3 lights
65 // I see some artifacts if I mix channels, not sure if ORing is fine
66 const float r0 = 1.0f, g0 = 0.6f, b0 = 0.0f;
67 const float r1 = 0.5f, g1 = 1.0f, b1 = 0.2f;
68 const float r2 = 0.6f, g2 = 0.4f, b2 = 1.0f;
70 // if every light uses it's own channel bits, it's better
71 const float r0 = 1.0f, g0 = 0.0f, b0 = 0.0f;
72 const float r1 = 0.0f, g1 = 1.0f, b1 = 0.0f;
73 const float r2 = 0.0f, g2 = 0.0f, b2 = 1.0f;
78 heightmap = malloc(sizeof(*heightmap) * fb_size);
79 lightmap = malloc(sizeof(*lightmap) * fb_size);
80 bumpOffset = malloc(sizeof(*bumpOffset) * fb_size);
82 lightR = malloc(sizeof(*lightR) * lightSize);
83 lightG = malloc(sizeof(*lightG) * lightSize);
84 lightB = malloc(sizeof(*lightB) * lightSize);
86 memset(lightmap, 0, sizeof(*lightmap) * fb_size);
87 memset(bumpOffset, 0, sizeof(*bumpOffset) * fb_size);
90 for (i = 0; i < fb_size; i++)
91 heightmap[i] = rand() & 255;
94 for (j = 0; j < numBlurs; j++)
95 for (i = 0; i < fb_size; i++)
96 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;
98 // Inclination precalculation
100 for (y = 0; y < fb_height; y++)
102 for (x = 0; x < fb_width; x++)
104 const float offsetPower = 2.0f;
107 dx = (int)((heightmap[i] - heightmap[i + 1]) * offsetPower);
108 dy = (int)((heightmap[i] - heightmap[i + fb_width]) * offsetPower);
112 if (xp > fb_width - 1) xp = fb_width - 1;
116 if (yp > fb_height - 1) yp = fb_height - 1;
118 bumpOffset[i++] = yp * fb_width + xp;
122 // Generate three lights
124 for (y = 0; y < LIGHT_HEIGHT; y++)
126 int yc = y - (LIGHT_HEIGHT / 2);
127 for (x = 0; x < LIGHT_WIDTH; x++)
129 int xc = x - (LIGHT_WIDTH / 2);
130 float d = (float)sqrt(xc * xc + yc * yc);
131 float invDist = ((float)lightRadius - (float)sqrt(xc * xc + yc * yc)) / (float)lightRadius;
132 if (invDist < 0.0f) invDist = 0.0f;
134 c = (int)(invDist * 63);
139 lightR[i] = ((int)(r * r0) << 11) | ((int)(g * g0) << 5) | (int)(b * b0);
140 lightG[i] = ((int)(r * r1) << 11) | ((int)(g * g1) << 5) | (int)(b * b1);
141 lightB[i] = ((int)(r * r2) << 11) | ((int)(g * g2) << 5) | (int)(b * b2);
149 static void destroy(void)
153 static void start(long trans_time)
155 startingTime = time_msec;
158 static void stop(long trans_time)
162 static void eraseArea(struct point *p, int width, int height)
169 int x1 = p->x + width;
170 int y1 = p->y + height;
176 if (x1 > fb_width) x1 = fb_width;
177 if (y1 > fb_height) y1 = fb_height;
182 dst = (unsigned short*)lightmap + y0 * fb_width + x0;
184 for (y = y0; y < y1; y++)
186 for (x = x0; x < x1; x++)
190 dst += fb_width - dx;
195 static void renderLight(struct point *p, int width, int height, unsigned short *light)
197 // Check for boundaries is missing atm, will add soon
199 unsigned short *dst = (unsigned short*)lightmap + p->y * fb_width + p->x;
200 for (y = 0; y < height; y++)
202 for (x = 0; x < width; x++)
206 dst += fb_width - width;
210 static void eraseLights()
212 eraseArea(&pointR, LIGHT_WIDTH, LIGHT_HEIGHT);
213 eraseArea(&pointG, LIGHT_WIDTH, LIGHT_HEIGHT);
214 eraseArea(&pointB, LIGHT_WIDTH, LIGHT_HEIGHT);
217 static void renderLights()
219 renderLight(&pointR, LIGHT_WIDTH, LIGHT_HEIGHT, lightR);
220 renderLight(&pointG, LIGHT_WIDTH, LIGHT_HEIGHT, lightG);
221 renderLight(&pointB, LIGHT_WIDTH, LIGHT_HEIGHT, lightB);
224 static void animateLights()
227 float dt = (float)(time_msec - startingTime) / 1000.0f;
229 center.x = (fb_width >> 1) - (LIGHT_WIDTH / 2);
230 center.y = (fb_height >> 1) - (LIGHT_HEIGHT / 2);
232 // This test condition will crash because I also need to add boundaries to renderLight (tomorrow)
233 //pointR.x = center.x + sin(1.2f * dt) * 144.0f;
234 //pointR.y = center.y + sin(0.8f * dt) * 148.0f;
236 pointR.x = center.x + sin(1.2f * dt) * 96.0f;
237 pointR.y = center.y + sin(0.8f * dt) * 48.0f;
239 pointG.x = center.x + sin(1.5f * dt) * 56.0f;
240 pointG.y = center.y + sin(1.1f * dt) * 42.0f;
242 pointB.x = center.x + sin(2.0f * dt) * 80.0f;
243 pointB.y = center.y + sin(1.3f * dt) * 46.0f;
246 static void renderBump(unsigned short *vram)
249 for (i = 0; i < fb_width * fb_height; i++)
251 unsigned short c = lightmap[bumpOffset[i]];
256 static void draw(void)
261 renderBump((unsigned short*)vmem_back);
263 drawFps((unsigned short*)vmem_back);