diff options
Diffstat (limited to 'src/modules')
| -rw-r--r-- | src/modules/Makefile.am | 2 | ||||
| -rw-r--r-- | src/modules/plasma/Makefile.am | 4 | ||||
| -rw-r--r-- | src/modules/plasma/plasma.c | 126 | 
3 files changed, 131 insertions, 1 deletions
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am index a291174..2890308 100644 --- a/src/modules/Makefile.am +++ b/src/modules/Makefile.am @@ -1 +1 @@ -SUBDIRS = ray roto sparkler stars +SUBDIRS = plasma ray roto sparkler stars diff --git a/src/modules/plasma/Makefile.am b/src/modules/plasma/Makefile.am new file mode 100644 index 0000000..16efeb4 --- /dev/null +++ b/src/modules/plasma/Makefile.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES = libplasma.a +libplasma_a_SOURCES = plasma.c +libplasma_a_CFLAGS = @ROTOTILLER_CFLAGS@ +libplasma_a_CPPFLAGS = @ROTOTILLER_CFLAGS@ -I@top_srcdir@/src diff --git a/src/modules/plasma/plasma.c b/src/modules/plasma/plasma.c new file mode 100644 index 0000000..59c394a --- /dev/null +++ b/src/modules/plasma/plasma.c @@ -0,0 +1,126 @@ +#include <stdint.h> +#include <inttypes.h> +#include <math.h> + +#include "fb.h" +#include "rototiller.h" + +/* Copyright (C) 2017 Vito Caputo <vcaputo@pengaru.com> */ + +#define FIXED_TRIG_LUT_SIZE	4096			/* size of the cos/sin look-up tables */ +#define FIXED_BITS		10			/* fractional bits */ +#define FIXED_EXP		(1 << FIXED_BITS)	/* 2^FIXED_BITS */ +#define FIXED_MASK		(FIXED_EXP - 1)		/* fractional part mask */ +#define FIXED_COS(_rad)		costab[(_rad) & (FIXED_TRIG_LUT_SIZE-1)] +#define FIXED_SIN(_rad)		sintab[(_rad) & (FIXED_TRIG_LUT_SIZE-1)] +#define FIXED_MULT(_a, _b)	(((_a) * (_b)) >> FIXED_BITS) +#define FIXED_NEW(_i)		((_i) << FIXED_BITS) +#define FIXED_TO_INT(_f)	((_f) >> FIXED_BITS) + +typedef struct color_t { +	int	r, g, b; +} color_t; + + +static inline uint32_t color2pixel(color_t *color) +{ +	return (FIXED_TO_INT(color->r) << 16) | (FIXED_TO_INT(color->g) << 8) | FIXED_TO_INT(color->b); +} + + +static void init_plasma(int32_t *costab, int32_t *sintab) +{ +	int	i; + +	/* Generate fixed-point cos & sin LUTs. */ +	for (i = 0; i < FIXED_TRIG_LUT_SIZE; i++) { +		costab[i] = ((cos((double)2*M_PI*i/FIXED_TRIG_LUT_SIZE))*FIXED_EXP); +		sintab[i] = ((sin((double)2*M_PI*i/FIXED_TRIG_LUT_SIZE))*FIXED_EXP); +	} +} + + +/* Draw a plasma effect */ +static void plasma(fb_fragment_t *fragment) +{ +	static int32_t	costab[FIXED_TRIG_LUT_SIZE], sintab[FIXED_TRIG_LUT_SIZE]; +	static int	initialized; +	static unsigned	rr, rr2, rr6, rr8, rr16, rr20, rr12; + +	unsigned	stride = fragment->stride / 4, width = fragment->width, height = fragment->height; +	int		fw2 = FIXED_NEW(width / 2), fh2 = FIXED_NEW(height / 2); +	int		x, y, cx, cy, dx2, dy2; +	uint32_t	*buf = fragment->buf; +	color_t		c = { .r = 0, .g = 0, .b = 0 }, cscale; + +	if (!initialized) { +		initialized = 1; + +		init_plasma(costab, sintab); +	} + +	rr2 = rr * 2; +	rr6 = rr * 6; +	rr8 = rr * 8; +	rr16 = rr * 16; +	rr20 = rr * 20; +	rr12 = rr * 12; + +	/* vary the color channel intensities */ +	cscale.r = FIXED_MULT(FIXED_COS(rr / 2), FIXED_NEW(64)) + FIXED_NEW(64); +	cscale.g = FIXED_MULT(FIXED_COS(rr / 5), FIXED_NEW(64)) + FIXED_NEW(64); +	cscale.b = FIXED_MULT(FIXED_COS(rr / 7), FIXED_NEW(64)) + FIXED_NEW(64); + +	cx = FIXED_TO_INT(FIXED_MULT(FIXED_COS(rr), fw2) + fw2); +	cy = FIXED_TO_INT(FIXED_MULT(FIXED_SIN(rr2), fh2) + fh2); + +	for (y = 0; y < height; y++) { +		int	y2 = y << 1; +		int	y4 = y << 2; + +		dy2 = cy - y; +		dy2 *= dy2; + +		for (x = 0; x < width; x++, buf++) { +			int	v; +			int	hyp; + +			dx2 = cx - x; +			dx2 *= dx2; + +			hyp = (dx2 + dy2) >> 10;	/* XXX: technically this should be a sqrt(), but >> 10 is a whole lot faster. */ + +			v = FIXED_MULT(	((FIXED_COS(rr8 + hyp * 5)) + +					(FIXED_SIN(-rr16 + (x << 2))) + +					(FIXED_COS(rr20 + y4))), +					FIXED_EXP / 3);	/* XXX: note these '/ 3' get optimized out. */ +			c.r = FIXED_MULT(v, cscale.r) + cscale.r; + +			v = FIXED_MULT(	((FIXED_COS(rr12 + (hyp << 2))) + +					(FIXED_COS(rr6 + (x << 1))) + +					(FIXED_SIN(rr16 + y2))), +					FIXED_EXP / 3); +			c.g = FIXED_MULT(v, cscale.g) + cscale.g; + +			v = FIXED_MULT(	((FIXED_SIN(rr6 + hyp * 6)) + +					(FIXED_COS(-rr12 + x * 5)) + +					(FIXED_SIN(-rr6 + y2))), +					FIXED_EXP / 3); +			c.b = FIXED_MULT(v, cscale.b) + cscale.b; + +			*buf = color2pixel(&c); +		} + +		buf += stride; +	} + +	rr += 3; +} + +rototiller_renderer_t	plasma_renderer = { +	.render = plasma, +	.name = "plasma", +	.description = "Oldskool plasma effect", +	.author = "Vito Caputo <vcaputo@pengaru.com>", +	.license = "GPLv2", +};  | 
