summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README1
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/modules/Makefile.am2
-rw-r--r--src/modules/julia/Makefile.am4
-rw-r--r--src/modules/julia/julia.c117
-rw-r--r--src/rototiller.c2
7 files changed, 127 insertions, 2 deletions
diff --git a/README b/README
index e7a2ab3..98f0950 100644
--- a/README
+++ b/README
@@ -4,6 +4,7 @@ rototiller is, rendered entirely in software:
sparkler: a fireworks-like particle system with spatial interactions
stars: a starfield simulator
plasma: an oldskool "plasma" effect
+ julia: a morphing Julia set (fractal)
---
diff --git a/configure.ac b/configure.ac
index 728c7ba..9c6eebb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,7 @@ AC_CONFIG_FILES([
Makefile
src/Makefile
src/modules/Makefile
+ src/modules/julia/Makefile
src/modules/plasma/Makefile
src/modules/ray/Makefile
src/modules/roto/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index b72d41c..928b8d7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,5 @@
SUBDIRS = modules
bin_PROGRAMS = rototiller
rototiller_SOURCES = drmsetup.c drmsetup.h fb.c fb.h fps.c fps.h rototiller.c rototiller.h util.c util.h
-rototiller_LDADD = @ROTOTILLER_LIBS@ -lm modules/plasma/libplasma.a modules/ray/libray.a modules/roto/libroto.a modules/sparkler/libsparkler.a modules/stars/libstars.a
+rototiller_LDADD = @ROTOTILLER_LIBS@ -lm modules/julia/libjulia.a modules/plasma/libplasma.a modules/ray/libray.a modules/roto/libroto.a modules/sparkler/libsparkler.a modules/stars/libstars.a
rototiller_CPPFLAGS = @ROTOTILLER_CFLAGS@
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
index 2890308..f65ba63 100644
--- a/src/modules/Makefile.am
+++ b/src/modules/Makefile.am
@@ -1 +1 @@
-SUBDIRS = plasma ray roto sparkler stars
+SUBDIRS = julia plasma ray roto sparkler stars
diff --git a/src/modules/julia/Makefile.am b/src/modules/julia/Makefile.am
new file mode 100644
index 0000000..54a9228
--- /dev/null
+++ b/src/modules/julia/Makefile.am
@@ -0,0 +1,4 @@
+noinst_LIBRARIES = libjulia.a
+libjulia_a_SOURCES = julia.c
+libjulia_a_CFLAGS = @ROTOTILLER_CFLAGS@
+libjulia_a_CPPFLAGS = @ROTOTILLER_CFLAGS@ -I@top_srcdir@/src
diff --git a/src/modules/julia/julia.c b/src/modules/julia/julia.c
new file mode 100644
index 0000000..1afb3cc
--- /dev/null
+++ b/src/modules/julia/julia.c
@@ -0,0 +1,117 @@
+#include <stdint.h>
+#include <inttypes.h>
+#include <math.h>
+
+#include "fb.h"
+#include "rototiller.h"
+
+/* Copyright (C) 2017 Vito Caputo <vcaputo@pengaru.com> */
+
+/* Julia set renderer - see https://en.wikipedia.org/wiki/Julia_set, morphing just means to vary C. */
+
+/* TODO: explore using C99 complex.h and its types? */
+
+static inline unsigned julia_iter(float real, float imag, float creal, float cimag, unsigned max_iters)
+{
+ unsigned i;
+ float newr, newi;
+
+ for (i = 1; i < max_iters; i++) {
+ newr = real * real - imag * imag;
+ newi = imag * real;
+ newi += newi;
+
+ newr += creal;
+ newi += cimag;
+
+ if ((newr * newr + newi * newi) > 4.0)
+ return i;
+
+ real = newr;
+ imag = newi;
+ }
+
+ return 0;
+}
+
+/* Draw a morphing Julia set */
+static void julia(fb_fragment_t *fragment)
+{
+ static uint32_t colors[] = {
+ /* this palette is just something I slapped together, definitely needs improvement. TODO */
+ 0x000000,
+ 0x000044,
+ 0x000088,
+ 0x0000aa,
+ 0x0000ff,
+ 0x0044ff,
+ 0x0088ff,
+ 0x00aaff,
+ 0x00ffff,
+ 0x44ffaa,
+ 0x88ff88,
+ 0xaaff44,
+ 0xffff00,
+ 0xffaa00,
+ 0xff8800,
+ 0xff4400,
+ 0xff0000,
+ 0xaa0000,
+ 0x880000,
+ 0x440000,
+ 0x440044,
+ 0x880088,
+ 0xaa00aa,
+ 0xff00ff,
+ 0xff4400,
+ 0xff8800,
+ 0xffaa00,
+ 0xffff00,
+ 0xaaff44,
+ 0x88ff88,
+ 0x44ffaa,
+ 0x00ffff,
+ 0x00aaff,
+ 0x0088ff,
+ 0xff4400,
+ 0xff00ff,
+ 0xaa00aa,
+ 0x880088,
+ 0x440044,
+
+ };
+ static float rr;
+
+ unsigned x, y;
+ unsigned stride = fragment->stride / 4, width = fragment->width, height = fragment->height;
+ uint32_t *buf = fragment->buf;
+ float real, imag;
+ float realstep = 3.6f / (float)width, imagstep = 3.6f / (float)height;
+
+ /* Rather than just sweeping creal,cimag from -2.0-+2.0, I try to keep things confined
+ * to an interesting (visually) range. TODO: could certainly use refinement.
+ */
+ float realscale = 0.01f * cosf(rr) + 0.01f;
+ float imagscale = 0.01f * sinf(rr * 3.0f) + 0.01f;
+ float creal = (1.01f + (realscale * cosf(1.5f*M_PI+rr) + realscale)) * cosf(rr * .3f);
+ float cimag = (1.01f + (imagscale * sinf(rr * 3.0f) + imagscale)) * sinf(rr);
+
+ /* Complex plane confined to {-1.8 - 1.8} on both axis (slightly zoomed), no dynamic zooming is performed. */
+ for (imag = 1.8, y = 0; y < height; y++, imag += -imagstep) {
+ for (real = -1.8, x = 0; x < width; x++, buf++, real += realstep) {
+ *buf = colors[julia_iter(real, imag, creal, cimag, sizeof(colors) / sizeof(*colors))];
+ }
+
+ buf += stride;
+ }
+
+ rr += .01;
+}
+
+rototiller_renderer_t julia_renderer = {
+ .render = julia,
+ .name = "julia",
+ .description = "Julia set fractal morpher",
+ .author = "Vito Caputo <vcaputo@pengaru.com>",
+ .license = "GPLv2",
+};
diff --git a/src/rototiller.c b/src/rototiller.c
index 313cb0c..22d13e2 100644
--- a/src/rototiller.c
+++ b/src/rototiller.c
@@ -24,6 +24,7 @@
* just two pages we end up twiddling thumbs until the vsync arrives.
*/
+extern rototiller_renderer_t julia_renderer;
extern rototiller_renderer_t plasma_renderer;
extern rototiller_renderer_t roto32_renderer;
extern rototiller_renderer_t roto64_renderer;
@@ -38,6 +39,7 @@ static rototiller_renderer_t *renderers[] = {
&sparkler_renderer,
&stars_renderer,
&plasma_renderer,
+ &julia_renderer,
};
© All Rights Reserved