From 8d990b8929964fcf88a023128dc26f27a13f264c Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Mon, 27 Jun 2022 12:07:33 -0700 Subject: modules/drizzle: experimenting with the new snapshotting This arguably doesn't require snapshotting to work, since it's doing a rudimentary in-place single pixel alpha-blended replacement using a single pixel at the same location. But the moment it startus using multiple adjacent super-samples, the snapshot becomes necessary. If it gets further complicated with displacements and maybe bump-mapping or something, then the samples can become quite distant from the pixel being written, spreading out into neighboring fragments being rendered simultaneously etc. These are all cause for snapshotting... For now though it's a very simple implementation that at least makes drizzle overlayable, while also providing a smoke test for the new snapshotting functionality. --- src/modules/drizzle/drizzle.c | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/modules/drizzle/drizzle.c b/src/modules/drizzle/drizzle.c index fff59bd..57b2664 100644 --- a/src/modules/drizzle/drizzle.c +++ b/src/modules/drizzle/drizzle.c @@ -43,6 +43,7 @@ typedef struct drizzle_setup_t { typedef struct drizzle_context_t { til_module_context_t til_module_context; + til_fb_fragment_t *snapshot; puddle_t *puddle; drizzle_setup_t setup; } drizzle_context_t; @@ -127,6 +128,31 @@ static void drizzle_prepare_frame(til_module_context_t *context, unsigned ticks, } puddle_tick(ctxt->puddle, ctxt->setup.viscosity); + + if ((*fragment_ptr)->cleared) + ctxt->snapshot = til_fb_fragment_snapshot(fragment_ptr, 0); +} + + +/* TODO: this probably should also go through a gamma correction */ +static inline uint32_t pixel_mult_scalar(uint32_t pixel, float t) +{ + float r, g, b; + + if (t > 1.f) + t = 1.f; + if (t < 0.f) + t = 0.f; + + r = (pixel >> 16) & 0xff; + g = (pixel >> 8) & 0xff; + b = (pixel & 0xff); + + r *= t; + g *= t; + b *= t; + + return ((uint32_t)r) << 16 | ((uint32_t)g) << 8 | ((uint32_t)b); } @@ -139,6 +165,26 @@ static void drizzle_render_fragment(til_module_context_t *context, unsigned tick float yf = 1.f / (float)fragment->frame_height; v2f_t coord; + if (ctxt->snapshot) { + coord.y = yf * (float)fragment->y; + for (int y = fragment->y; y < fragment->y + fragment->height; y++) { + + coord.x = xf * (float)fragment->x; + for (int x = fragment->x; x < fragment->x + fragment->width; x++) { + float t = puddle_sample(ctxt->puddle, &coord); + uint32_t pixel = pixel_mult_scalar(til_fb_fragment_get_pixel_unchecked(ctxt->snapshot, x, y), t); + + til_fb_fragment_put_pixel_unchecked(fragment, 0, x, y, pixel); + + coord.x += xf; + } + + coord.y += yf; + } + + return; + } + coord.y = yf * (float)fragment->y; for (int y = fragment->y; y < fragment->y + fragment->height; y++) { @@ -160,6 +206,15 @@ static void drizzle_render_fragment(til_module_context_t *context, unsigned tick } +static void drizzle_finish_frame(til_module_context_t *context, unsigned int ticks, til_fb_fragment_t **fragment_ptr) +{ + drizzle_context_t *ctxt = (drizzle_context_t *)context; + + if (ctxt->snapshot) + ctxt->snapshot = til_fb_fragment_reclaim(ctxt->snapshot); +} + + static int drizzle_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup) { const char *viscosity; @@ -208,8 +263,10 @@ til_module_t drizzle_module = { .destroy_context = drizzle_destroy_context, .prepare_frame = drizzle_prepare_frame, .render_fragment = drizzle_render_fragment, + .finish_frame = drizzle_finish_frame, .name = "drizzle", .description = "Classic 2D rain effect (threaded (poorly))", .author = "Vito Caputo ", .setup = drizzle_setup, + .flags = TIL_MODULE_OVERLAYABLE, }; -- cgit v1.2.3