66c6bbcf79cdbb733f279047d7c75107bf40ac0c
[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 stop(long trans_time);
16 static void draw(void);
17
18 static struct screen scr = {
19         "bump",
20         init,
21         destroy,
22         start,
23         stop,
24         draw
25 };
26
27 static unsigned long startingTime;
28
29 static unsigned char *heightmap;
30 static unsigned short *lightmap;
31 static int *bumpOffset;
32
33 struct screen *bump_screen(void)
34 {
35         return &scr;
36 }
37
38 static int init(void)
39 {
40         const int numBlurs = 3;
41         int i, j, x, y;
42         int fb_size = fb_width * fb_height;
43
44         initFpsFonts();
45
46         heightmap = malloc(sizeof(*heightmap) * fb_size);
47         lightmap = malloc(sizeof(*lightmap) * fb_size);
48         bumpOffset = malloc(sizeof(*bumpOffset) * fb_size);
49
50         memset(lightmap, 0, fb_size);
51         memset(bumpOffset, 0, fb_size);
52
53         // Create random junk
54         for (i = 0; i < fb_size; i++)
55                 heightmap[i] = rand() & 255;
56
57         // Blur to smooth
58         for (j = 0; j < numBlurs; j++)
59                 for (i = 0; i < fb_size; i++)
60                         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;
61
62         // Inclination precalculation
63         i = 0;
64         for (y = 0; y < fb_height; y++)
65         {
66                 for (x = 0; x < fb_width; x++)
67                 {
68                         const float offsetPower = 2.0f;
69                         int dx, dy, xp, yp;
70
71                         dx = (int)((heightmap[i] - heightmap[i + 1]) * offsetPower);
72                         dy = (int)((heightmap[i] - heightmap[i + fb_width]) * offsetPower);
73
74                         xp = x + dx;
75                         if (xp < 0) xp = 0;
76                         if (xp > fb_width - 1) xp = fb_width - 1;
77
78                         yp = y + dy;
79                         if (yp < 0) yp = 0;
80                         if (yp > fb_height - 1) yp = fb_height - 1;
81
82                         bumpOffset[i++] = yp * fb_width + xp;
83                 }
84         }
85
86         // Lightmap test (this will be replaced by code in the main loop later on, the idea is you can render moving lights and other light geometry or sprites in light buffer and the bumpOffset will catch them)
87         i = 0;
88         for (y = 0; y < fb_height; y++)
89         {
90                 int yc = y - (fb_height >> 1);
91                 for (x = 0; x < fb_width; x++)
92                 {
93                         int xc = x - (fb_width >> 1);
94                         int c = (int)sqrt(xc * xc + yc * yc) << 1;
95                         int r;
96                         if (c > 255) c = 255;
97                         r = 255 - c;
98                         lightmap[i++] = ((r >> 4) << 11) | ((r >> 3) << 5) | (r >> 3);
99                 }
100         }
101
102         return 0;
103 }
104
105 static void destroy(void)
106 {
107 }
108
109 static void start(long trans_time)
110 {
111         startingTime = time_msec;
112 }
113
114 static void stop(long trans_time)
115 {
116 }
117
118 static void draw(void)
119 {
120         int i;
121         unsigned short *vram = (unsigned short*)fb_pixels;
122         for (i = 0; i < fb_width * fb_height; i++)
123         {
124                 unsigned short c = lightmap[bumpOffset[i]];
125                 *vram++ = c;
126         }
127
128         drawFps((unsigned short*)fb_pixels);
129
130         swap_buffers(0);
131 }