summaryrefslogtreecommitdiff
path: root/src/modules/plasma
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@gnugeneration.com>2017-02-07 04:31:53 -0800
committerVito Caputo <vcaputo@gnugeneration.com>2017-02-07 04:40:03 -0800
commit9d032314e9db794dc88889bc24bf50bbafc3ec8d (patch)
treec5f9ed5af8b0f39a5d5e08646b620c3c71884411 /src/modules/plasma
parent467137113c8b3d6bcb73ecff8c76f23793f25cb7 (diff)
plasma: add a plasma renderer
Diffstat (limited to 'src/modules/plasma')
-rw-r--r--src/modules/plasma/Makefile.am4
-rw-r--r--src/modules/plasma/plasma.c126
2 files changed, 130 insertions, 0 deletions
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",
+};
© All Rights Reserved