From a563d2f0efaa980af0f0b39cdf1c9115fed99d00 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sat, 10 Feb 2018 14:04:24 +0200 Subject: [PATCH] - added blur in gfxutil - fixed 3dgfx to use the framebuffer set by g3d_framebuffer - trying a variant of the greets effect with a frame by frame blur --- src/3dgfx.c | 6 ++-- src/dos/timer.h | 37 -------------------- src/gfxutil.c | 81 +++++++++++++++++++++++++------------------ src/gfxutil.h | 9 +++-- src/greets.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++--------- src/sdl/main.c | 17 +++++++-- src/sdl/timer.c | 18 ++++++++++ src/timer.h | 20 +++++++++++ 8 files changed, 194 insertions(+), 98 deletions(-) delete mode 100644 src/dos/timer.h create mode 100644 src/sdl/timer.c create mode 100644 src/timer.h diff --git a/src/3dgfx.c b/src/3dgfx.c index 0b3505b..c32e6c2 100644 --- a/src/3dgfx.c +++ b/src/3dgfx.c @@ -44,7 +44,7 @@ struct g3d_state { struct material mtl; int width, height; - void *pixels; + uint16_t *pixels; int vport[4]; }; @@ -475,13 +475,13 @@ void g3d_draw_indexed(int prim, const struct g3d_vertex *varr, int varr_size, if(st->opt & G3D_BLEND) { int r, g, b; int inv_alpha = 255 - pv[0].a; - uint16_t *dest = fb_pixels + (pv[0].y >> 8) * fb_width + (pv[0].x >> 8); + uint16_t *dest = st->pixels + (pv[0].y >> 8) * st->width + (pv[0].x >> 8); r = ((int)pv[0].r * pv[0].a + UNPACK_R16(*dest) * inv_alpha) >> 8; g = ((int)pv[0].g * pv[0].a + UNPACK_G16(*dest) * inv_alpha) >> 8; b = ((int)pv[0].b * pv[0].a + UNPACK_B16(*dest) * inv_alpha) >> 8; *dest++ = PACK_RGB16(r, g, b); } else { - uint16_t *dest = fb_pixels + (pv[0].y >> 8) * fb_width + (pv[0].x >> 8); + uint16_t *dest = st->pixels + (pv[0].y >> 8) * st->width + (pv[0].x >> 8); *dest = PACK_RGB16(pv[0].r, pv[0].g, pv[0].b); } break; diff --git a/src/dos/timer.h b/src/dos/timer.h deleted file mode 100644 index 5f232b1..0000000 --- a/src/dos/timer.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -colcycle - color cycling image viewer -Copyright (C) 2016 John Tsiombikas - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ -#ifndef TIMER_H_ -#define TIMER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* expects the required timer resolution in hertz - * if res_hz is 0, the current resolution is retained - */ -void init_timer(int res_hz); - -void reset_timer(void); -unsigned long get_msec(void); - -#ifdef __cplusplus -} -#endif - -#endif /* TIMER_H_ */ diff --git a/src/gfxutil.c b/src/gfxutil.c index 811915e..cb51780 100644 --- a/src/gfxutil.c +++ b/src/gfxutil.c @@ -144,45 +144,60 @@ void draw_line(int x0, int y0, int x1, int y1, unsigned short color) } +#define BLUR(w, h, pstep, sstep) \ + for(i=0; i> 3) & 0x1f) << 11) | \ - ((((uint16_t)(g) >> 2) & 0x3f) << 5) | \ - (((uint16_t)(b) >> 3) & 0x1f)) + (((r) << 8) & 0xf800) | (((g) << 3) & 0x7e0) | (((b) >> 3) & 0x1f) #define UNPACK_R16(c) (((c) >> 8) & 0xf8) #define UNPACK_G16(c) (((c) >> 3) & 0xfc) @@ -18,7 +16,8 @@ int clip_line(int *x0, int *y0, int *x1, int *y1, int xmin, int ymin, int xmax, int ymax); void draw_line(int x0, int y0, int x1, int y1, unsigned short color); -void blur_grey_horiz(uint16_t *dest, uint16_t *src, int xsz, int ysz, int radius); -void blur_grey_vert(uint16_t *dest, uint16_t *src, int xsz, int ysz, int radius); +/* scale in 24.8 fixed point */ +void blur_grey_horiz(uint16_t *dest, uint16_t *src, int xsz, int ysz, int radius, int scale); +void blur_grey_vert(uint16_t *dest, uint16_t *src, int xsz, int ysz, int radius, int scale); #endif /* GFXUTIL_H_ */ diff --git a/src/greets.c b/src/greets.c index 9fa14df..0ad90a1 100644 --- a/src/greets.c +++ b/src/greets.c @@ -2,15 +2,31 @@ #include #include #include +#include #include "demo.h" #include "3dgfx.h" #include "screen.h" #include "cfgopt.h" #include "imago2.h" #include "util.h" +#include "gfxutil.h" +#include "timer.h" + +#ifdef MSDOS +#include "dos/gfx.h" /* for wait_vsync assembly macro */ +#else +void wait_vsync(void); +#endif + +/* if defined, use bilinear interpolation for dispersion field vectors */ +#define BILERP_FIELD +/* if defined randomize field vectors by RAND_FIELD_MAX */ +#define RANDOMIZE_FIELD + +#define RAND_FIELD_MAX 0.7 #define PCOUNT 4000 -#define MAX_LIFE 6.0f +#define MAX_LIFE 7.0f #define PALPHA 1.0f #define ZBIAS 0.25 #define DRAG 0.95 @@ -74,6 +90,16 @@ static struct vfield vfield; static struct g3d_vertex *varr; static long start_time; +static uint16_t *cur_smokebuf, *prev_smokebuf; +static int smokebuf_size; +#define smokebuf_start (cur_smokebuf < prev_smokebuf ? cur_smokebuf : prev_smokebuf) +#define swap_smoke_buffers() \ + do { \ + uint16_t *tmp = cur_smokebuf; \ + cur_smokebuf = prev_smokebuf; \ + prev_smokebuf = tmp; \ + } while(0) + static float cam_theta, cam_phi = 25; static float cam_dist = 3; @@ -105,11 +131,21 @@ static int init(void) return -1; } + smokebuf_size = fb_width * fb_height * sizeof *cur_smokebuf; + if(!(cur_smokebuf = malloc(smokebuf_size * 2))) { + perror("failed to allocate smoke framebuffer"); + return -1; + } + prev_smokebuf = cur_smokebuf + fb_width * fb_height; + return 0; } static void destroy(void) { + free(varr); + free(vfield.v); + free(smokebuf_start); } static void start(long trans_time) @@ -118,6 +154,8 @@ static void start(long trans_time) g3d_load_identity(); g3d_perspective(50.0, 1.3333333, 0.5, 100.0); + memset(smokebuf_start, 0, smokebuf_size * 2); + start_time = time_msec; } @@ -161,9 +199,12 @@ static void update(void) static void draw(void) { - update(); + int i, j; + uint16_t *dest, *src; + unsigned long msec; + static unsigned long last_swap; - memset(fb_pixels, 0, fb_width * fb_height * 2); + update(); g3d_matrix_mode(G3D_MODELVIEW); g3d_load_identity(); @@ -175,9 +216,35 @@ static void draw(void) g3d_rotate(cam_theta, 0, 1, 0); } + memcpy(cur_smokebuf, prev_smokebuf, smokebuf_size); + + g3d_framebuffer(fb_width, fb_height, cur_smokebuf); draw_particles(&em); + g3d_framebuffer(fb_width, fb_height, fb_pixels); + + dest = fb_pixels; + src = cur_smokebuf; + for(i=0; ix = (float)x / (float)xsz - 0.5; p->y = -(float)y / (float)xsz + 0.5 / aspect; p->z = ((float)i / (float)num * 2.0 - 1.0) * 0.005; - p->r = 0; - p->g = 0x1f; - p->b = 255; + p->r = p->g = p->b = 255; p->vx = p->vy = p->vz = 0.0f; p->life = MAX_LIFE; ++p; @@ -235,10 +300,10 @@ void update_particles(struct emitter *em, float dt) v->y = p->y; v->z = p->z; v->w = 1.0f; - v->r = p->r; - v->g = p->g; - v->b = p->b; v->a = cround64(p->life * 255.0 / MAX_LIFE); + v->r = 0; + v->g = (v->a & 0xe0) >> 3; + v->b = (v->a & 0x1f) << 3; ++v; ++p; @@ -247,9 +312,7 @@ void update_particles(struct emitter *em, float dt) void draw_particles(struct emitter *em) { - g3d_enable(G3D_BLEND); g3d_draw(G3D_POINTS, varr, PCOUNT); - g3d_disable(G3D_BLEND); } @@ -312,15 +375,16 @@ void vfield_eval(struct vfield *vf, float x, float y, struct vec2 *dir) if(x > vf->width - 2) x = vf->width - 2; if(y > vf->height - 2) y = vf->height - 2; - tx = fmod(x, 1.0f); - ty = fmod(y, 1.0f); - px = (int)x; py = (int)y; p1 = vf->v + (py << vf->xshift) + px; +#ifdef BILERP_FIELD p2 = p1 + vf->width; + tx = fmod(x, 1.0f); + ty = fmod(y, 1.0f); + left.x = p1->x + (p2->x - p1->x) * ty; left.y = p1->y + (p2->y - p1->y) * ty; ++p1; @@ -330,7 +394,13 @@ void vfield_eval(struct vfield *vf, float x, float y, struct vec2 *dir) dir->x = left.x + (right.x - left.x) * tx; dir->y = left.y + (right.y - left.y) * ty; - - dir->x += ((float)rand() / RAND_MAX - 0.5) * 0.7; - dir->y += ((float)rand() / RAND_MAX - 0.5) * 0.7; +#else + dir->x = p1->x; + dir->y = p1->y; +#endif + +#ifdef RANDOMIZE_FIELD + dir->x += ((float)rand() / RAND_MAX - 0.5) * RAND_FIELD_MAX; + dir->y += ((float)rand() / RAND_MAX - 0.5) * RAND_FIELD_MAX; +#endif } diff --git a/src/sdl/main.c b/src/sdl/main.c index 09645aa..c00bf7d 100644 --- a/src/sdl/main.c +++ b/src/sdl/main.c @@ -4,12 +4,13 @@ #include #include "demo.h" #include "tinyfps.h" +#include "timer.h" +#include "cfgopt.h" static void handle_event(SDL_Event *ev); static void toggle_fullscreen(void); static int quit; -static long start_time; static SDL_Surface *fbsurf; static int fbscale = 2; @@ -52,7 +53,7 @@ int main(int argc, char **argv) SDL_Quit(); return 1; } - start_time = SDL_GetTicks(); + reset_timer(); while(!quit) { SDL_Event ev; @@ -61,7 +62,7 @@ int main(int argc, char **argv) if(quit) goto break_evloop; } - time_msec = SDL_GetTicks() - start_time; + time_msec = get_msec(); demo_draw(); drawFps(fb_pixels); @@ -103,9 +104,19 @@ void demo_quit(void) quit = 1; } +void wait_vsync(void) +{ + unsigned long start = SDL_GetTicks(); + unsigned long until = (start | 0xf) + 1; + while(SDL_GetTicks() <= until); +} + void swap_buffers(void *pixels) { /* do nothing, all pointers point to the same buffer */ + if(opt.vsync) { + wait_vsync(); + } } static void handle_event(SDL_Event *ev) diff --git a/src/sdl/timer.c b/src/sdl/timer.c new file mode 100644 index 0000000..2193ddd --- /dev/null +++ b/src/sdl/timer.c @@ -0,0 +1,18 @@ +#include +#include "timer.h" + +static unsigned long start_time; + +void init_timer(int res_hz) +{ +} + +void reset_timer(void) +{ + start_time = SDL_GetTicks(); +} + +unsigned long get_msec(void) +{ + return SDL_GetTicks() - start_time; +} diff --git a/src/timer.h b/src/timer.h new file mode 100644 index 0000000..1fa83c3 --- /dev/null +++ b/src/timer.h @@ -0,0 +1,20 @@ +#ifndef TIMER_H_ +#define TIMER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* expects the required timer resolution in hertz + * if res_hz is 0, the current resolution is retained + */ +void init_timer(int res_hz); + +void reset_timer(void); +unsigned long get_msec(void); + +#ifdef __cplusplus +} +#endif + +#endif /* TIMER_H_ */ -- 1.7.10.4