From: John Tsiombikas Date: Sun, 16 Oct 2022 23:01:04 +0000 (+0300) Subject: interpolation X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=voxscape;a=commitdiff_plain;h=5eeffedb4f25f0513dc1e654ccd5722d814a3ecc interpolation --- diff --git a/src/main.c b/src/main.c index f0c89eb..bcf2250 100644 --- a/src/main.c +++ b/src/main.c @@ -34,6 +34,7 @@ int win_width, win_height; unsigned int fb[FB_W * FB_H]; int mouse_x, mouse_y, mwarp, mbstate[3]; +int hfilt = VOX_LINEAR, cfilt = VOX_LINEAR; unsigned int input; int32_t pos[2], angle; @@ -82,6 +83,7 @@ int init(void) vox_framebuf(vox, FB_W, FB_H, fb, -1); vox_proj(vox, 45, 1, 300); vox_fog(vox, 260, COLOR_HORIZON); + vox_filter(vox, hfilt, cfilt); glfb_setup(FB_W, FB_H, GLFB_RGBA32, FB_W * 4); return 0; @@ -186,6 +188,20 @@ void keyb(unsigned char key, int x, int y) input |= INP_RTURN; break; + case 'h': + hfilt ^= 1; + printf("filtering: height(%s) color(%s)\n", hfilt ? "linear" : "nearest", + cfilt ? "linear" : "nearest"); + vox_filter(vox, hfilt, cfilt); + break; + + case 'c': + cfilt ^= 1; + vox_filter(vox, hfilt, cfilt); + printf("filtering: height(%s) color(%s)\n", hfilt ? "linear" : "nearest", + cfilt ? "linear" : "nearest"); + break; + default: break; } diff --git a/src/voxscape.c b/src/voxscape.c index 60d80a0..0b538d9 100644 --- a/src/voxscape.c +++ b/src/voxscape.c @@ -8,6 +8,13 @@ #include "voxscape.h" #include "lut.h" +#define XLERP(a, b, t, fp) \ + ((((a) << (fp)) + ((b) - (a)) * (t)) >> fp) + +static uint32_t lerp_rgb(int r0, int g0, int b0, int r1, int g1, int b1, int32_t t); +static uint32_t lerp_color(uint32_t ca, uint32_t cb, int32_t t); +static uint32_t lerp_pcol_rgb(uint32_t pcol, int r, int g, int b, int32_t t); + enum { SLICELEN = 1 }; @@ -18,6 +25,8 @@ struct voxscape { uint32_t *color; int xshift, xmask, ymask; + int hfilt, cfilt; + /* framebuffer */ uint32_t *fb; int fbwidth, fbheight; @@ -137,12 +146,61 @@ void vox_fog(struct voxscape *vox, int zstart, uint32_t color) vox->fogcolor[2] = color & 0xff; } +#define H(x, y) \ + vox->height[((((y) >> 16) & vox->ymask) << vox->xshift) + (((x) >> 16) & vox->xmask)] +#define C(x, y) \ + vox->color[((((y) >> 16) & vox->ymask) << vox->xshift) + (((x) >> 16) & vox->xmask)] + + int vox_height(struct voxscape *vox, int32_t x, int32_t y) { - int tx = (x >> 16) & vox->xmask; - int ty = (y >> 16) & vox->ymask; + int32_t u, v; + int h00, h01, h10, h11, h0, h1; + + if(!vox->hfilt) { + return H(x, y); + } + + h00 = H(x, y); + h01 = H(x, y + 0x10000); + h10 = H(x + 0x10000, y); + h11 = H(x + 0x10000, y + 0x10000); + + u = x & 0xffff; + v = y & 0xffff; + + h0 = XLERP(h00, h01, v, 16); + h1 = XLERP(h10, h11, v, 16); + return XLERP(h0, h1, u, 16); +} + +int vox_color(struct voxscape *vox, int32_t x, int32_t y) +{ + int32_t u, v; + uint32_t c00, c01, c10, c11, c0, c1; - return vox->height[(ty << vox->xshift) + tx]; + if(!vox->cfilt) { + return C(x, y); + } + + c00 = C(x, y); + c01 = C(x, y + 0x10000); + c10 = C(x + 0x10000, y); + c11 = C(x + 0x10000, y + 0x10000); + + u = x & 0xffff; + v = y & 0xffff; + + c0 = lerp_color(c00, c01, v); + c1 = lerp_color(c10, c11, v); + return lerp_color(c0, c1, u); +} + + +void vox_filter(struct voxscape *vox, int hfilt, int cfilt) +{ + vox->hfilt = hfilt; + vox->cfilt = cfilt; } void vox_framebuf(struct voxscape *vox, int xres, int yres, uint32_t *fb, int horizon) @@ -223,7 +281,7 @@ void vox_begin(struct voxscape *vox) void vox_render_slice(struct voxscape *vox, int n) { - int i, j, tx, ty, hval, colstart, colheight, z, r, g, b; + int i, j, hval, colstart, colheight, z; int32_t x, y, len, xstep, ystep, fog; uint32_t color; uint32_t *fbptr; @@ -243,26 +301,17 @@ void vox_render_slice(struct voxscape *vox, int n) x = vox->x - SIN(vox->angle) * z - xstep * (vox->fbwidth >> 1); y = vox->y + COS(vox->angle) * z - ystep * (vox->fbwidth >> 1); for(i=0; ifbwidth; i++) { - tx = (x >> 16) & vox->xmask; - ty = (y >> 16) & vox->ymask; - - hval = vox->height[(ty << vox->xshift) + tx] - vox->vheight; + hval = vox_height(vox, x, y) - vox->vheight; hval = hval * 160 / (vox->znear + n) + vox->horizon; if(hval > vox->fbheight) hval = vox->fbheight; if(hval > vox->coltop[i]) { - color = vox->color[(ty << vox->xshift) + tx]; + color = vox_color(vox, x, y); colstart = vox->fbheight - hval; colheight = hval - vox->coltop[i]; fbptr = vox->fb + colstart * vox->fbwidth + i; if(fog > 0) { - r = color >> 16; - g = (color >> 8) & 0xff; - b = color & 0xff; - r = ((r << 8) + (vox->fogcolor[0] - r) * fog) >> 8; - g = ((g << 8) + (vox->fogcolor[1] - g) * fog) >> 8; - b = ((b << 8) + (vox->fogcolor[2] - b) * fog) >> 8; - color = (r << 16) | (g << 8) | b; + color = lerp_pcol_rgb(color, vox->fogcolor[0], vox->fogcolor[1], vox->fogcolor[2], fog); } for(j=0; jfbheight - vox->horizon; uint32_t *grad, *fbptr; @@ -310,13 +359,7 @@ void vox_sky_grad(struct voxscape *vox, uint32_t chor, uint32_t ctop) for(i=0; i> 8; - g = ((g0 << 8) + (g1 - g0) * t) >> 8; - b = ((b0 << 8) + (b1 - b0) * t) >> 8; - assert(r >= 0 && r < 256); - assert(g >= 0 && g < 256); - assert(b >= 0 && b < 256); - grad[i] = (r << 16) | (g << 8) | b; + grad[i] = lerp_rgb(r0, g0, b0, r1, g1, b1, t); } for(i=d; ifbheight; i++) { grad[i] = chor; @@ -331,3 +374,35 @@ void vox_sky_grad(struct voxscape *vox, uint32_t chor, uint32_t ctop) } } } + +static uint32_t lerp_rgb(int r0, int g0, int b0, int r1, int g1, int b1, int32_t t) +{ + int r = XLERP(r0, r1, t, 16); + int g = XLERP(g0, g1, t, 16); + int b = XLERP(b0, b1, t, 16); + return (r << 16) | (g << 8) | b; +} + +static uint32_t lerp_color(uint32_t ca, uint32_t cb, int32_t t) +{ + int r0, g0, b0, r1, g1, b1; + + r0 = ca >> 16; + g0 = (ca >> 8) & 0xff; + b0 = ca & 0xff; + r1 = cb >> 16; + g1 = (cb >> 8) & 0xff; + b1 = cb & 0xff; + + return lerp_rgb(r0, g0, b0, r1, g1, b1, t); +} + +static uint32_t lerp_pcol_rgb(uint32_t pcol, int r, int g, int b, int32_t t) +{ + int r0 = pcol >> 16; + int g0 = (pcol >> 8) & 0xff; + int b0 = pcol & 0xff; + + return lerp_rgb(r0, g0, b0, r, g, b, t); +} + diff --git a/src/voxscape.h b/src/voxscape.h index 9bd5164..0602831 100644 --- a/src/voxscape.h +++ b/src/voxscape.h @@ -3,6 +3,11 @@ #include +enum { + VOX_NEAREST, + VOX_LINEAR +}; + struct voxscape; #define VOX_RGB(r, g, b) \ @@ -15,6 +20,8 @@ void vox_free(struct voxscape *vox); void vox_fog(struct voxscape *vox, int zstart, uint32_t color); int vox_height(struct voxscape *vox, int32_t x, int32_t y); +void vox_filter(struct voxscape *vox, int hfilt, int cfilt); + void vox_framebuf(struct voxscape *vox, int xres, int yres, uint32_t *fb, int horizon); /* negative height for auto at -h above terrain */ void vox_view(struct voxscape *vox, int32_t x, int32_t y, int h, int32_t angle);