X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fmike.c;h=ed995d9d6ac4211e4d2ab948541ac5cca7c4a5c2;hb=e75a1243556f063851a5adf9cb2e1a00878c4365;hp=fda18fee5e0da1fad2928a8d995e66ae95160d50;hpb=95e7797c2bb32a62fada629877a75b86bcf1aba9;p=dosdemo diff --git a/src/mike.c b/src/mike.c index fda18fe..ed995d9 100644 --- a/src/mike.c +++ b/src/mike.c @@ -7,9 +7,16 @@ #include "demo.h" #include "screen.h" +/* APPROX. 170 FPS Minimum */ + #define BG_FILENAME "data/grise.png" -#define MIN_SCROLL 32 +#define BB_SIZE 512 /* Let's use a power of 2. Maybe we'll zoom/rotate the effect */ + +/* Every backBuffer scanline is guaranteed to have that many dummy pixels before and after */ +#define PIXEL_PADDING 32 + +#define MIN_SCROLL PIXEL_PADDING #define MAX_SCROLL (backgroundW - fb_width - MIN_SCROLL) #define FAR_SCROLL_SPEED 50.0f @@ -40,10 +47,13 @@ static float lastFrameDuration = 0.0f; static short *displacementMap; -static float scrollSpeedTable[REFLECTION_HEIGHT]; +static unsigned short *backBuffer; + +static float scrollScaleTable[REFLECTION_HEIGHT]; static float scrollTable[REFLECTION_HEIGHT]; static int scrollTableRounded[REFLECTION_HEIGHT]; static int scrollModTable[REFLECTION_HEIGHT]; +static float nearScrollAmount = 0.0f; static struct screen scr = { "mike", @@ -62,6 +72,9 @@ struct screen *mike_screen(void) static int init(void) { + /* Allocate back buffer */ + backBuffer = (unsigned short*) malloc(BB_SIZE * BB_SIZE * sizeof(unsigned short)); + if (!(background = img_load_pixels(BG_FILENAME, &backgroundW, &backgroundH, IMG_FMT_RGBA32))) { fprintf(stderr, "failed to load image " BG_FILENAME "\n"); return -1; @@ -70,16 +83,23 @@ static int init(void) /* Convert to 16bpp */ convert32To16((unsigned int*)background, background, backgroundW * NORMALMAP_SCANLINE); /* Normalmap will keep its 32 bit color */ - processNormal(); - initScrollTables(); + processNormal(); + +#ifdef MIKE_PC + return 0xCAFE; +#else return 0; +#endif } static void destroy(void) { - //img_free_pixels(background); + free(backBuffer); + backBuffer = 0; + + img_free_pixels(background); } static void start(long trans_time) @@ -94,34 +114,47 @@ static void stop(long trans_time) static void draw(void) { int scroll = MIN_SCROLL + (MAX_SCROLL - MIN_SCROLL) * mouse_x / fb_width; - unsigned short *dst = fb_pixels; + unsigned short *dst = backBuffer + PIXEL_PADDING; unsigned short *src = background + scroll; int scanline = 0; int i = 0; - short *disp; + short *dispScanline; int d; lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f; lastFrameTime = time_msec; - for (scanline = 0; scanline < fb_height; scanline++) { + /* First, render the horizon */ + for (scanline = 0; scanline < HORIZON_HEIGHT; scanline++) { memcpy(dst, src, fb_width * 2); src += backgroundW; - dst += fb_width; + dst += BB_SIZE; } + /* Create scroll opffsets for all scanlines of the normalmap */ updateScrollTables(lastFrameDuration); - dst = (unsigned short*) fb_pixels + HORIZON_HEIGHT * fb_width; + /* Then, render the reflection under the horizon */ + /* dst is already in place */ src = background + HORIZON_HEIGHT * backgroundW; - disp = displacementMap; + dispScanline = displacementMap; for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { for (i = 0; i < fb_width; i++) { - d = disp[(i + scrollTableRounded[scanline]) % scrollModTable[scanline]]; + d = dispScanline[(i + scrollTableRounded[scanline]) % scrollModTable[scanline]]; *dst++ = src[i + scroll + d]; } src += backgroundW; - disp += backgroundW; + dst += BB_SIZE - fb_width; + dispScanline += backgroundW; + } + + /* Blit effect to framebuffer */ + src = backBuffer + PIXEL_PADDING; + dst = fb_pixels; + for (scanline = 0; scanline < fb_height; scanline++) { + memcpy(dst, src, fb_width * 2); + src += BB_SIZE; + dst += fb_width; } } @@ -141,24 +174,24 @@ static void convert32To16(unsigned int *src32, unsigned short *dst16, unsigned i /* Scale normal with depth and unpack R component (horizontal component) */ static void processNormal() { int scanline; - unsigned int *normalmap = (unsigned int*)background; - normalmap += NORMALMAP_SCANLINE * backgroundW; - unsigned short *dst = normalmap; - displacementMap = (short*)dst; - short *dst2 = displacementMap; - float scale; int i; int x; short maxDisplacement = 0; short minDisplacement = 256; + unsigned short *dst; + short *dst2; + unsigned int *normalmap = (unsigned int*)background; + normalmap += NORMALMAP_SCANLINE * backgroundW; + dst = (unsigned short*)normalmap; + displacementMap = (short*)dst; + dst2 = displacementMap; for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) { - scale = 2.0f - (float)scanline / ((float)REFLECTION_HEIGHT - 1); - scrollModTable[scanline] = (int) (backgroundW / scale + 0.5f); + scrollModTable[scanline] = (int) (backgroundW / scrollScaleTable[scanline] + 0.5f); for (i = 0; i < backgroundW; i++) { - x = (int)(i * scale + 0.5f); + x = (int)(i * scrollScaleTable[scanline] + 0.5f); if (x < backgroundW) { - *dst = (unsigned short)normalmap[x] & 0xFF; + *dst = (unsigned short)(normalmap[x] >> 8) & 0xFF; if ((short)*dst > maxDisplacement) maxDisplacement = (short)(*dst); if ((short)*dst < minDisplacement) minDisplacement = (short)(*dst); } else { @@ -179,18 +212,23 @@ static void processNormal() { for (i = 0; i < backgroundW; i++) { /* Remember that MIN_SCROLL is the padding around the screen, so ti's the maximum displacement we can get (positive & negative) */ *dst2 = 2 * MIN_SCROLL * (*dst2 - minDisplacement) / (maxDisplacement - minDisplacement) - MIN_SCROLL; + *dst2 = (short)((float)*dst2 / scrollScaleTable[scanline] + 0.5f); /* Displacements must also scale with distance*/ dst2++; } } } +static float distanceScale(int scanline) { + float farScale, t; + farScale = (float)NEAR_SCROLL_SPEED / (float)FAR_SCROLL_SPEED; + t = (float)scanline / ((float)REFLECTION_HEIGHT - 1); + return 1.0f / (1.0f / farScale + (1.0f - 1.0f / farScale) * t); +} + static void initScrollTables() { int i = 0; - float scrollSpeed = FAR_SCROLL_SPEED; - float speedIncrement = (NEAR_SCROLL_SPEED - FAR_SCROLL_SPEED) / ((float) (REFLECTION_HEIGHT - 1)); for (i = 0; i < REFLECTION_HEIGHT; i++) { - scrollSpeedTable[i] = scrollSpeed; - scrollSpeed += speedIncrement; + scrollScaleTable[i] = distanceScale(i); scrollTable[i] = 0.0f; scrollTableRounded[i] = 0; } @@ -199,8 +237,12 @@ static void initScrollTables() { static void updateScrollTables(float dt) { int i = 0; + + nearScrollAmount += dt * NEAR_SCROLL_SPEED; + nearScrollAmount = (float) fmod(nearScrollAmount, 512.0f); + for (i = 0; i < REFLECTION_HEIGHT; i++) { - scrollTable[i] += scrollSpeedTable[i] * dt; + scrollTable[i] = nearScrollAmount / scrollScaleTable[i]; scrollTableRounded[i] = (int)(scrollTable[i] + 0.5f) % scrollModTable[i]; } -} \ No newline at end of file +}