Google+ post
Tim HuttonTim Hutton - 2014-04-25 20:24:49+0000 - Updated: 2014-04-25 20:24:49+0000
Originally shared by Felix WoitzelIn case anyone missed it, my entry "DragonDrop" has won the #js1k JavaScript code golfing competition 2014!

This year's topic was "Here Be Dragons". The theme is not mandatory anyway, but i must have nailed it twice and a third time just for the lulz.
recommended listen:

"Glowing small hours
Fade into black with you
In echoing chambers"

The winning entry is an interactive Dragon curve that can be edited by Drag'n'drop of four control points, all in just below 1024 characters of JavaScript for classic HTML5. That means, it also runs in the Internet Explorer. I endorse you to try it on your tablet PC too - touch events are supported just as well.

Here's the winning entry in action:
And read the description there too:

I'm attending the competition since 2012, and this year I've entered 3 submissions.
The first one went in the new and experimental WebGL category:
It features the pingpong framebuffer boilerplate for all sorts of render-to-texture feedback effects. But even with the most simple sustain and fadeout, plus basic mouse interactivity, i was already at the 1k limit, and I had to throw out the resizing of the viewport to the full available screen size, which also messed up the mapping of the mouse coordinate. It felt good enough to submit at the the time anyway. ;)

Then i went on extending that basis to a decent 2k entry. In the following 3 days, I've first added a complex number multiplication shader function for the "rotozoom" in the affine transformation for the Lindenmayer-type fractals (with a random twist), then i separated the shader program in one that processes a new frame from the old one, and another one that renders a final output to the screen. I've used this method a lot since 2007, when in the programmable music visualization plugin Milkdrop2 for Winamp, the 'composite' and the 'warp' shader steps were introduced. I wrote and talked about that in my FMX2013 session - see here:
Many of my WebGL experiments adopted this method more or less directly. 
Even before custom shaders, in Milkdrop1, you could achieve (multi-)texture feedback effects with semi-transparent overlays of textured shapes. That's how I learned to use the progressive image-based approach to render a certain kind of fractals in the first place, simply by learning by doing out of curiosity. In 2007, I've published my first pieces, but I must have had exercised two years quietly already. That was the time when I also worked out the "self-similarity" series too, with a lot of ferns and other stuff like that - check out, or . The latter one got reused by me over and over again, and some mixes are also readily included in the official Winamp release since version 5.5. I'm speaking about the presets "milkcore" and "fractal seafood". If you don't want to fire up Winamp, here's a youtube recording: MGMT - Electric Feel [Milkdrop2.0 Demo]

In Milkdrop, i had also previously found the intricate yet simple shader function for another winged fractal. 
If you look at the source code either in the current WebGL glsl or in the old Milkdrop hlsl, the formula is remarkable simple. Assume the screen space as the complex number plane with a real and an imaginary axis, one complex division that is scaled down so that it is near zero over most of the screen space with one asymptote at a variable center point, mixed together with the undistorted domain plane, is used as a so-called "plane deformation". Or if you feel more comfortable with this description: This is used as a partial differential equation, and frame-per-frame line integral convolution step that reads the color from the displaced position in the old frame. Before the division, another multiplication is used to rotate the complex number plane so that the two "wings" become adjustable to the motion direction. All in one well-below-tweet-sized code line. A procedural circle, or rather a cone tip, at the center is added to make the pearl necklace like impression. This is the only point where the "black" is injected to the initially empty scene and slowly but steady it fills up the whole screen. I can date my first use of the function back to 2008 and I've remixed it from time to time too. After all, Winamp is still not dead, and so is the forum. You can download the Milkdrop presets here and here 

By the way, with the same method with a formula that contains an even simpler complex square function (^2) instead of the (^-1) polynomial, you can also render Julia fractals:
The trick is to flow with each Bit of the four individual Bytes of the feedback texture's rgba pixel values. 1 Bit changes per frame can still give a good dynamic performance. I've learned to appreciate the power of simple gradients.
Thanks to the nature of shaders, it's pretty easy to wire different types of fractals in the separate rgba channels of the feedback texture, and recolor them in a final composite operation. And in fact, the red and the alpha are still unused in the last version of my 2k WebGL entry "Edgy The Pit Minder":
The blue channel is mapped to a red that goes over in white, for the randomly changing L-system fractal. The black winged fractal is actually set up in the green channel. At last, I've used a differential edge detection with 4 texture lookups from the one-pixel for the enhancements on the gradients of blue and green. Gradients in blue are enhanced by subtracting to black where the green or blue level is low, and adding white where the red level is high. The gradients in green become white only in the absence of blue and in the environment of low-value green. I've also used the gradients in green for a subtle refraction and reflection effect. Just look very closely. ;) At last I've applied the plane deformation from the warp step to the composite to give everything a really mind-bending touch.

Only 2k WebGL was just not a legal category! If I had read the rules properly, I must have known that. And when I wanted to submit it, I only got the confused response that it must be rejected.

I've made one or two bad puns about it. And I've overheard a comment by an interested fellow at the local hackerspace, which made a little wave on Twitter too: ;) Cheers, and honor to whom honor is due, Sascha!

Then I refocused on how to do it the classic way. I tried a few times to emulate a FrameBufferObject, first with ImageData instances and then even ToDataURL(), which all just not performed well. Finally, I've found out that you can directly use canvases as arguments for drawImage calls on a context2d object, and it just runs hardware accelerated and butter smooth. My first shot at a not yet interactive fractal drop with a rock-solid performance already compressed to below 512 Bytes. The rest is not so much spectacular. The control point data values are stored in extended properties of fresh canvas instances in an array of four, and I've used a custom meta function for the often reoccurring loop from i=1 to 4. Just read the richly commented source code. ;)

You can find the history of my progresses here:

I really didn't expect it to go out like that, and I really felt funny too. On the last day, i made another old Milkdrop reference joke, that was hardly to get for anyone who doesn't follow me for too long, I suspect. Go search for the preset "The early bird" in your Milkdrop preset folder and you know what I might have thought back on that day. ;) I mean, i really had made a version of the flappy wing fractal that was wired to simple differential easing functions, quite similar to how you would do springs physics simulation in a Verlet integration style. But I just didn't manage to get them in on the last minute. I've finished the April's Fools edition "Le Moustache" 23:59 on 31st March but I had no time left to submit it. :D

I hope you had as much fun as I had and maybe you could even learn something. ;)

Also thanks to the generous sponsors! As a tribute, I'm looking forward to buy a Lasershow rig, and build a depth scanner silhouette edge tracer program! ;)
Shared with: Public
+1'd by: TheBlack Box

This post was originally on Google+