10 #define BG_FILENAME "data/grise.png"
13 #define MAX_SCROLL (backgroundW - fb_width - MIN_SCROLL)
15 #define FAR_SCROLL_SPEED 50.0f
16 #define NEAR_SCROLL_SPEED 400.0f
18 #define HORIZON_HEIGHT 100
19 #define REFLECTION_HEIGHT (240 - HORIZON_HEIGHT)
21 #define NORMALMAP_SCANLINE 372
23 static int init(void);
24 static void destroy(void);
25 static void start(long trans_time);
26 static void stop(long trans_time);
27 static void draw(void);
29 static void convert32To16(unsigned int *src32, unsigned short *dst16, unsigned int pixelCount);
30 static void processNormal();
31 static void initScrollTables();
32 static void updateScrollTables(float dt);
34 static unsigned short *background = 0;
35 static unsigned int backgroundW = 0;
36 static unsigned int backgroundH = 0;
38 static unsigned int lastFrameTime = 0;
39 static float lastFrameDuration = 0.0f;
41 static short *displacementMap;
43 static float scrollSpeedTable[REFLECTION_HEIGHT];
44 static float scrollTable[REFLECTION_HEIGHT];
45 static int scrollTableRounded[REFLECTION_HEIGHT];
46 static int scrollModTable[REFLECTION_HEIGHT];
48 static struct screen scr = {
57 struct screen *mike_screen(void)
65 if (!(background = img_load_pixels(BG_FILENAME, &backgroundW, &backgroundH, IMG_FMT_RGBA32))) {
66 fprintf(stderr, "failed to load image " BG_FILENAME "\n");
70 /* Convert to 16bpp */
71 convert32To16((unsigned int*)background, background, backgroundW * NORMALMAP_SCANLINE); /* Normalmap will keep its 32 bit color */
80 static void destroy(void)
82 //img_free_pixels(background);
85 static void start(long trans_time)
87 lastFrameTime = time_msec;
90 static void stop(long trans_time)
94 static void draw(void)
96 int scroll = MIN_SCROLL + (MAX_SCROLL - MIN_SCROLL) * mouse_x / fb_width;
97 unsigned short *dst = fb_pixels;
98 unsigned short *src = background + scroll;
104 lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f;
105 lastFrameTime = time_msec;
107 for (scanline = 0; scanline < fb_height; scanline++) {
108 memcpy(dst, src, fb_width * 2);
113 updateScrollTables(lastFrameDuration);
115 dst = (unsigned short*) fb_pixels + HORIZON_HEIGHT * fb_width;
116 src = background + HORIZON_HEIGHT * backgroundW;
117 disp = displacementMap;
118 for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) {
119 for (i = 0; i < fb_width; i++) {
120 d = disp[(i + scrollTableRounded[scanline]) % scrollModTable[scanline]];
121 *dst++ = src[i + scroll + d];
128 /* src and dst can be the same */
129 static void convert32To16(unsigned int *src32, unsigned short *dst16, unsigned int pixelCount) {
133 *dst16++ = ((p << 8) & 0xF800) /* R */
134 | ((p >> 5) & 0x07E0) /* G */
135 | ((p >> 19) & 0x001F); /* B */
140 /* Normal map preprocessing */
141 /* Scale normal with depth and unpack R component (horizontal component) */
142 static void processNormal() {
144 unsigned int *normalmap = (unsigned int*)background;
145 normalmap += NORMALMAP_SCANLINE * backgroundW;
146 unsigned short *dst = normalmap;
147 displacementMap = (short*)dst;
148 short *dst2 = displacementMap;
152 short maxDisplacement = 0;
153 short minDisplacement = 256;
155 for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) {
156 scale = 2.0f - (float)scanline / ((float)REFLECTION_HEIGHT - 1);
157 scrollModTable[scanline] = (int) (backgroundW / scale + 0.5f);
158 for (i = 0; i < backgroundW; i++) {
159 x = (int)(i * scale + 0.5f);
160 if (x < backgroundW) {
161 *dst = (unsigned short)normalmap[x] & 0xFF;
162 if ((short)*dst > maxDisplacement) maxDisplacement = (short)(*dst);
163 if ((short)*dst < minDisplacement) minDisplacement = (short)(*dst);
169 normalmap += backgroundW;
172 if (maxDisplacement == minDisplacement) {
173 printf("Warning: grise normalmap fucked up\n");
177 /* Second pass - subtract half maximum displacement to displace in both directions */
178 for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) {
179 for (i = 0; i < backgroundW; i++) {
180 /* Remember that MIN_SCROLL is the padding around the screen, so ti's the maximum displacement we can get (positive & negative) */
181 *dst2 = 2 * MIN_SCROLL * (*dst2 - minDisplacement) / (maxDisplacement - minDisplacement) - MIN_SCROLL;
187 static void initScrollTables() {
189 float scrollSpeed = FAR_SCROLL_SPEED;
190 float speedIncrement = (NEAR_SCROLL_SPEED - FAR_SCROLL_SPEED) / ((float) (REFLECTION_HEIGHT - 1));
191 for (i = 0; i < REFLECTION_HEIGHT; i++) {
192 scrollSpeedTable[i] = scrollSpeed;
193 scrollSpeed += speedIncrement;
194 scrollTable[i] = 0.0f;
195 scrollTableRounded[i] = 0;
200 static void updateScrollTables(float dt) {
202 for (i = 0; i < REFLECTION_HEIGHT; i++) {
203 scrollTable[i] += scrollSpeedTable[i] * dt;
204 scrollTableRounded[i] = (int)(scrollTable[i] + 0.5f) % scrollModTable[i];