From 09af809c6e4364b92b10c983d38ab6b32dd7d50c Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Wed, 8 Jan 2020 20:40:23 -0800 Subject: modules/drizzle: add a classic 2D raindrops vis Using the new puddle lib throw some raindrops on the framebuffer --- configure.ac | 1 + src/Makefile.am | 2 +- src/modules/Makefile.am | 2 +- src/modules/drizzle/Makefile.am | 3 + src/modules/drizzle/drizzle.c | 197 ++++++++++++++++++++++++++++++++++++++++ src/rototiller.c | 2 + 6 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 src/modules/drizzle/Makefile.am create mode 100644 src/modules/drizzle/drizzle.c diff --git a/configure.ac b/configure.ac index 37c8a4c..4d562b5 100644 --- a/configure.ac +++ b/configure.ac @@ -42,6 +42,7 @@ AC_CONFIG_FILES([ src/libs/ray/Makefile src/libs/txt/Makefile src/modules/Makefile + src/modules/drizzle/Makefile src/modules/flui2d/Makefile src/modules/julia/Makefile src/modules/meta2d/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 8e4ae2e..2dda6d5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,4 +4,4 @@ rototiller_SOURCES = fb.c fb.h fps.c fps.h rototiller.c rototiller.h sdl_fb.c se if ENABLE_DRM rototiller_SOURCES += drm_fb.c endif -rototiller_LDADD = modules/flui2d/libflui2d.a modules/julia/libjulia.a modules/meta2d/libmeta2d.a modules/montage/libmontage.a modules/pixbounce/libpixbounce.a modules/plasma/libplasma.a modules/ray/libray.a modules/roto/libroto.a modules/rtv/librtv.a modules/snow/libsnow.a modules/sparkler/libsparkler.a modules/spiro/libspiro.a modules/stars/libstars.a modules/submit/libsubmit.a modules/swab/libswab.a libs/grid/libgrid.a libs/puddle/libpuddle.a libs/ray/libray.a libs/txt/libtxt.a libs/ascii/libascii.a libs/din/libdin.a -lm +rototiller_LDADD = modules/drizzle/libdrizzle.a modules/flui2d/libflui2d.a modules/julia/libjulia.a modules/meta2d/libmeta2d.a modules/montage/libmontage.a modules/pixbounce/libpixbounce.a modules/plasma/libplasma.a modules/ray/libray.a modules/roto/libroto.a modules/rtv/librtv.a modules/snow/libsnow.a modules/sparkler/libsparkler.a modules/spiro/libspiro.a modules/stars/libstars.a modules/submit/libsubmit.a modules/swab/libswab.a libs/grid/libgrid.a libs/puddle/libpuddle.a libs/ray/libray.a libs/txt/libtxt.a libs/ascii/libascii.a libs/din/libdin.a -lm diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am index 958d835..ad0c7bd 100644 --- a/src/modules/Makefile.am +++ b/src/modules/Makefile.am @@ -1 +1 @@ -SUBDIRS = flui2d julia meta2d montage pixbounce plasma ray roto rtv snow sparkler spiro stars submit swab +SUBDIRS = drizzle flui2d julia meta2d montage pixbounce plasma ray roto rtv snow sparkler spiro stars submit swab diff --git a/src/modules/drizzle/Makefile.am b/src/modules/drizzle/Makefile.am new file mode 100644 index 0000000..caaa45f --- /dev/null +++ b/src/modules/drizzle/Makefile.am @@ -0,0 +1,3 @@ +noinst_LIBRARIES = libdrizzle.a +libdrizzle_a_SOURCES = drizzle.c +libdrizzle_a_CPPFLAGS = -I@top_srcdir@/src -I@top_srcdir@/src/libs diff --git a/src/modules/drizzle/drizzle.c b/src/modules/drizzle/drizzle.c new file mode 100644 index 0000000..436c347 --- /dev/null +++ b/src/modules/drizzle/drizzle.c @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2020 - Vito Caputo - + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * 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 . + */ + +#include +#include + +#include "fb.h" +#include "puddle/puddle.h" +#include "rototiller.h" + +#define PUDDLE_SIZE 512 +#define DRIZZLE_CNT 20 +#define DEFAULT_VISCOSITY .01f + +typedef struct drizzle_context_t { + puddle_t *puddle; + unsigned n_cpus; +} drizzle_context_t; + +typedef struct v3f_t { + float x, y, z; +} v3f_t; + +typedef struct v2f_t { + float x, y; +} v2f_t; + +static float drizzle_viscosity = DEFAULT_VISCOSITY; + + +/* convert a color into a packed, 32-bit rgb pixel value (taken from libs/ray/ray_color.h) */ +static inline uint32_t color_to_uint32(v3f_t color) { + uint32_t pixel; + + if (color.x > 1.0f) color.x = 1.0f; + if (color.y > 1.0f) color.y = 1.0f; + if (color.z > 1.0f) color.z = 1.0f; + + if (color.x < .0f) color.x = .0f; + if (color.y < .0f) color.y = .0f; + if (color.z < .0f) color.z = .0f; + + pixel = (uint32_t)(color.x * 255.0f); + pixel <<= 8; + pixel |= (uint32_t)(color.y * 255.0f); + pixel <<= 8; + pixel |= (uint32_t)(color.z * 255.0f); + + return pixel; +} + + +static void * drizzle_create_context(unsigned num_cpus) +{ + drizzle_context_t *ctxt; + + ctxt = calloc(1, sizeof(drizzle_context_t)); + if (!ctxt) + return NULL; + + ctxt->puddle = puddle_new(PUDDLE_SIZE, PUDDLE_SIZE); + if (!ctxt->puddle) { + free(ctxt); + return NULL; + } + + ctxt->n_cpus = num_cpus; + + return ctxt; +} + + +static void drizzle_destroy_context(void *context) +{ + drizzle_context_t *ctxt = context; + + puddle_free(ctxt->puddle); + free(ctxt); +} + + +static int drizzle_fragmenter(void *context, const fb_fragment_t *fragment, unsigned number, fb_fragment_t *res_fragment) +{ + drizzle_context_t *ctxt = context; + + return fb_fragment_slice_single(fragment, ctxt->n_cpus, number, res_fragment); +} + + +static void drizzle_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fragment, rototiller_fragmenter_t *res_fragmenter) +{ + drizzle_context_t *ctxt = context; + + *res_fragmenter = drizzle_fragmenter; + + for (int i = 0; i < DRIZZLE_CNT; i++) { + int x = rand() % (PUDDLE_SIZE - 1); + int y = rand() % (PUDDLE_SIZE - 1); + + /* TODO: puddle should probably offer a normalized way of setting an + * area to a value, so if PUDDLE_SIZE changes this automatically + * would adapt to cover the same portion of the unit square... + */ + puddle_set(ctxt->puddle, x, y, 1.f); + puddle_set(ctxt->puddle, x + 1, y, 1.f); + puddle_set(ctxt->puddle, x, y + 1, 1.f); + puddle_set(ctxt->puddle, x + 1, y + 1, 1.f); + } + + puddle_tick(ctxt->puddle, drizzle_viscosity); +} + + +static void drizzle_render_fragment(void *context, unsigned cpu, fb_fragment_t *fragment) +{ + drizzle_context_t *ctxt = context; + float xf = 2.f / (float)fragment->frame_width; + float yf = 2.f / (float)fragment->frame_height; + v2f_t coord; + + for (int y = fragment->y; y < fragment->y + fragment->height; y++) { + coord.y = yf * (float)y - 1.f; + + for (int x = fragment->x; x < fragment->x + fragment->width; x++) { + v3f_t color = {}; + uint32_t pixel; + + coord.x = xf * (float)x - 1.f; + + color.z = puddle_sample(ctxt->puddle, &coord); + + pixel = color_to_uint32(color); + fb_fragment_put_pixel_unchecked(fragment, x, y, pixel); + } + } +} + + +static int drizzle_setup(const settings_t *settings, setting_desc_t **next_setting) +{ + const char *viscosity; + const char *values[] = { + ".005f", + ".01f", + ".03f", + ".05f", + NULL + }; + + viscosity = settings_get_value(settings, "viscosity"); + if (!viscosity) { + int r; + + r = setting_desc_clone(&(setting_desc_t){ + .name = "Puddle Viscosity", + .key = "viscosity", + .regex = "\\.[0-9]+", + .preferred = SETTINGS_STR(DEFAULT_VISCOSITY), + .values = values, + .annotations = NULL + }, next_setting); + if (r < 0) + return r; + + return 1; + } + + sscanf(viscosity, "%f", &drizzle_viscosity); + + return 0; +} + + +rototiller_module_t drizzle_module = { + .create_context = drizzle_create_context, + .destroy_context = drizzle_destroy_context, + .prepare_frame = drizzle_prepare_frame, + .render_fragment = drizzle_render_fragment, + .name = "drizzle", + .description = "Classic 2D rain effect (threaded (poorly))", + .author = "Vito Caputo ", + .license = "GPLv3", + .setup = drizzle_setup, +}; diff --git a/src/rototiller.c b/src/rototiller.c index 644013b..2477d4b 100644 --- a/src/rototiller.c +++ b/src/rototiller.c @@ -32,6 +32,7 @@ extern fb_ops_t drm_fb_ops; extern fb_ops_t sdl_fb_ops; fb_ops_t *fb_ops; +extern rototiller_module_t drizzle_module; extern rototiller_module_t flui2d_module; extern rototiller_module_t julia_module; extern rototiller_module_t meta2d_module; @@ -49,6 +50,7 @@ extern rototiller_module_t submit_module; extern rototiller_module_t swab_module; static const rototiller_module_t *modules[] = { + &drizzle_module, &flui2d_module, &julia_module, &meta2d_module, -- cgit v1.2.1