diff --git a/201410_-_Sine_City/README b/201410_-_Sine_City/README
new file mode 100644
index 0000000..6c111eb
--- /dev/null
+++ b/201410_-_Sine_City/README
@@ -0,0 +1,11 @@
+Source code for "Sine City"
+A JavaScript 8K intro
+
+On Pouet: http://www.pouet.net/prod.php?which=64233
+
+Notes:
+	* It is likely not to work on your end.
+	* Tested on Linux using Chromium and Firefox with a NVidia GPU
+	* Known to work on some Windows boxes w/ native GL enabled
+	* The "original" version is not the code that was shown at DemoJS,
+		I adjusted quite a few things in the final, packed version.
diff --git a/201410_-_Sine_City/custom-jsexe-bootstrap b/201410_-_Sine_City/custom-jsexe-bootstrap
new file mode 100644
index 0000000..ea3c9f2
--- /dev/null
+++ b/201410_-_Sine_City/custom-jsexe-bootstrap
@@ -0,0 +1,2 @@
+// in case I need it again
+C=V.getContext('2d');for(C.drawImage(this,0,_='');$--;(A=C.getImageData($%X,$/X,1,1).data[0])&&(_+=String.fromCharCode(A)));(1,eval)(_)
diff --git a/201410_-_Sine_City/music.js b/201410_-_Sine_City/music.js
new file mode 100644
index 0000000..f51b6e7
--- /dev/null
+++ b/201410_-_Sine_City/music.js
@@ -0,0 +1,159 @@
+var song = {
+  songData: [
+    {
+      i: [ 0, 198, 128, 0, 3, 192, 128, 1, 0, 0, 96, 128, 28, 0, 0, 0, 0, 2, 63, 61, 13, 16, 44, 8, 0, 0 ],
+
+      p: [1,2,3,4,5,2,3,4,6,7,1,2,3,4,5,2,3,4,5,2,3,4,1,2,3,8,9],
+
+      c: [
+        {n: [115,,,,,,,,,,,,117,,,,,,,,,,,,113],
+         f: [12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]},
+        {n: [115,,,,,,,,,,,,,,,110],
+         f: [12,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,148]},
+        {n: [115,,,,,,,,,,,,117,,,,,,,,,,,,118],
+         f: [12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]},
+        {n: [122,,,,,,,,,,,,,,,123,,,,,115],
+         f: [12,,,,,,,,,,,,,,,12,,,,,12,,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,8,,,,,128]},
+        {n: [118,,,,,,,,,,,,117,,,,,,,,,,,,113],
+         f: [12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]},
+        {n: [115],
+         f: [12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,255]},
+        {n: [,,,,,,,,,,,,,,,,118,118,118],
+         f: [,,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,128]},
+        {n: [122,,,,,,,,,,,,,,,123,,,,,115],
+         f: [12,,,,,,,,,,,,,,,12,,,,,13,12,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,8,,,,,95,61]},
+        {n: [],
+         f: []}
+      ]
+    },
+    {
+      i: [ 0, 255, 116, 1, 0, 255, 101, 0, 0, 15, 1, 4, 45, 0, 13, 6, 1, 2, 62, 27, 60, 48, 0, 0, 44, 2 ],
+
+      p: [,1,,2,,1,,2,,3,4,4,5,4,5,4,5,4,5,4,5,4,5,4,3,6],
+
+      c: [
+        {n: [,,,,,139,,,139,139,,,,,,139,,,,,,,,139,,,139,139,,,,,139,139,139],
+         f: []},
+        {n: [,,139,139,,,,,139,139,,,,,139,139,,,,,,,,,,139,139,139,,,,,139,139,139],
+         f: []},
+        {n: [,,,139,,,,,139,139,,,,,,139,,,,,139,139,,,,,,139,,,,139,139,139],
+         f: []},
+        {n: [139,,,,139,,139,,,139,,,139,,,,139,,139,,,139,,,139,,,,139,,139,,,139],
+         f: []},
+        {n: [139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139],
+         f: []},
+        {n: [139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139,139],
+         f: []}
+      ]
+    },
+    {
+      i: [ 0, 0, 140, 0, 0, 0, 140, 0, 0, 128, 4, 10, 34, 0, 187, 5, 0, 1, 239, 135, 34, 19, 108, 8, 8, 4 ],
+
+      p: [,,1,,1,,3,,1,3,2,2,2,2,2,3,2,3,2,3,2,3,2,3,1],
+
+      c: [
+        {n: [,,,,,,,,,,127,,,,,,,,,,,,127,,,,,,,,,,,,127],
+         f: []},
+        {n: [,,,139,,,,,,139,139,,,,,139,,,,,,139,139,,,,,139,,,,,139,,139],
+         f: []},
+        {n: [,,127,,,,,,,,127,,,,127,,,,,,,,127,,,,127,,,,,,,,127],
+         f: []}
+      ]
+    },
+    {
+      i: [ 1, 192, 128, 0, 3, 201, 128, 0, 0, 93, 5, 6, 58, 3, 195, 6, 1, 3, 35, 63, 14, 17, 11, 10, 61, 6 ],
+
+      p: [,,,,1,2,3,4,5,6,7,5,8,9,10,11,8,9,10,11,12,13,14,15,16],
+
+      c: [
+        {n: [,,,,,,,,147,146,145,,,,,,,,,,145,147,146,,,,,,,,,,149,148,147],
+         f: []},
+        {n: [,,,,,,151,151,151,,,,,,,146,142,138,,,,,,,,,,,,,,,147,150,147],
+         f: []},
+        {n: [,,146,,,146,,,,,,,,,147,146,145,,,,,,,,,,146,145,142,,,142,,,142],
+         f: []},
+        {n: [,,141,,,,,,,,,,,,141,140,139,,,146,,,146,,,127],
+         f: []},
+        {n: [,139,,151,,,,,,,,,,151,,139,,,,,,,,,,139,,151],
+         f: []},
+        {n: [,139,,151,150,149,,,,,,,,139,,149,148,147,,,,,,,,139,,,146,,,145,,,144],
+         f: []},
+        {n: [,139,,,139,142,,,142,144,146,,144,,,,146,147,,,147,146,141,,137,,,,142,141,,141,,137],
+         f: []},
+        {n: [139,,127,,142,,,130,,,144,142,141,,129,,141,,,144,,,141,144,142,,,,149,,,146,,,151],
+         f: []},
+        {n: [,149,,149,,146,144,142,,,141,,142,,,139,,,,151,147,,,,146,147,,144,146,,142,144,141,146],
+         f: []},
+        {n: [,,,,,,,,147,146,145,,,,,141,144,147,146,,144,,137,,,144,146,142,144,,,142,144,141,146],
+         f: []},
+        {n: [,146,,151,,146,,,,144,142,144,146,,,,142,,,,,139,,,,,151,146,139,144,139,142,141,142,151],
+         f: []},
+        {n: [,,147,,,149,146,,,142,,142,141,,,144,,144,,,144,146,142,144,142,,,,151,150,149,,137,,149],
+         f: []},
+        {n: [,151,,,147,151,,,146,151,,,,,144,151,,149,147,149,151,,146,,,144,143,142,,,139,,151,139],
+         f: []},
+        {n: [,,134,,,134,,,134,,,146,144,,,141,144,,,146,147,146,,,144,,139,140,141,,,153,,,141],
+         f: []},
+        {n: [,142,,151,,,142,143,144,,,,151,,,139,,,137,,149,,137,,,,125,,,141,142,141,,,146],
+         f: []},
+        {n: [139,,127,139,,127,139,,127,139,127],
+         f: []}
+      ]
+    },
+    {
+      i: [ 2, 160, 128, 1, 0, 160, 128, 0, 1, 60, 4, 7, 41, 0, 60, 4, 1, 3, 14, 0, 35, 32, 31, 12, 89, 1 ],
+
+      p: [,,,,,,,,,,,,1,2,1,2,1,2,1,2,1,2,1,2,1,3],
+
+      c: [
+        {n: [,,139,,,,,,,,,,,,139,,,,,,,,,,,,139,,,,,139,139,,,139],
+         f: []},
+        {n: [,,139,,,151,,,139,,,151,,,139,,,151,,,139,,,151,,,139,,,151,,,146,146,146,146],
+         f: []},
+        {n: [,,139,,,151,,,139,,,151,,,139,,139,139,139,139,127],
+         f: []}
+      ]
+    },
+    {
+      i: [ 2, 100, 128, 0, 3, 201, 128, 0, 0, 0, 0, 6, 29, 0, 195, 6, 1, 3, 28, 229, 119, 77, 147, 6, 61, 2 ],
+
+      p: [,,,,,,,,,6,1,2,3,4,5,2,3,4,1,2,3,4,1,2,3,7],
+
+      c: [
+        {n: [115,115,115,115,115,115,115,115,115,115,115,115,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],
+         f: []},
+        {n: [115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110],
+         f: []},
+        {n: [115,115,115,115,115,115,115,115,115,115,115,115,117,117,117,117,117,117,117,117,117,117,117,117,118,118,118,118,118,118,118,118,118,118,118,118],
+         f: []},
+        {n: [110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115],
+         f: []},
+        {n: [118,118,118,118,118,118,118,118,118,118,118,118,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],
+         f: []},
+        {n: [,,,,,,,,,,,,,,,,,,130,,130,,130,,130,,130,,130,118,130,118,130,118,130,118],
+         f: [,,,,,,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2]},
+        {n: [110,122,,122,134,,110,122,,122,134,,110,122,,111,123,,111,123,115,127,139,127,115],
+         f: [,,,,,,,,,,,,,,,,,,,,26,25,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,147]}
+      ]
+    },
+    {
+      i: [ 2, 100, 128, 0, 3, 201, 128, 0, 0, 0, 5, 6, 58, 0, 195, 6, 1, 2, 135, 0, 0, 32, 147, 6, 121, 6 ],
+
+      p: [],
+
+      c: [
+      ]
+    },
+    {
+      i: [ 2, 100, 128, 0, 3, 201, 128, 0, 0, 0, 5, 6, 58, 0, 195, 6, 1, 2, 135, 0, 0, 32, 147, 6, 121, 6 ],
+
+      p: [],
+
+      c: [
+      ]
+    }
+  ],
+  rowLen: 5513,
+  patternLen: 36,
+  endPattern: 28
+};
diff --git a/201410_-_Sine_City/music.ogg b/201410_-_Sine_City/music.ogg
new file mode 100644
index 0000000..0f4291e
Binary files /dev/null and b/201410_-_Sine_City/music.ogg differ
diff --git a/201410_-_Sine_City/player-small.js b/201410_-_Sine_City/player-small.js
new file mode 100644
index 0000000..22c48d8
--- /dev/null
+++ b/201410_-_Sine_City/player-small.js
@@ -0,0 +1,336 @@
+/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil; -*-
+*
+* Copyright (c) 2011-2013 Marcus Geelnard
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+*
+* 3. This notice may not be removed or altered from any source
+*    distribution.
+*
+*/
+
+"use strict";
+
+var CPlayer = function() {
+
+    //--------------------------------------------------------------------------
+    // Private methods
+    //--------------------------------------------------------------------------
+
+    // Oscillators
+    var osc_sin = function (value) {
+        return Math.sin(value * 6.283184);
+    };
+
+    var osc_saw = function (value) {
+        return 2 * (value % 1) - 1;
+    };
+
+    var osc_square = function (value) {
+        return (value % 1) < 0.5 ? 1 : -1;
+    };
+
+    var osc_tri = function (value) {
+        var v2 = (value % 1) * 4;
+        if(v2 < 2) return v2 - 1;
+        return 3 - v2;
+    };
+
+    var getnotefreq = function (n) {
+        // 174.61.. / 44100 = 0.003959503758 (F3)
+        return 0.003959503758 * Math.pow(2, (n - 128) / 12);
+    };
+
+    var createNote = function (instr, n) {
+        var osc1 = mOscillators[instr.i[0]],
+            o1vol = instr.i[1],
+            o1xenv = instr.i[3],
+            osc2 = mOscillators[instr.i[4]],
+            o2vol = instr.i[5],
+            o2xenv = instr.i[8],
+            noiseVol = instr.i[9],
+            attack = instr.i[10] * instr.i[10] * 4,
+            sustain = instr.i[11] * instr.i[11] * 4,
+            release = instr.i[12] * instr.i[12] * 4,
+            releaseInv = 1 / release;
+
+        var noteBuf = new Int32Array(attack + sustain + release);
+
+        // Calculate note frequencies for the oscillators
+        var o1t = getnotefreq(n + instr.i[2] - 128);
+        var o2t = getnotefreq(n + instr.i[6] - 128) * (1 + 0.0008 * instr.i[7]);
+
+        // Re-trig oscillators
+        var c1 = 0, c2 = 0;
+
+        // Local variables.
+        var j, e, t, rsample;
+
+        // Generate one note (attack + sustain + release)
+        for (j = 0; j < attack + sustain + release; j++) {
+            // Envelope
+            e = 1;
+            if (j < attack) {
+                e = j / attack;
+            } else if (j >= attack + sustain) {
+                e -= (j - attack - sustain) * releaseInv;
+            }
+
+            // Oscillator 1
+            t = o1t;
+            if (o1xenv) {
+                t *= e * e;
+            }
+            c1 += t;
+            rsample = osc1(c1) * o1vol;
+
+            // Oscillator 2
+            t = o2t;
+            if (o2xenv) {
+                t *= e * e;
+            }
+            c2 += t;
+            rsample += osc2(c2) * o2vol;
+
+            // Noise oscillator
+            if (noiseVol) {
+                rsample += (2 * Math.random() - 1) * noiseVol;
+            }
+
+            // Add to (mono) channel buffer
+            noteBuf[j] = (80 * rsample * e) | 0;
+        }
+
+        return noteBuf;
+    };
+
+
+    //--------------------------------------------------------------------------
+    // Private members
+    //--------------------------------------------------------------------------
+
+    // Array of oscillator functions
+    var mOscillators = [
+        osc_sin,
+        osc_square,
+        osc_saw,
+        osc_tri
+    ];
+
+    // Private variables set up by init()
+    var mSong, mLastRow, mCurrentCol, mNumWords, mMixBuf;
+
+
+    //--------------------------------------------------------------------------
+    // Initialization
+    //--------------------------------------------------------------------------
+
+    this.init = function (song) {
+        // Define the song
+        mSong = song;
+
+        // Init iteration state variables
+        mLastRow = song.endPattern - 2;
+        mCurrentCol = 0;
+
+        // Prepare song info
+        mNumWords =  song.rowLen * song.patternLen * (mLastRow + 1) * 2;
+
+        // Create work buffer (initially cleared)
+        mMixBuf = new Int32Array(mNumWords);
+    };
+
+
+    //--------------------------------------------------------------------------
+    // Public methods
+    //--------------------------------------------------------------------------
+
+    // Generate audio data for a single track
+    this.generate = function () {
+        // Local variables
+        var i, j, b, p, row, col, n, cp,
+            k, t, lfor, e, x, rsample, rowStartSample, f, da;
+
+        // Put performance critical items in local variables
+        var chnBuf = new Int32Array(mNumWords),
+            instr = mSong.songData[mCurrentCol],
+            rowLen = mSong.rowLen,
+            patternLen = mSong.patternLen;
+
+        // Clear effect state
+        var low = 0, band = 0, high;
+        var lsample, filterActive = false;
+
+        // Clear note cache.
+        var noteCache = [];
+
+         // Patterns
+         for (p = 0; p <= mLastRow; ++p) {
+            cp = instr.p[p];
+
+            // Pattern rows
+            for (row = 0; row < patternLen; ++row) {
+                // Execute effect command.
+                var cmdNo = cp ? instr.c[cp - 1].f[row] : 0;
+                if (cmdNo) {
+                    instr.i[cmdNo - 1] = instr.c[cp - 1].f[row + patternLen] || 0;
+
+                    // Clear the note cache since the instrument has changed.
+                    if (cmdNo < 14) {
+                        noteCache = [];
+                    }
+                }
+
+                // Put performance critical instrument properties in local variables
+                var oscLFO = mOscillators[instr.i[13]],
+                    lfoAmt = instr.i[14] / 512,
+                    lfoFreq = Math.pow(2, instr.i[15] - 9) / rowLen,
+                    fxLFO = instr.i[16],
+                    fxFilter = instr.i[17],
+                    fxFreq = instr.i[18] * 43.23529 * 3.141592 / 44100,
+                    q = 1 - instr.i[19] / 255,
+                    dist = instr.i[20] * 1e-5,
+                    drive = instr.i[21] / 32,
+                    panAmt = instr.i[22] / 512,
+                    panFreq = 6.283184 * Math.pow(2, instr.i[23] - 9) / rowLen,
+                    dlyAmt = instr.i[24] / 255,
+                    dly = instr.i[25] * rowLen;
+
+                // Calculate start sample number for this row in the pattern
+                rowStartSample = (p * patternLen + row) * rowLen;
+
+                // Generate notes for this pattern row
+                for (col = 0; col < 4; ++col) {
+                    n = cp ? instr.c[cp - 1].n[row + col * patternLen] : 0;
+                    if (n) {
+                        if (!noteCache[n]) {
+                            noteCache[n] = createNote(instr, n);
+                        }
+
+                        // Copy note from the note cache
+                        var noteBuf = noteCache[n];
+                        for (j = 0, i = rowStartSample * 2; j < noteBuf.length; j++, i += 2) {
+                          chnBuf[i] += noteBuf[j];
+                        }
+                    }
+                }
+
+                // Perform effects for this pattern row
+                for (j = 0; j < rowLen; j++) {
+                    // Dry mono-sample
+                    k = (rowStartSample + j) * 2;
+                    rsample = chnBuf[k];
+
+                    // We only do effects if we have some sound input
+                    if (rsample || filterActive) {
+                        // State variable filter
+                        f = fxFreq;
+                        if (fxLFO) {
+                            f *= oscLFO(lfoFreq * k) * lfoAmt + 0.5;
+                        }
+                        f = 1.5 * Math.sin(f);
+                        low += f * band;
+                        high = q * (rsample - band) - low;
+                        band += f * high;
+                        rsample = fxFilter == 3 ? band : fxFilter == 1 ? high : low;
+
+                        // Distortion
+                        if (dist) {
+                            rsample *= dist;
+                            rsample = rsample < 1 ? rsample > -1 ? osc_sin(rsample*.25) : -1 : 1;
+                            rsample /= dist;
+                        }
+
+                        // Drive
+                        rsample *= drive;
+
+                        // Is the filter active (i.e. still audiable)?
+                        filterActive = rsample * rsample > 1e-5;
+
+                        // Panning
+                        t = Math.sin(panFreq * k) * panAmt + 0.5;
+                        lsample = rsample * (1 - t);
+                        rsample *= t;
+                    } else {
+                        lsample = 0;
+                    }
+
+                    // Delay is always done, since it does not need sound input
+                    if (k >= dly) {
+                        // Left channel = left + right[-p] * t
+                        lsample += chnBuf[k-dly+1] * dlyAmt;
+
+                        // Right channel = right + left[-p] * t
+                        rsample += chnBuf[k-dly] * dlyAmt;
+                    }
+
+                    // Store in stereo channel buffer (needed for the delay effect)
+                    chnBuf[k] = lsample | 0;
+                    chnBuf[k+1] = rsample | 0;
+
+                    // ...and add to stereo mix buffer
+                    mMixBuf[k] += lsample | 0;
+                    mMixBuf[k+1] += rsample | 0;
+                }
+            }
+        }
+
+        // Next iteration. Return progress (1.0 == done!).
+        mCurrentCol++;
+        return mCurrentCol / 8;
+    };
+
+    // Create a WAVE formatted Uint8Array from the generated audio data
+    this.createWave = function() {
+        // Create WAVE header
+        var l1 = mNumWords * 2 - 8;
+        var l2 = l1 - 36;
+        var headerLen = 44;
+        var wave = new Uint8Array(headerLen + mNumWords * 2);
+        wave.set(
+            [82,73,70,70,
+             l1 & 255,(l1 >> 8) & 255,(l1 >> 16) & 255,(l1 >> 24) & 255,
+             87,65,86,69,102,109,116,32,16,0,0,0,1,0,2,0,
+             68,172,0,0,16,177,2,0,4,0,16,0,100,97,116,97,
+             l2 & 255,(l2 >> 8) & 255,(l2 >> 16) & 255,(l2 >> 24) & 255]
+        );
+
+        // Append actual wave data
+        for (var i = 0, idx = headerLen; i < mNumWords; ++i) {
+            // Note: We clamp here
+            var y = mMixBuf[i];
+            y = y < -32767 ? -32767 : (y > 32767 ? 32767 : y);
+            wave[idx++] = y & 255;
+            wave[idx++] = (y >> 8) & 255;
+        }
+
+        // Return the WAVE formatted typed array
+        return wave;
+    };
+
+    // Get n samples of wave data at time t [s]. Wave data in range [-2,2].
+    this.getData = function(t, n) {
+        var i = 2 * Math.floor(t * 44100);
+        var d = new Array(n);
+        for (var j = 0; j < 2*n; j += 1) {
+            var k = i + j;
+            d[j] = t > 0 && k < mMixBuf.length ? mMixBuf[k] / 32768 : 0;
+        }
+        return d;
+    };
+};
+
diff --git a/201410_-_Sine_City/sine-city-ori.html b/201410_-_Sine_City/sine-city-ori.html
new file mode 100644
index 0000000..7b94824
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-ori.html
@@ -0,0 +1,5 @@
+<body>
+<script language="javascript" src="music.js"></script>
+<script language="javascript" src="player-small.js"></script>
+<script language="javascript" src="sine-city-ori.js"></script>
+
diff --git a/201410_-_Sine_City/sine-city-ori.js b/201410_-_Sine_City/sine-city-ori.js
new file mode 100644
index 0000000..75c0928
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-ori.js
@@ -0,0 +1,1665 @@
+var USE_SYNTH = 0;
+
+// Vector stuff
+function vecOp(code) {
+	return eval('(function(o,a,b){for(var i=o.length;--i>=0;)' + code + ';return o})')
+}
+function vomNew(s) {
+	return new Float32Array(s)
+}
+var vecDot = function(a,b) {
+	var s = 0;
+	for ( var i in a ) {
+		s += a[i]*b[i];
+	}
+	return s;
+};
+var vecLen = function(a) {
+	return Math.sqrt( vecDot(a,a) )
+};
+var vecNorm = function(o,a) {
+	var l = vecLen(a);
+	return l ? vecScale(o,a,1/l) : vecCopy(o,a);
+};
+var vecCross = function(o,a,b) {
+	return vecSet(o,
+		a[1]*b[2]-a[2]*b[1] ,
+		a[2]*b[0]-a[0]*b[2] ,
+		a[0]*b[1]-a[1]*b[0]
+	);
+};
+var vecs2Mat3 = function(o,a,b,c){
+	for ( var i = 0 ; i < 3 ; i ++ ) {
+		o[i*3+0] = a[i];
+		o[i*3+1] = b[i];
+		o[i*3+2] = c[i];
+	}
+};
+var vecSet = vecOp('o[i]=arguments[i+1]') ,
+    vecCopy = vecOp('o[i]=a[i]') ,
+    vecAdd = vecOp('o[i]=a[i]+b[i]') ,
+    vecSub = vecOp('o[i]=a[i]-b[i]') ,
+    vecScale = vecOp('o[i]=a[i]*b');
+
+var luma = [.299 , .587 , .114];
+
+
+// Shaders
+var shaderBits = {
+	precision: 'precision highp float;' ,
+	inPosition: 'attribute vec2 inPosition;' ,
+	voTexCoords: 'varying vec2 voTexCoords;' ,
+	raymarchVSMain: [
+		"void main( )" ,
+		"{" ,
+			"gl_Position = vec4( inPosition , 0. , 1. );" ,
+			"voTexCoords = inPosition;" ,
+		"}"
+	].join('') ,
+	rmUtils: [
+		"const vec3 LUMA = vec3( " , shaderVec(luma) , " );" ,
+
+		"struct Material" ,
+		"{" ,
+			"vec3 albedo;" ,
+			"float metallic;" ,
+			"float smoothness;" ,
+			"float r0;" ,
+		"};" ,
+
+		"float hash( float n )" ,
+		"{" ,
+			"return fract(sin(n)*43758.5453);" ,
+		"}" ,
+
+		"float noise( vec3 x )" ,
+		"{" ,
+			"vec3 p = floor(x);" ,
+			"vec3 f = fract(x);" ,
+
+			"f = f*f*(3.0-2.0*f);" ,
+			"float n = p.x + p.y*57.0 + 113.0*p.z;" ,
+			"return mix(mix(mix( hash(n+  0.0), hash(n+  1.0),f.x)," ,
+					"mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y)," ,
+				"   mix(mix( hash(n+113.0), hash(n+114.0),f.x)," ,
+					"mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);" ,
+		"}" ,
+
+		"float atan2( in float y , in float x )" ,
+		"{" ,
+			"return ( x == 0.0" ,
+				"? ( y > 0.0 ? ( 3.14159 * .5 ) : ( -3.14159 * .5 ) )" ,
+				": atan( y , x ) );",
+		"}" ,
+
+		"vec2 solve(float a, float b, float c)" ,
+		"{" ,
+			"float d = b * b - 4. * a * c;" ,
+			"if ( d < 0. ) {" ,
+				"return vec2(-1.);" ,
+			"}" ,
+			"d=sqrt(d);" ,
+			"vec2 s = -.5*vec2(b+d,b-d)/a;" ,
+			"return vec2(min(s.x,s.y),max(s.x,s.y));" ,
+		"}" ,
+
+		"float lx( vec2 v , float x )" ,
+		"{" ,
+			"vec2 s = pow(abs(v),vec2(x));" ,
+			"return pow( s.x + s.y , 1. / x );" ,
+		"}" ,
+
+		"mat2 rot( float angle )" ,
+		"{" ,
+			"vec2 cs = vec2( cos(angle),sin(angle));" ,
+			"return mat2( -cs.x,cs.y,cs.y,cs.x );" ,
+		"}" ,
+
+		"float schlick( vec3 hv , vec3 cd , float r0, float smooth )" ,
+		"{" ,
+			"float d = clamp((1. - dot( hv, -cd )), 0., 1.) , d2 = d * d;" ,
+			"return r0 + (1. - r0) * d * d2 * d2 * smooth;" ,
+		"}" ,
+
+		"float getSpecular(vec3 i, vec3 l, vec3 n, float smooth)" ,
+		"{          " ,
+			"float rDotL = max(dot(reflect(i, n), l), 0.0);" ,
+			"float sp = exp2(4.0 + 6.0 * smooth);" ,
+			"float si = (sp + 2.0) * 0.125;" ,
+			"return pow(rDotL, sp) * si;" ,
+		"}" ,
+
+	].join('\n'),
+	beadCyl: [
+		"float beadCyl( vec3 p )" ,
+		"{" ,
+			"vec2 q = mod( p.xy , vec2(15.) ) - vec2(7.5);" ,
+			"return length(q) - .5 + .05 * sin(p.z*9.42477);" ,
+		"}"
+	].join('\n'),
+};
+
+var shaders = {
+	raymarchVS: [ 'v' ,
+		'inPosition' , 'voTexCoords' , 'raymarchVSMain' ] ,
+};
+var programs = {
+};
+
+function shaderFloat( v ) {
+	return '' + v + ( v == Math.floor(v) ? '.' : '' );
+}
+function shaderVec( v ) {
+	return v.map(shaderFloat).join(',');
+}
+
+function compileShader( def ) {
+	var type = def[0] == 'f' ? glCtx.FRAGMENT_SHADER : glCtx.VERTEX_SHADER;
+	var src = '';
+	for ( var i = 1 ; i < def.length ; i ++ ) {
+		src += shaderBits[ def[ i ] ];
+	}
+
+	var shader = glCtx.createShader( type );
+	glCtx.shaderSource( shader , src );
+	glCtx.compileShader( shader );
+	if (!glCtx.getShaderParameter(shader, glCtx.COMPILE_STATUS)) {
+		src = src.split( /\n/ );
+		for ( var i in src ) {
+			var j = parseInt(i)+1;
+			src[i] = j + ": " + src[i];
+		}
+		throw "SHADER ERROR\n" + glCtx.getShaderInfoLog(shader) + "\n" + src.join('\n');
+	}
+
+
+	return shader;
+}
+
+function compileShaders( ) {
+	for ( var name in shaders ) {
+		shaders[name] = compileShader( shaders[name] );
+	}
+}
+
+function buildProgram( name ) {
+	var p = glCtx.createProgram( );
+	var d = programs[name];
+	var ul = d.shift();
+	while( d.length ) {
+		glCtx.attachShader( p , shaders[ d.shift() ] );
+	}
+	glCtx.bindAttribLocation( p , 0 , "inPosition" );
+	glCtx.linkProgram( p );
+	var nul = {};
+	while ( ul.length ) {
+		d = ul.shift();
+		nul[d] = glCtx.getUniformLocation( p , 'u' + d );
+	}
+	programs[name] = [p,nul];
+}
+
+function buildPrograms( ) {
+	compileShaders( );
+	for ( var name in programs ) {
+		buildProgram(name);
+	}
+}
+
+
+// Raymarchers
+
+var materials = [
+	{
+		albedo: [.05,.05,.05] ,
+		metallic: .7 ,
+		smoothness: .02 ,
+		r0: .01
+	} , {
+		albedo: [ .2,.2,.2 ] ,
+		noise: [ .1,.1,.1] ,
+		noiseScale: 5 ,
+		metallic: .7 ,
+		smoothness: .9 ,
+		r0: .01
+	} , {
+		albedo: [ 1,1,1 ] ,
+		metallic: .5 ,
+		smoothness: .4 ,
+		r0: .02
+	} , {
+		albedo: [ 3,0,0 ] ,
+		noise: [.6,0,0],
+		noiseScale: 6 ,
+		metallic: .3 ,
+		smoothness: .1 ,
+		r0: .6
+	} , {
+		albedo: [ 0,2,0 ] ,
+		noise: [0,.2,0],
+		noiseScale: 15 ,
+		metallic: .9 ,
+		smoothness: .5 ,
+		r0: .4
+	} , {
+		albedo: [ 3,1.5,0 ] ,
+		noise: [.3,.6,0],
+		noiseScale: .3 ,
+		metallic: .95 ,
+		smoothness: .6 ,
+		r0: .9
+	} , {
+		albedo: [ .1,.1,.1 ] ,
+		noise: [3,3,3] ,
+		noiseScale: 3,
+		metallic: 0 ,
+		smoothness: .04 ,
+		r0: .002
+	} , {
+		albedo: [ 0,1.5,2 ] ,
+		metallic: .9 ,
+		smoothness: .3 ,
+		r0: .4
+	}
+];
+
+
+var raymarchers = {
+	tunnel: {
+		extraUniforms: {BallOffset:'float'} ,
+		extraBits: [] ,
+
+		maxDistance: 100 ,
+		epsilon: .025 ,
+		epsilonMultiplier: 1 ,
+		step: .7 ,
+		depth: 64 ,
+
+		normalDelta: .0005 ,
+		noiseScale: .5 ,
+		reflectionDistance: .3 ,
+
+		fog: .4 ,
+		fogDensity: .015 ,
+
+		aoSteps: 4 ,
+		aoDelta: 2 ,
+		aoWeight: .75 ,
+
+		materials: [0,1,2,3] ,
+
+		setCamera: function( ctx ) {
+			var z = ctx.time*30;
+			vecSet(ctx.camPos,0,0,z);
+			z += 5;
+			vecSet(ctx.lookAt,-Math.sin(z*.05),-.7*Math.cos(z*.033),z);
+			vecSet(ctx.up,0,1,0);
+			ctx.toNearPlane = 2;
+		} ,
+		map: [
+			"vec3 q = p + .1 * ( sin(p.zxy*.17+uTime*.5)+sin(p.yzx*.7+uTime*1.5) )*8.5*(1. + cos(sin(p.z * .1 ) + p.z * .3 ));" ,
+			"float b = 14. - length( q.xy )," ,
+			"ap = atan2(p.y,p.x),c,m,n=8.35-uBallOffset*1.35;" ,
+			"q = vec3( 9.*(mod(ap+p.z*.02,.628)-.314) , length(p.xy)-9. , mod(p.z,12.56)-6.28);" ,
+			"c = length(q.xy)-.25+.1*cos(p.z*8.+uTime*.1);" ,
+			"c = min(c,length(q.yz)-.5);",
+			"q = vec3(n*(mod(ap+p.z*.02,1.256636)-.628318),q.y+9.-n,mod(p.z,62.8318)-31.4159);" ,
+			"m = step(c,b)+1.;" ,
+			"b=min(c,b);" ,
+			"c=length(q) - 1.3;" ,
+			"if(c<b){b=c;m=3.;}" ,
+			"q.y+=n-9.;" ,
+			"c = lx(q.yz,8.)-2.;" ,
+			"if(c<b){b=c;m=0.;}" ,
+			"return vec2(b,m);"
+		].join('\n') ,
+		lights: [
+			{
+				attenuation: .25 ,
+				vRadius: 0 ,
+				update: function(ctx,lctx) {
+					vecSet(lctx.pos , 0 , -.5 , ctx.time*30-.5);
+					vecSet(lctx.colour,3,3,3);
+					lctx.distance = 30;
+					return true;
+				}
+			} , {
+				attenuation: .5 ,
+				vRadius: .5 ,
+				update: function(ctx,lctx) {
+					vecSet(lctx.pos , 4*Math.sin(ctx.time*.5)*Math.cos(ctx.time*.7) ,
+							3*Math.cos(ctx.time*1.5),
+							ctx.time*30+14+16*Math.sin(ctx.time*3.3)*Math.cos(ctx.time*.77)
+					);
+					vecSet(lctx.colour,1,1,1);
+					lctx.distance = 15;
+					return true;
+				}
+			}
+		] ,
+	} ,
+	fractals: {
+		extraUniforms: {BallSize:'float',TimeEffect:'float'} ,
+		extraBits: [] ,
+
+		maxDistance: 6 ,
+		epsilon: .00025 ,
+		epsilonMultiplier: 1.08 ,
+		step: .7 ,
+		depth: 100 ,
+
+		normalDelta: .000008 ,
+		noiseScale: 10 ,
+		reflectionDistance: .03 ,
+
+		fog: 2.1 ,
+		fogDensity: .2 ,
+
+		aoSteps: 6 ,
+		aoDelta: .4 ,
+		aoWeight: 5 ,
+
+		materials: [0,2,5] ,
+
+		setCamera: function( ctx ) {
+			var z = ctx.time*30;
+			vecSet(ctx.camPos,5*Math.sin(ctx.time*.1),10*Math.cos(ctx.time*.2),7.5);
+			vecSet(ctx.lookAt,0,0,ctx.camPos[2]-2);
+			vecSet(ctx.up,0,0,1);
+			ctx.toNearPlane = 3;
+		} ,
+		map: [
+			"const vec3 CSize=vec3(.58,.9,1.1);" ,
+			"float scale=1.,k,m;" ,
+			"vec3 fp=p;" ,
+			"for(int i=0;i<7;i++){" ,
+				"p=2.*clamp(p,-CSize,CSize)-p;" ,
+				"k=max((1.3+uTimeEffect*.1*cos(uTime*.5))/dot(p,p),1.);" ,
+				"p*=k;" ,
+				"scale*=k;" ,
+			"}" ,
+			"k=length(p.xy);" ,
+			"vec2 ds=vec2(k-3.,-k*p.z/length(p)-2.*log(1.+.01*d))/abs(scale);" ,
+			"k=max(ds.x,ds.y);" ,
+			"m=step(ds.y,ds.x);" ,
+			// FIXME!
+			"vec3 ctr=uCamPos-vec3(.1,.3,-.4)*uCamMat;" ,
+			"fp-=ctr;fp+=.25*sin(p*1.);" ,
+			"ds.x = length(fp)-.1*uBallSize;" ,
+			"if (ds.x < k ) { k = ds.x ; m = 2.; }" ,
+			"return vec2(k,m);"
+		].join('\n') ,
+		lights: [
+			{
+				attenuation: .05 ,
+				update: function(ctx,lctx) {
+					vecCopy(lctx.pos,ctx.camPos);
+					lctx.pos[2]+=2;
+					vecSet(lctx.colour,1,1,1);
+					lctx.distance = 3;
+					return true;
+				}
+			}
+		] ,
+	} ,
+	squares: {
+		extraUniforms: [] ,
+		extraBits: ['beadCyl'] ,
+
+		maxDistance: 100 ,
+		epsilon: .000025 ,
+		epsilonMultiplier: 1 ,
+		step: .75 ,
+		depth: 80 ,
+
+		normalDelta: .00005 ,
+		noiseScale: .5 ,
+		reflectionDistance: .3 ,
+
+		fog: 3 ,
+		fogDensity: .01 ,
+
+		aoSteps: 4 ,
+		aoDelta: .75 ,
+		aoWeight: 4.75 ,
+
+		materials: [6,0,4] ,
+
+		setCamera: function( ctx ) {
+			var z = ctx.time*30;
+			vecSet(ctx.camPos,Math.cos(ctx.time)*40.,0.,Math.sin(ctx.time*.5)*80.);
+			vecSet(ctx.lookAt,0,0,-100);
+			vecSet(ctx.up,0,1,0);
+			ctx.toNearPlane = 2.5;
+		} ,
+		map: [
+			"p.xy*=rot(d*.009 );" ,
+			"vec3 q;" ,
+
+			"float y,m,x = beadCyl( p.xzy );" ,
+			"x = min( x , beadCyl( p ) );" ,
+			"x = min( x , beadCyl(p.yzx ) );" ,
+
+			"q = mod( p , vec3(15.) ) - vec3(7.5);" ,
+			"y = max(length(max(abs(q) - vec3(2.5),vec3(0.))) - .25 , 3.5 - length(q) );" ,
+			"m = step(y,x);" ,
+			"x = min(x,y);" ,
+			"y = length(q+.1*sin(q*5.5+uTime))-2.;" ,
+			"if (y<x) {" ,
+				"x = y;" ,
+				"m=2.;" ,
+			"}" ,
+			"return vec2( x , m );"
+		].join('\n') ,
+		lights: [
+			{
+				attenuation: .05 ,
+				update: function(ctx,lctx) {
+					vecCopy(lctx.pos,ctx.camPos);
+					vecSet(lctx.colour,1,1,1);
+					lctx.distance = 30;
+					return true;
+				}
+			}
+		] ,
+	} ,
+	balls: {
+		extraUniforms: {EffectTime:'float'} ,
+
+		maxDistance: 20 ,
+		epsilon: .0005 ,
+		epsilonMultiplier: 1.0 ,
+		step: .6 ,
+		depth: 128 ,
+
+		normalDelta: .0001 ,
+		noiseScale: .5 ,
+		reflectionDistance: .002 ,
+
+		fog: .01 ,
+		fogDensity: .08 ,
+
+		aoSteps: 4 ,
+		aoDelta: .5 ,
+		aoWeight: 1.75 ,
+
+		materials: [2,7] ,
+
+		setCamera: function( ctx ) {
+			var z = ctx.time*30;
+			vecSet(ctx.camPos,Math.cos(ctx.time)*12,8,Math.sin(ctx.time)*12);
+			vecSet(ctx.lookAt,1,0,0);
+			vecSet(ctx.up,0,1,0);
+			ctx.toNearPlane = 2.5;
+		} ,
+
+		map: [
+			"float t = uEffectTime;" ,
+			"vec3 r = p;" ,
+			"r.xz = mod(r.xz,8.)-4.;" ,
+			"r.yz *= rot(t+.1*d);" ,
+			"r.xy *= rot(t*.5+.2*d);" ,
+			"r.y *= .9 + .1 * sin(t * 5.);" ,
+			"float a = max( length(r)-3. , -min( length(r)-2.8 , " ,
+				"max(mod(r.y,.8)-.4 , -mod(r.y+.4,.8)+.4)));" ,
+			"float b = p.y+1.+sin(p.x*4.+t*2.)*sin(p.z+t)*.1;" ,
+			"float h = clamp( .5+.5*(b-a)/1., .0, 1. );" ,
+			"a = mix(b,a,h)-1.*h*(1.-h);" ,
+			"r=p;" ,
+			"r.xz = mod(r.xz,8.)-4.;" ,
+			"r /= 1.25 + .25 * sin(t*5.);" ,
+			"r.xy *= rot(t*5.);" ,
+			"r.yz *= rot(t*2.5);" ,
+			"b = max( length(r)-1. , .04-length(max(abs(mod(r,.5)-.25) - vec3(.15),vec3(0.))) );" ,
+			"return vec2( min(a,b) , step(b,a) );"
+		].join('\n') ,
+		lights: [
+			{
+				attenuation: .02 ,
+				update: function(ctx,lctx) {
+					vecCopy(lctx.pos,ctx.camPos);
+					vecSet(lctx.colour,.6,.6,.6);
+					lctx.distance = 30;
+					return true;
+				}
+			},{
+				attenuation: .05 ,
+				vRadius: .5 ,
+				update: function(ctx,lctx) {
+					vecSet(lctx.pos,Math.cos(ctx.time*2)*5,0,Math.sin(ctx.time*2)*5);
+					vecSet(lctx.colour,1,1,1);
+					lctx.distance = 4;
+					return true;
+				}
+			} , {
+				attenuation: .05 ,
+				vRadius: .5 ,
+				update: function(ctx,lctx) {
+					vecSet(lctx.pos,-Math.cos(ctx.time*2)*5,0,-Math.sin(ctx.time*2)*5);
+					vecSet(lctx.colour,1,1,1);
+					lctx.distance = 4;
+					return true;
+				}
+			}
+		] ,
+	}
+};
+
+var lightFunc = function(intensity,distance) {
+	return function(ctx,lctx) {
+		vecCopy(lctx.pos,ctx.camPos);
+		vecSet(lctx.colour,intensity,intensity,intensity);
+		lctx.distance = distance;
+		return true;
+	}
+};
+var tun1CamCommon = function(ctx,dir) {
+	var z = ctx.time*6;
+	vecSet(ctx.camPos,-6,0,z);
+	vecSet(ctx.lookAt,1,0,z);
+	vecSet(ctx.up,0,1,0);
+	ctx.greyMix = 1;
+	ctx.extras[0] = '1f(p.BallOffset,0)';
+	return ctx.stepTime / dir.time;
+};
+var desyncFunc = function(desync) {
+	return function(ctx,tt) {
+		var z = ctx.stepTime / tt;
+		ctx.desync = -z * desync;
+		if ( desync > 0 ) {
+			ctx.desync += desync;
+		}
+		ctx.desync *= Math.random( ) * .25 + .75;
+	};
+};
+var balls1CamFunc = function(lax,laz,desync) {
+	var dsf = desyncFunc(desync);
+	return function(ctx) {
+		var z = ctx.time*3;
+		vecSet(ctx.camPos,0,4,z);
+		vecSet(ctx.lookAt,lax,0,z+laz);
+		vecSet(ctx.up,0,0,1);
+		ctx.fade = 0;
+		dsf(ctx,this.time);
+	};
+};
+var balls2CamCommon = function(ctx) {
+	var z = ctx.time*5;
+	vecSet(ctx.camPos,Math.cos(ctx.time)*12,8,Math.sin(ctx.time)*12+z);
+	vecSet(ctx.lookAt,1,0,z);
+	vecSet(ctx.up,0,1,0);
+	ctx.toNearPlane = 2.5;
+	z = ctx.time - direction[43].startTime;
+	ctx.extras[0] = '1f(p.EffectTime,'+z+')';
+};
+var balls2LightFunc = function(scale) {
+	return function(ctx,lctx) {
+		var z = ctx.time*30;
+		vecSet(lctx.pos,scale*Math.cos(ctx.time*2)*5,3,scale*Math.sin(ctx.time*2)*5+z);
+		vecSet(lctx.colour,1,1,1);
+		lctx.distance = 4;
+		return true;
+	};
+};
+var fract1CamCommon = function(ctx) {
+	var z = ctx.time;
+	vecSet(ctx.camPos,4,2.5+.025*z,6.7);
+	vecSet(ctx.lookAt,0,2.5-.05*z,6.7);
+	vecSet(ctx.up,0,0,1);
+	ctx.extras = [ '1f(p.BallSize,0)' , '1f(p.TimeEffect,0)' ];
+	ctx.toNearPlane = 3;
+};
+var fract1CamFunc = function(desync) {
+	var dsf = desyncFunc(desync);
+	return function(ctx){
+		fract1CamCommon(ctx);
+		dsf(ctx,this.time);
+	};
+};
+var fract2CamCommon = function(ctx,bs) {
+	vecSet(ctx.camPos,5*Math.sin(ctx.time*.2),9*Math.cos(ctx.time*.41),7.8);
+	vecCopy(ctx.lookAt,ctx.camPos);
+	ctx.lookAt[0] = Math.cos(ctx.time*.2);
+	ctx.lookAt[1] = Math.sin(ctx.time*.33);
+	ctx.lookAt[2] -= 2;
+	vecSet(ctx.up,0,0,1);
+	ctx.toNearPlane = 3;
+	ctx.extras = [ '1f(p.BallSize,'+bs+')' , '1f(p.TimeEffect,1)' ];
+};
+
+var drawText = function(str,x) {
+	twoDCtx.shadowBlur = c2height/5;
+	twoDCtx.fillText( str , x , c2height / 2 );
+	twoDCtx.shadowBlur = 0;
+	twoDCtx.strokeText( str , x , c2height / 2 );
+};
+var titleText = function(str,shake,alpha,r,g,b) {
+	drawText( str , canvasWidth/15 );
+	vecSet( context.text , 1 - c2rHeight + Math.random() * shake - shake * .5 , alpha , c2rHeight );
+	vecSet( context.textColour , r , g , b );
+};
+var greetings = "Greetings to ... Mog, Sycop, Tim & Wullon ... Adinpsz ... Alcatraz ... ASD ... Bits'n'Bites ... Brain Control ... Cocoon ... Conspiracy ... Ctrl+Alt+Test ... Fairlight ... Farbrausch ... Kewlers ... LNX ... Loonies ... Mercury ... Popsy Team ... Razor 1911 ... RGBA ... 7th Cube ... Still ... TPOLM ... TRBL ... Umlaut Design ... X-Men ... Youth Uprising ... Everyone here at DemoJS 2014!";
+var greetingsText = function() {
+	var t = ( context.time - direction[34].startTime ) * canvasWidth * .5;
+	drawText( greetings , canvasWidth - t );
+	vecSet( context.text , 1 - c2rHeight + Math.random() * .02 - .01 , 1 , c2rHeight );
+	vecSet( context.textColour , 1 , 1 , 1 );
+};
+
+var squaresCam = function(ctx) {
+	var t = ctx.time - direction[25].startTime;
+	var z = t*10 - 80;
+	vecSet(ctx.camPos,z,0,0);
+	vecSet(ctx.lookAt,z+Math.cos(t*.5) * 80,Math.sin(t*.25)*40,100);
+	vecSet(ctx.up,0,1,0);
+};
+
+var squaresCam2 = function(ctx,s) {
+	var t = ctx.time - direction[s].startTime;
+	var z = t*20 - 80;
+	vecSet(ctx.camPos,0,0,z);
+	vecSet(ctx.lookAt,Math.cos(t*.5) * 80,Math.sin(t*.25)*40,z+100);
+	vecSet(ctx.up,Math.sin(t),Math.cos(t),0);
+	ctx.desync = Math.random() * .025 - .0125;
+};
+
+var tunnelLight = function(ctx,lctx) {
+	vecAdd(lctx.pos,vecNorm(lctx.pos,vecScale(lctx.pos,ctx.lookAt,-1)),ctx.camPos);
+	lctx.pos[1] -= .5;
+	vecSet(lctx.colour,3,3,3);
+	lctx.distance = 30;
+	return true;
+};
+var tunnelCam = function(ctx,mul) {
+	var z = ctx.time*30*ctx.tunMul;
+	vecSet(ctx.camPos,1.1*Math.cos(z*.1),Math.sin(z*.02),z);
+	z += 5;
+	vecSet(ctx.lookAt,-Math.sin(z*.05),-.7*Math.cos(z*.033),z);
+	vecSet(ctx.up,0,1,0);
+	ctx.toNearPlane = 2;
+};
+var tunnelLightBall = function(ctx,lctx) {
+	vecSet(lctx.pos , 4*Math.sin(ctx.time*.5)*Math.cos(ctx.time*.7) ,
+			3*Math.cos(ctx.time*1.5),
+			ctx.time*30*ctx.tunMul+14+16*Math.sin(ctx.time*3.3)*Math.cos(ctx.time*.77)
+	);
+	vecSet(lctx.colour,1,1,1);
+	lctx.distance = 15;
+	return true;
+};
+
+var direction = [
+	{
+		// Music rows
+		rows: 36 ,
+		// Raymarcher id
+		rm: 'tunnel' ,
+		setGlobals: function( ctx ) {
+			var z = tun1CamCommon(ctx,this);
+			z *= z*z;
+			ctx.fade = 1 - z;
+			ctx.toNearPlane = 5;
+		} ,
+		lights: [
+			lightFunc(3,20)
+		] ,
+		updateText: null
+	} , {
+		rows: 18 ,
+		rm: 'tunnel' ,
+		setGlobals: function( ctx ) {
+			var z = tun1CamCommon(ctx,this);
+			ctx.toNearPlane = 5 - 2.25 * z;
+			ctx.fade = 0;
+		} ,
+		lights: [
+			lightFunc(3,20)
+		] ,
+		updateText: null
+	} , {
+		rows: 36 ,
+		rm: 'tunnel' ,
+		setGlobals: function( ctx ) {
+			var z = tun1CamCommon(ctx,this);
+			ctx.toNearPlane = 2.75 - 2.25 * z;
+			ctx.fade = z;
+		} ,
+		lights: [
+			lightFunc(3,20)
+		] ,
+		updateText: null
+	} , {
+		rows: 18 ,
+		rm: 'balls' ,
+		setGlobals: function( ctx ) {
+			var z = ctx.time*3;
+			vecSet(ctx.camPos,0,4,z);
+			vecSet(ctx.lookAt,4,0,z);
+			vecSet(ctx.up,0,0,1);
+			z = ctx.stepTime / this.time;
+			z *= z*z;
+			ctx.fade = 1 - z;
+			ctx.toNearPlane = 2.5;
+		} ,
+		lights: [
+			lightFunc(.75,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc(4,0,0) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc(2,-2,0) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 6 , 0 , -.5 ) ,
+		lights: [
+			lightFunc(.5,4)
+		] ,
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 6 , 0 , .5 ) ,
+		lights: [
+			lightFunc(.5,4)
+		] ,
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 2 , 2 , -.2 ) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 2 , 2 , .2 ) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 2 , 5 , -.7 ) ,
+		lights: [
+			lightFunc(1,2)
+		] ,
+		updateText: null
+	} , {
+		rows: 7 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 2 , 2 , .7 ) ,
+		lights: [
+			lightFunc(1,2)
+		] ,
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 'balls' ,
+		setGlobals: function(ctx) {
+			var z = ctx.time*3;
+			ctx.fade = ctx.stepTime / this.time;
+			vecSet(ctx.camPos,0,4+ctx.fade*2,z);
+			vecSet(ctx.lookAt,2,0,z+2);
+			vecSet(ctx.up,0,0,1);
+			ctx.fadeColour = 1;
+		} ,
+		lights: [
+			lightFunc(1,2)
+		] ,
+		updateText: null
+	} , {
+		rows: 21 ,
+		rm: 'fractals' ,
+		setGlobals: function( ctx ) {
+			fract1CamCommon(ctx);
+			ctx.fadeColour = 1;
+			var z = ctx.stepTime / this.time;
+			ctx.fade = 1 - z*z*z;
+		} , lights : [
+			fractLight = function(ctx,lctx) {
+				vecCopy(lctx.pos,ctx.camPos);
+				lctx.pos[2]+=2;
+				vecSet(lctx.colour,1,1,1);
+				lctx.distance = 3;
+				return true;
+			}
+		],
+		updateText: null
+	} , {
+		rows: 14 ,
+		rm: 'fractals' ,
+		setGlobals: fract1CamFunc(0) ,
+		lights : [
+			fractLight
+		],
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'fractals' ,
+		setGlobals: fract1CamFunc(-.4) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 'fractals' ,
+		setGlobals: fract1CamFunc(.4) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'fractals' ,
+		setGlobals: fract1CamFunc(-.2) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 'fractals' ,
+		setGlobals: fract1CamFunc(.2) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 12 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract1CamCommon(ctx);
+			ctx.desync = -( 6 * ctx.stepTime / this.time ) % 1;
+			ctx.desync *= Math.random( ) * .25 + .75;
+		} ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract1CamCommon(ctx);
+			ctx.fadeColour = .4;
+			ctx.fade = ctx.stepTime / this.time;
+			ctx.toNearPlane = 3 - 2.5*Math.max(1,2*ctx.fade);
+			ctx.desync = ( 30 * ctx.fade ) % 1;
+			ctx.desync *= Math.random( ) * .15 + .85;
+		} ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'fractals' ,
+		setGlobals: neutral = function(ctx) {
+			fract1CamCommon(ctx);
+			ctx.fadeColour = .4;
+			ctx.fade = 1;
+			ctx.desync = 0;
+		} ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 12 ,
+		rm: 'fractals' ,
+		setGlobals: neutral ,
+		lights : [ fractLight ],
+		updateText: function() {
+			titleText( "TheT(ourist)" , .08 , 1 , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 12 ,
+		rm: 'fractals' ,
+		setGlobals: neutral ,
+		lights : [ fractLight ],
+		updateText: function() {
+			titleText( "TheT(ourist)" , .08 , 1 - context.stepTime / this.time , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 12 ,
+		rm: 'fractals' ,
+		setGlobals: neutral ,
+		lights : [ fractLight ],
+		updateText: function() {
+			titleText( "presents" , .08 , 1 - context.stepTime / this.time , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 20 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam(ctx);
+			ctx.toNearPlane = 2.5;
+			ctx.fade = 1 - ctx.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , context.stepTime / this.time , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 52 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam(ctx);
+			ctx.fade = 0;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , 1 , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 12 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx){
+			squaresCam(ctx);
+			var z = context.stepTime / this.time;
+			ctx.fadeColour = 1;
+			ctx.fade = Math.max(0,1-z*2);
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			var z = context.stepTime / this.time;
+			titleText( "Sine City" , .04 , 1 , 1 - z , 1 - z * .5 , 1 - z );
+		}
+	} , {
+		rows: 12 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam(ctx);
+			var z = context.stepTime / this.time;
+			ctx.desync = ( 1 - z ) * .7 + Math.random() * .025 - .0125;
+			ctx.greyMix = 1 - .5 * z;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , 1 , 0 , .5 , 0 );
+		}
+	} , {
+		rows: 9 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,29);
+			var z = context.stepTime / this.time;
+			ctx.fade = Math.max(0,1-z*1.5);
+			ctx.desync += ( z - 1 ) * .3;
+			ctx.greyMix = .5 - .5 * z;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , 1 - context.stepTime / this.time , 0 , .5 , 0 );
+		}
+	} , {
+		rows: 69 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,29);
+			ctx.greyMix = 0;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: null
+	} , {
+		rows: 11 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,29);
+			ctx.fadeColour = .2;
+			ctx.fade = context.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: null
+	} , {
+		rows: 11 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			ctx.tunMul = 1;
+			tunnelCam(ctx);
+			ctx.fade = 1 - context.stepTime / this.time;
+		} ,
+		lights : [ tunnelLight ],
+		updateText: null
+	} , {
+		rows: 17 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.fade = 0;
+			ctx.desync = (1.2 - 1.2 * context.stepTime / this.time) * (.98 + .04*Math.random());
+		} ,
+		lights : [ tunnelLight ],
+		updateText: null
+	} , {
+		rows: 18 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.desync = 0;
+			ctx.extras[0] = '1f(p.BallOffset,'+(context.stepTime / this.time) + ')';
+		} ,
+		lights : [ tunnelLight ],
+		updateText: greetingsText
+	} , {
+		rows: 36 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.fade = 1 - Math.min(4*context.stepTime / this.time,1);
+			ctx.extras[0] = '1f(p.BallOffset,1)';
+		} ,
+		lights : tunLights = [ tunnelLight , tunnelLightBall ],
+		updateText: greetingsText
+	} , {
+		rows: 33 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.fadeColour = .7;
+			ctx.fade = context.stepTime / this.time;
+			ctx.extras[0] = '1f(p.BallOffset,1)';
+			ctx.desync = -((4*ctx.fade)%1)*(.95+Math.random()*.1);
+		} ,
+		lights : tunLights ,
+		updateText: greetingsText
+	} , {
+		rows: 9 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,0);
+			ctx.fadeColour = 1;
+			ctx.fade = context.stepTime / this.time;
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 20 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,context.stepTime / this.time);
+			ctx.fade = 0;
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 31 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.fade = Math.min(0,1-5*context.stepTime / this.time);
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 5 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.fade = 1-context.stepTime / this.time;
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 18 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.fade = Math.min(0,1-5*context.stepTime / this.time);
+			ctx.desync = Math.max(0,1.6*context.stepTime / this.time - .8 )*(.95+Math.random()*.1);
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 12 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.fadeColour = .1;
+			ctx.fade = context.stepTime / this.time;
+			ctx.desync = .8*(1-ctx.fade)*(.9+Math.random()*.2);
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 22 ,
+		rm: 'balls' ,
+		setGlobals: function(ctx) {
+			balls2CamCommon(ctx);
+			ctx.fade = 1-context.stepTime / this.time;
+			ctx.desync = 0;
+		} ,
+		lights : ballsLights = [ lightFunc(.6,30) , balls2LightFunc(1),balls2LightFunc(-1) ],
+		updateText: greetingsText
+	} , {
+		rows: 59 ,
+		rm: 'balls' ,
+		setGlobals: function(ctx) {
+			balls2CamCommon(ctx);
+			ctx.fadeColour = .8;
+			ctx.fade = Math.max(0,1-(12*context.stepTime / this.time)%4);
+		} ,
+		lights : ballsLights,
+		updateText: greetingsText
+	} , {
+		rows: 8 ,
+		rm: 'balls' ,
+		setGlobals: function(ctx) {
+			balls2CamCommon(ctx);
+			ctx.fadeColour = .1;
+			ctx.fade = context.stepTime / this.time;
+			ctx.desync = .1-Math.random()*.2;
+		} ,
+		lights : ballsLights,
+		updateText: null
+	} , {
+		rows: 7 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			ctx.tunMul = 2;
+			tunnelCam(ctx);
+			ctx.fade = 1-context.stepTime / this.time;
+			ctx.desync = .1-Math.random()*.2;
+		} ,
+		lights : tunLights ,
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.desync = .1-Math.random()*.2;
+		} ,
+		lights : tunLights ,
+		updateText: null
+	} , {
+		rows: 10 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.desync = context.stepTime*4+.1-Math.random()*.2;
+			ctx.fadeColour = 1;
+			ctx.fade = context.stepTime / this.time;
+		} ,
+		lights : tunLights ,
+		updateText: null
+	} , {
+		rows: 10 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.desync = (context.time-direction[48].startTime)*4+.1-Math.random()*.2;
+			ctx.fade = 1-context.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	} , {
+		rows: 40 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.desync = -(context.time-direction[48].startTime)*6;
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	} , {
+		rows: 40 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.desync = (context.time-direction[48].startTime)*8;
+			ctx.fadeColour = 0;
+			ctx.fade = context.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	} , {
+		rows: 68 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.fade = 1
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	}
+];
+var t = 0;
+var BPM = 120;
+for ( var i in direction ) {
+	direction[ i ].startTime = t;
+	t += ( direction[i].time = direction[ i ].rows * 60 / ( BPM * 4 ) );
+	direction[ i ].endTime = t;
+}
+rows = t * BPM * 4 / 60;
+console.log( "endTime: " + t + " (rows: " + rows + "; patterns: " + Math.floor(rows/36) + " + " + (rows - 36*Math.floor(rows/36)) + " extra row(s))" );
+console.log( "len : " + direction.length );
+t = 0;
+
+function getMaterialsCode(indices,noiseScale)
+{
+	var code = 'Material getMaterial( vec3 pos , float index ) {\n'
+		+ 'Material m;';
+
+	for ( var i in indices ) {
+		if ( i > 0 ) {
+			code += 'else ';
+		}
+		var m = materials[ indices[i] ];
+		code += 'if ( index == ' + shaderFloat( i ) + ' ) {\n'
+			+ 'm.albedo = ';
+		if ( m.noiseScale ) {
+			code += 'mix( vec3(' + shaderVec( m.albedo ) + ') , vec3('
+				+ shaderVec( m.noise ) + ') , noise( pos * '
+				+ shaderFloat( noiseScale * m.noiseScale ) + ') )';
+		} else {
+			code += 'vec3(' + shaderVec( m.albedo ) + ')';
+		}
+		code += ';\nm.metallic=' + shaderFloat( m.metallic ) + ';\nm.smoothness='
+			+ shaderFloat( m.smoothness ) + ';\nm.r0=' + shaderFloat( m.r0 ) + ';\n}';
+	}
+
+	return code + 'return m;\n}\n';
+}
+
+function createRaymarcherCode( def , nLights ) {
+	var uniforms = [ 'CamMat' , 'CamPos' , 'Time' , 'Desync' , 'GreyMix' , 'Fade' , 'FadeColour' , 'TextParams' , 'TextColour' , 'Texture' ];
+	var code = shaderBits['precision']
+		+ shaderBits['voTexCoords']
+		+ [ 'uniform mat3 uCamMat;' ,
+		    'uniform vec3 uCamPos;' ,
+		    'uniform float uTime;' ,
+		    'uniform float uGreyMix;' ,
+		    'uniform float uFade;' ,
+		    'uniform float uFadeColour;' ,
+		    'uniform vec3 uTextParams;' ,
+		    'uniform vec3 uTextColour;' ,
+		    'uniform sampler2D uTexture;' ,
+		    'uniform float uDesync;'
+		  ].join('\n');
+	for ( var i in def.lights ) {
+		code += 'uniform vec3 uLightPos' + i + ', uLightColor' + i + ";\nuniform float uLightDistance" + i + ";\n";
+		uniforms.splice( uniforms.length , 0 , 'LightPos' + i , 'LightColor' + i , 'LightDistance' + i );
+	}
+	for ( var i in def.extraUniforms ) {
+		code += 'uniform ' + def.extraUniforms[i] + " u" + i + ";\n";
+		uniforms.push(i);
+	}
+	for ( var i in def.extraBits ) {
+		code += shaderBits[def.extraBits[i]];
+	}
+	code += shaderBits['rmUtils'];
+	code += 'vec2 cMap( vec3 p , float d ) {' + def.map
+		+ '}' + getMaterialsCode(def.materials,def.noiseScale)
+		+ [
+			"vec3 getNormal( vec3 hp , float d )" ,
+			"{" ,
+				"vec2 e = vec2(1.,-1.)*" , shaderFloat(def.normalDelta)  , ";" ,
+				"vec4 f = vec4(" ,
+					"cMap(hp+e.xyy,d).x," ,
+					"cMap(hp+e.yyx,d).x," ,
+					"cMap(hp+e.yxy,d).x," ,
+					"cMap(hp+e.xxx,d).x" ,
+				");" ,
+				"return normalize(f.x * e.xyy + f.y * e.yyx + f.z * e.yxy + f.w * e.xxx);" ,
+			"}" ,
+
+			"float ambientOcclusion(vec3 p, vec3 n, vec3 cp){" ,
+				"const int steps = ", def.aoSteps , ";" ,
+				"const float delta = ", shaderFloat( def.aoDelta ) , ";" ,
+
+				"float a = 0.0;" ,
+				"float weight = " , shaderFloat( def.aoWeight ) , ";" ,
+				"float m;" ,
+				"for(int i=1; i<=steps; i++) {" ,
+					"float d = (float(i) / float(steps)) * delta;" ,
+					"vec3 op = p + n * d;" ,
+					"a += weight*(d - cMap(op,distance(op,cp)).x);" ,
+					"weight *= 0.5;" ,
+				"}" ,
+				"return max(0.1 , 1.0 - clamp( pow(a , 1. ) , 0.0, 1.0) );" ,
+			"}" ,
+
+
+			"vec2 march( vec3 pos , vec3 dir , int nSteps)" ,
+			"{" ,
+				"float cd = 0. , e = " , shaderFloat( def.epsilon ) , ';' ,
+				"vec2 m;" ,
+
+				"for ( int i = 0 ; i < " , def.depth , " ; i++ ) {" ,
+					"m = cMap( pos + dir * cd , cd );" ,
+					"if ( m.x < e || i > nSteps || cd >" , shaderFloat( def.maxDistance ) , " ) {" ,
+						"break;" ,
+					"}" ,
+					"cd += m.x * " , shaderFloat( def.step ) , ";" ,
+					"e *= " , shaderFloat( def.epsilonMultiplier ) , ";" ,
+				"}" ,
+
+				"return vec2(cd,m.y);" ,
+			"}" ,
+
+			"void main( ) " ,
+			"{" ,
+				"vec3 tc = vec3(voTexCoords,1.);" ,
+				"tc.y += mod(uDesync,1.)*2.2;" ,
+				"if ( tc.y > 1. ) {" ,
+					"if ( tc.y < 1.2 ) discard;" ,
+					"tc.y -= 2.2;" ,
+				"}" ,
+				"tc.x *= 1.6;" ,
+				"vec3 dir = normalize( tc * uCamMat ) ," ,
+					"pos = uCamPos , outColor = vec3( 0. ) , " ,
+					"cMul = vec3( 1. ) , ld , l;" ,
+
+				"float ll;" ,
+				"for ( int j = 0 ; j < 2 ; j ++ ) {" ,
+					"vec3 col, nDir = dir , nPos = pos, ncMul = vec3(0.);" ,
+					"vec2 vl,r = march( pos , dir , " , def.depth , " / ( j + 1 ) );" ,
+					"if ( r.x < " , shaderFloat( def.maxDistance ) , " ) {" ,
+						"vec3 hp = pos + dir * r.x , n=getNormal( hp , r.x ),hDir;" ,
+						"nDir = reflect(dir,n);" ,
+						"hDir = normalize( nDir + dir );" ,
+						"float fog = " , shaderFloat( def.fogDensity ) , " * r.x;" ,
+						"fog *= fog*fog*1.442695;" ,
+						"fog = clamp( exp(-fog) , 0., 1. );" ,
+						"Material m = getMaterial( hp , r.y );" ,
+						"float occlusion = ambientOcclusion( hp , n , pos ) , " ,
+							"fresnel = schlick( hDir , dir , m.r0 , m.smoothness * .9 + .1 );" ,
+						"vec3 sCol = mix(vec3(1.),m.albedo/dot(LUMA,m.albedo),m.metallic) ," ,
+							"dc , sc;" ,
+						"col = vec3(0.);" ,
+		].join('\n');
+
+	for ( var l in def.lights ) {
+		var ld = def.lights[l];
+		code += [
+			"ld = uLightPos" + l + " - hp;" ,
+			"ll = length(ld);" ,
+			"ld /= ll;" ,
+			"ll = max( 1. , ll - uLightDistance" + l + ") * " , shaderFloat( ld.attenuation ) , ";" ,
+			"ll = 1. / max( 1. , ll * ll );" ,
+			"l = ll * max(dot(ld,n),0.) * uLightColor" + l + ";" ,
+			"dc = (1. - m.metallic) * m.albedo * occlusion;" ,
+			"sc = sCol * getSpecular( dir , ld , n , m.smoothness );" ,
+			"col += mix( dc , sc , fresnel ) * l;" 
+		].join('\n');
+		code += ";";
+	}
+	code += [
+						"ncMul = cMul * fog * normalize(sCol) * m.r0 * (m.smoothness * .9 + .1) * fresnel;" ,
+						"col = mix( vec3(" , shaderFloat(def.fog) , ") , col , fog );" ,
+						"nPos += normalize(nDir) * " , shaderFloat(def.reflectionDistance) , ";" ,
+					"} else {" ,
+						"col=vec3(" , shaderFloat(def.fog) , ');' ,
+					"}" ,
+	].join('\n');
+
+	for ( var l in def.lights ) {
+		var ld = def.lights[l];
+		var r = ld.vRadius;
+		if ( r ) {
+			code += [
+					"ld = pos - uLightPos" + l + ";" ,
+					"vl = solve(dot(dir,dir),2.*dot(ld,dir),dot(ld,ld)-" + shaderFloat(r*r) + ");" ,
+					"if ( vl.x > 0. && vl.y < r.x ) {" ,
+						"float fog = " , shaderFloat( def.fogDensity ) , " * vl.x;" ,
+						"fog *= fog*fog*1.442695;" ,
+						"fog = clamp( exp(-fog) , 0., 1. );" ,
+						"col += fog * uLightDistance" + l + " * uLightColor" + l + " * pow( (vl.y-vl.x) / " + shaderFloat(r*2) + " , 64. );" ,
+					"}"
+			].join( "\n" );
+		}
+	}
+
+	code += [
+					"outColor += col * cMul;" ,
+					"if ( all(lessThan(ncMul, vec3(.01))) ) {" ,
+						"break;" ,
+					"}" ,
+					"cMul = ncMul;" ,
+					"pos = nPos;" ,
+					"dir = normalize(nDir);" ,
+				"}" ,
+
+				"vec3 cMix = ( outColor.r == outColor.g && outColor.b == outColor.g ) ? outColor : vec3( dot( outColor , LUMA ) );" ,
+				"outColor = mix( mix( outColor , cMix , uGreyMix ) , vec3(uFadeColour) , smoothstep( .05 , .95 , uFade ) );" ,
+
+				"cMix.xy = vec2(voTexCoords.x,tc.y) * .5 + .5;" ,
+				"cMix.y = ( 1. - cMix.y - uTextParams.x ) / uTextParams.z;" ,
+				"vec4 tcol = texture2D( uTexture , cMix.xy );" ,
+				"outColor = mix(outColor , tcol.rgb * uTextColour ,  tcol.a * uTextParams.y );" ,
+
+				"outColor = max( vec3( 0. ) , outColor - vec3( .004 ) );" ,
+				"outColor = ( outColor * ( 6.2 * outColor + .5 ) ) / ( outColor * ( 6.2 * outColor + vec3( 1.7 ) ) + vec3( .06 ) );" ,
+
+				"float g = smoothstep(.98,1.,noise(tc*8.-uTime*40.));" ,
+				"outColor *= .95 + .05 * cos(uTime*41.);" ,
+				"outColor += vec3(g);" ,
+				"g = 1.-(smoothstep(.98,1.,noise(tc*8.+uTime*20.))+smoothstep(.95,1.,noise(tc*1.5+uTime*10.)));" ,
+
+				"float v = g*smoothstep(1.042+.008*cos(uTime*40.),.8,lx(voTexCoords,8.));" ,
+				"g = (tc.x + 1. ) * (tc.y + 1. ) * (uTime * 10.0);" ,
+				"v *= 1.-(mod((mod(g, 13.0) + 1.0) * (mod(g, 47.0) + 1.0), 0.01)) * 8.;" ,
+
+				"gl_FragColor = vec4(v*outColor,1.);" ,
+			"}" ,
+	].join('\n');
+	return [ code , uniforms ];
+}
+
+function buildRaymarchers( )
+{
+	var ml = 1;
+	for ( var n in raymarchers ) {
+		var rm = raymarchers[n];
+		var nl = rm.lights.length;
+		ml=nl>ml?nl:ml;
+		for ( var i=1;i<=nl;i++) {
+			var sn = 'rmfs_' + n + '_' + i;
+			var sd = createRaymarcherCode(rm,i);
+			shaderBits[sn] = sd[0];
+			shaders[sn] = ['f',sn];
+			programs['rm_' + n + '_' + i] = [ sd[1] , 'raymarchVS' , sn ];
+		}
+	}
+	var context = {
+		camPos: vomNew(3),
+		lookAt: vomNew(3),
+		up: vomNew(3),
+		toNearPlane: 0 ,
+		time: 0 ,
+		desync: 0 ,
+		greyMix: 0 ,
+		fade: 0 ,
+		fadeColour: 0 ,
+		text: vomNew(3) ,
+		textColour: vomNew(3) ,
+		lights: []
+	};
+	for ( var i = 0;i<ml;i++ ) {
+		context.lights.push({
+			pos: vomNew(3),
+			colour: vomNew(3) ,
+			distance: 0
+		});
+	}
+	return context;
+}
+
+var cmU=vomNew(3),
+    cmV=vomNew(3),
+    cmW=vomNew(3),
+    cd=vomNew(3),
+    cu=vomNew(3),
+    cm=vomNew(9);
+function prepareRaymarcher( ds )
+{
+	var rm = raymarchers[ds.rm], ctx = context;
+	ctx.extras = [];
+	ds.setGlobals( ctx );
+	vecNorm(cmW,vecSub(cmW,ctx.lookAt,ctx.camPos));
+	vecNorm(cmU,vecCross(cmU,ctx.up,cmW));
+	vecNorm(cmV,vecCross(cmV,cmW,cmU));
+	vecScale(cmW,cmW,ctx.toNearPlane);
+	vecs2Mat3(cm,cmU,cmV,cmW);
+
+	var active = [];
+	for ( var i in ds.lights ) {
+		if ( ds.lights[i] && ds.lights[ i ](ctx,ctx.lights[ i ]) ) {
+			active.push( ctx.lights[ i ] );
+		}
+	}
+
+	var p = programs[ 'rm_' + ds.rm + '_' + active.length ];
+	glCtx.useProgram( p[ 0 ] );
+	glCtx.enableVertexAttribArray( 0 );
+	glCtx.vertexAttribPointer( 0 , 2 , glCtx.FLOAT , false , 8 , 0 );
+	p = p[1];
+	glCtx.uniform1f( p.GreyMix , ctx.greyMix );
+	glCtx.uniform1f( p.Fade , ctx.fade );
+	glCtx.uniform1f( p.FadeColour , ctx.fadeColour );
+	glCtx.uniform1f( p.Desync , ctx.desync );
+	glCtx.uniform1f( p.Time , ctx.time );
+	glCtx.uniform3fv( p.CamPos , ctx.camPos );
+	glCtx.uniform3fv( p.TextParams , ctx.text );
+	glCtx.uniform3fv( p.TextColour , ctx.textColour );
+	glCtx.uniform1i( p.Texture , 0 );
+	glCtx.uniformMatrix3fv( p.CamMat , false , cm );
+	for ( var e in ctx.extras ) {
+		eval( 'glCtx.uniform' + ctx.extras[e] );
+	}
+	for ( var i in active ) {
+		glCtx.uniform1f( p[ 'LightDistance' + i ] , active[ i ].distance );
+		glCtx.uniform3fv( p[ 'LightPos' + i ] , active[ i ].pos );
+		glCtx.uniform3fv( p[ 'LightColor' + i ] , active[ i ].colour );
+	}
+	glCtx.drawArrays( 4 , 0 , 3 );
+}
+
+
+// Main
+
+function resize() {
+	var vw=window.innerWidth,vh=window.innerHeight;
+	var cw=Math.floor(vh*1.6),ch=Math.floor(vw*.625);
+	if(cw>vw){
+		C1.width=canvasWidth=vw;
+		C1.height=canvasHeight=ch;
+	}else{
+		C1.width=canvasWidth=cw;
+		C1.height=canvasHeight=vh;
+	}
+	C2.style.width=C2.width=canvasWidth;
+	c2height=C2.style.height=C2.height=Math.max(canvasHeight/8,100);
+	c2rHeight=c2height/canvasHeight;
+	twoDCtx.shadowColor = "#ccc";
+	twoDCtx.font = "normal small-caps bold " + Math.floor(c2height/2) + "px monospace";
+	twoDCtx.fillStyle = "#111";
+	twoDCtx.strokeStyle = "#ddd";
+	C1.style.left=Math.floor((vw-canvasWidth)*.5);
+	C1.style.top=Math.floor((vh-canvasHeight)*.5);
+	glCtx.viewport(0,0,canvasWidth,canvasHeight);
+}
+
+// FIXME: re-enable! document.body.style.cursor = 'none';
+document.body.style.background = 'black';
+document.body.innerHTML = '<canvas id=C1 style=position:fixed></canvas><canvas id=C2 style=display:none>';
+glCtx=C1.getContext('webgl');
+twoDCtx = C2.getContext('2d');
+(window.onresize=resize)();
+var context = buildRaymarchers( );
+buildPrograms();
+vtxBuffer = glCtx.createBuffer( );
+glCtx.bindBuffer( glCtx.ARRAY_BUFFER , glCtx.createBuffer( ) );
+glCtx.bufferData( glCtx.ARRAY_BUFFER , vomNew([1,4,1,-1,-4,-1]) , glCtx.STATIC_DRAW );
+glCtx.clearColor(0,0,0,1);
+
+textTexture = glCtx.createTexture( );
+glCtx.bindTexture( glCtx.TEXTURE_2D , textTexture );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_S, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_T, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MIN_FILTER, glCtx.NEAREST );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MAG_FILTER, glCtx.NEAREST );
+glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+
+timeStart = previousFrame = 0;
+FRAME_TIME = 100/3;
+
+paused = 0;
+document.body.onkeypress = function(e) {
+	if ( e.keyCode == 32 ) {
+		var now = Date.now();
+		if ( paused ) {
+			timeStart += now - paused;
+			paused = 0;
+			requestAnimationFrame(draw);
+			A.play( );
+		} else {
+			paused = now;
+			A.pause( );
+		}
+	}
+};
+
+mainfunc = function(){
+requestAnimationFrame(draw=function(time){
+	if ( ! paused ) {
+		requestAnimationFrame(draw);
+	}
+	if ( timeStart == 0 ) {
+		A.play( );
+		timeStart = time;
+		previousFrame = timeStart - FRAME_TIME;
+	}
+	var delta = time - previousFrame, demoTime = .001*(time - timeStart);
+	if ( delta < FRAME_TIME ) {
+		return;
+	}
+	previousFrame = time - ( delta % FRAME_TIME );
+
+	var ds = direction[t];
+	while ( ds && ds.endTime < demoTime ) {
+		ds=direction[++t];
+	}
+	if ( ! ds ) {
+		A.pause( );
+		return;
+	}
+	context.time = demoTime;
+	context.stepTime = demoTime - ds.startTime;
+	if ( ds.updateText ) {
+		twoDCtx.clearRect( 0 , 0 , canvasWidth , 100 );
+		ds.updateText();
+		glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+	} else {
+		vecSet(context.text,0,0,100/canvasHeight);
+	}
+	prepareRaymarcher( ds );
+})
+}
+
+if ( USE_SYNTH ) {
+	synth = new CPlayer();
+	synth.init(song);
+	synthGen = setInterval(function(){
+		if ( synth.generate() == 1 ) {
+			clearInterval(synthGen);
+			var s = '' , a = synth.createWave();
+			for(var i=0;i<a.length;i++)
+				s+= String.fromCharCode(a[i]);
+			A = document.createElement("audio");
+			A.src= 'data:audio/wav;base64,' + btoa(s);
+			A.oncanplaythrough=mainfunc;
+		}
+
+	}, 0);
+} else {
+	A = document.createElement("audio");
+	A.oncanplaythrough=mainfunc;
+	A.src= 'music.ogg';
+}
+
diff --git a/201410_-_Sine_City/sine-city-packing-1-shaders.html b/201410_-_Sine_City/sine-city-packing-1-shaders.html
new file mode 100644
index 0000000..743a66d
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-1-shaders.html
@@ -0,0 +1,5 @@
+<body>
+<script language="javascript" src="music.js"></script>
+<script language="javascript" src="player-small.js"></script>
+<script language="javascript" src="sine-city-packing-1-shaders.js"></script>
+
diff --git a/201410_-_Sine_City/sine-city-packing-1-shaders.js b/201410_-_Sine_City/sine-city-packing-1-shaders.js
new file mode 100644
index 0000000..00e3ab0
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-1-shaders.js
@@ -0,0 +1,1405 @@
+var USE_SYNTH = 0;
+
+// Vector stuff
+function vecOp(code) {
+	return eval('(function(o,a,b){for(var i=o.length;--i>=0;)' + code + ';return o})')
+}
+function vomNew(s) {
+	return new Float32Array(s)
+}
+var vecDot = function(a,b) {
+	var s = 0;
+	for ( var i in a ) {
+		s += a[i]*b[i];
+	}
+	return s;
+};
+var vecLen = function(a) {
+	return Math.sqrt( vecDot(a,a) )
+};
+var vecNorm = function(o,a) {
+	var l = vecLen(a);
+	return l ? vecScale(o,a,1/l) : vecCopy(o,a);
+};
+var vecCross = function(o,a,b) {
+	return vecSet(o,
+		a[1]*b[2]-a[2]*b[1] ,
+		a[2]*b[0]-a[0]*b[2] ,
+		a[0]*b[1]-a[1]*b[0]
+	);
+};
+var vecs2Mat3 = function(o,a,b,c){
+	for ( var i = 0 ; i < 3 ; i ++ ) {
+		o[i*3+0] = a[i];
+		o[i*3+1] = b[i];
+		o[i*3+2] = c[i];
+	}
+};
+var vecSet = vecOp('o[i]=arguments[i+1]') ,
+    vecCopy = vecOp('o[i]=a[i]') ,
+    vecAdd = vecOp('o[i]=a[i]+b[i]') ,
+    vecSub = vecOp('o[i]=a[i]-b[i]') ,
+    vecScale = vecOp('o[i]=a[i]*b');
+
+
+// Shaders
+var shaderHeader = 'precision highp float;varying !2 zx;';
+
+
+function shaderFloat( v ) {
+	return '' + v + ( v == Math.floor(v) ? '.' : '' );
+}
+function shaderVec( v ) {
+	return v.map(shaderFloat).join(',');
+}
+
+
+// Raymarchers
+
+var materials = [
+	{
+		albedo: [.05,.05,.05] ,
+		metallic: .7 ,
+		smoothness: .02 ,
+		r0: .01
+	} , {
+		albedo: [ .2,.2,.2 ] ,
+		noise: [ .1,.1,.1] ,
+		noiseScale: 5 ,
+		metallic: .7 ,
+		smoothness: .9 ,
+		r0: .01
+	} , {
+		albedo: [ 1,1,1 ] ,
+		metallic: .5 ,
+		smoothness: .4 ,
+		r0: .02
+	} , {
+		albedo: [ 3,0,0 ] ,
+		noise: [.6,0,0],
+		noiseScale: 6 ,
+		metallic: .3 ,
+		smoothness: .1 ,
+		r0: .6
+	} , {
+		albedo: [ 0,2,0 ] ,
+		noise: [0,.2,0],
+		noiseScale: 15 ,
+		metallic: .9 ,
+		smoothness: .5 ,
+		r0: .4
+	} , {
+		albedo: [ 3,1.5,0 ] ,
+		noise: [.3,.6,0],
+		noiseScale: .3 ,
+		metallic: .95 ,
+		smoothness: .6 ,
+		r0: .9
+	} , {
+		albedo: [ .1,.1,.1 ] ,
+		noise: [3,3,3] ,
+		noiseScale: 3,
+		metallic: 0 ,
+		smoothness: .04 ,
+		r0: .002
+	} , {
+		albedo: [ 0,1.5,2 ] ,
+		metallic: .9 ,
+		smoothness: .3 ,
+		r0: .4
+	}
+];
+
+
+var raymarchers = {
+	tunnel: {
+		maxDistance: 100 ,
+		epsilon: .025 ,
+		epsilonMultiplier: 1 ,
+		step: .7 ,
+		depth: 64 ,
+
+		normalDelta: .0005 ,
+		noiseScale: .5 ,
+		reflectionDistance: .3 ,
+
+		fog: .4 ,
+		fogDensity: .015 ,
+
+		aoSteps: 4 ,
+		aoDelta: 2 ,
+		aoWeight: .75 ,
+
+		materials: [0,1,2,3] ,
+
+		map: [
+			"y=x+.1*(sin(x.zxy*.17+u4[0]*.5)+sin(x.yzx*.7+u4[0]*1.5))*8.5*(1.+cos(sin(x.z*.1)+x.z*.3)),",
+
+			"z=14.-length(y.xy),",
+			"w=x.x==.0?1.570795*(x.y>.0?1.:-1.):atan(x.y,x.x),",
+			"q=8.35-u4[8]*1.35,",
+
+			"y=!3(9.*(mod(w+x.z*.02,.628)-.314),length(x.xy)-9.,mod(x.z,12.56)-6.28),",
+			"u=min(length(y.xy)-.25+.1*cos(x.z*8.+u4[0]*.1),length(y.yz)-.5),",
+			"y=!3(q*(mod(w+x.z*.02,1.256636)-.628318),y.y+9.-q,mod(x.z,62.8318)-31.4159)," ,
+			"o=step(u,z)+1.,",
+			"z=min(u,z),",
+			"u=length(y)-1.3;",
+			"if(u<z)z=u,o=3.;" ,
+			"y.y+=q-9.," ,
+			"u=yyx(y.yz,8.)-2.;" ,
+			"if(u<z)z=u,o=.0;" ,
+			"return !2(z,o);"
+		].join('\n') ,
+		lights: [
+			{
+				attenuation: .25 ,
+				vRadius: 0
+			} , {
+				attenuation: .5 ,
+				vRadius: .5
+			}
+		] ,
+	} ,
+	fractals: {
+		maxDistance: 6 ,
+		epsilon: .00025 ,
+		epsilonMultiplier: 1.08 ,
+		step: .7 ,
+		depth: 100 ,
+
+		normalDelta: .000008 ,
+		noiseScale: 10 ,
+		reflectionDistance: .03 ,
+
+		fog: 2.1 ,
+		fogDensity: .2 ,
+
+		aoSteps: 6 ,
+		aoDelta: .4 ,
+		aoWeight: 5.1 ,
+
+		materials: [0,2,5] ,
+
+		map: [
+			"z=1.," ,
+			"y=x;" ,
+			"for(int i=0;i<7;i++)" ,
+				"x=2.*clamp(x,-!3(.58,.9,1.1),!3(.58,.9,1.1))-x," ,
+				"w=max((1.3+u4[9]*.1*cos(u4[0]*.5))/dot(x,x),1.)," ,
+				"x*=w," ,
+				"z*=w;" ,
+			"w=length(x.xy),",
+			"e=!2(w-3.,-w*x.z/length(x)-2.*log(1.+.01*a))/abs(z),",
+			"w=max(e.x,e.y),",
+			"o=step(e.y,e.x),",
+			"y+=!3(.1,.3,-.4)*u0-u2+.25*sin(x*1.),",
+			"e.x=length(y)-.1*u4[8];",
+			"if(e.x<w)w=e.x,o=2.;" ,
+			"return !2(w,o);"
+		].join('\n') ,
+		lights: [
+			{
+				attenuation: .05
+			}
+		] ,
+	} ,
+	squares: {
+		maxDistance: 100 ,
+		epsilon: .000025 ,
+		epsilonMultiplier: 1 ,
+		step: .75 ,
+		depth: 80 ,
+
+		normalDelta: .00005 ,
+		noiseScale: .5 ,
+		reflectionDistance: .3 ,
+
+		fog: 3 ,
+		fogDensity: .01 ,
+
+		aoSteps: 4 ,
+		aoDelta: .75 ,
+		aoWeight: 4.75 ,
+
+		materials: [6,0,4] ,
+
+		map: [
+			"x.xy*=t(a*.009),",
+
+			"w=min(min(yz(x.xzy),yz(x)),yz(x.yzx)),",
+
+			"y=mod(x,!3(15.))-!3(7.5),",
+			"o=step(z=max(length(max(abs(y)-!3(2.5),!3(.0)))-.25,3.5-length(y)),w),",
+			"w=min(w,z),",
+			"z=length(y+.1*sin(y*5.5+u4[0]))-2.;",
+			"if(z<w)",
+				"w=z,",
+				"o=2.;",
+			"return !2(w,o);"
+		].join('\n') ,
+		lights: [
+			{
+				attenuation: .05
+			}
+		] ,
+	} ,
+	balls: {
+		maxDistance: 20 ,
+		epsilon: .0005 ,
+		epsilonMultiplier: 1 ,
+		step: .6 ,
+		depth: 128 ,
+
+		normalDelta: .0001 ,
+		noiseScale: .5 ,
+		reflectionDistance: .002 ,
+
+		fog: .01 ,
+		fogDensity: .08 ,
+
+		aoSteps: 4 ,
+		aoDelta: .5 ,
+		aoWeight: 1.75 ,
+
+		materials: [2,7] ,
+
+		map: [
+			"y=x,",
+			"y.xz=mod(x.xz,8.)-4.,",
+			"y.yz*=t(u4[8]+.1*a),",
+			"y.xy*=t(u4[8]*.5+.2*a),",
+			"y.y*=.9+.1*sin(u4[8]*5.),",
+			"w=max(length(y)-3.,-min(length(y)-2.8,",
+				"max(mod(y.y,.8)-.4,-mod(y.y+.4,.8)+.4))),",
+			"z=x.y+1.+sin(x.x*4.+u4[8]*2.)*sin(x.z+u4[8])*.1,",
+			"o=clamp(.5+.5*(z-w)/1.,.0,1.),",
+			"w=mix(z,w,o)-1.*o*(1.-o),",
+			"y=x,",
+			"y.xz=mod(y.xz,8.)-4.,",
+			"y/=1.25+.25*sin(u4[8]*5.),",
+			"y.xy*=t(u4[8]*5.),",
+			"y.yz*=t(u4[8]*2.5),",
+			"z=max(length(y)-1.,.04-length(max(abs(mod(y,.5)-.25)-!3(.15),!3(.0))));",
+			"return !2(min(w,z),step(z,w));"
+		].join('\n') ,
+		lights: [
+			{
+				attenuation: .02
+			},{
+				attenuation: .05 ,
+				vRadius: .5
+			} , {
+				attenuation: .05 ,
+				vRadius: .5
+			}
+		] ,
+	}
+};
+
+var lightFunc = function(intensity,distance) {
+	return function(ctx,lctx) {
+		vecCopy(lctx.pos,ctx.camPos);
+		vecSet(lctx.colour,intensity,intensity,intensity);
+		lctx.distance = distance;
+		return true;
+	}
+};
+var tun1CamCommon = function(ctx,dir) {
+	var z = demoTime*6;
+	vecSet(ctx.camPos,-6,0,z);
+	vecSet(ctx.lookAt,1,0,z);
+	vecSet(ctx.up,0,1,0);
+	ctx.misc[1] = 1;
+	ctx.misc[8] = 0;
+	return ctx.stepTime / dir.time;
+};
+var desyncFunc = function(desync) {
+	return function(ctx,tt) {
+		var z = ctx.stepTime / tt;
+		ctx.misc[4] = -z * desync;
+		if ( desync > 0 ) {
+			ctx.misc[4] += desync;
+		}
+		ctx.misc[4] *= Math.random( ) * .25 + .75;
+	};
+};
+var balls1CamFunc = function(lax,laz,desync) {
+	var dsf = desyncFunc(desync);
+	return function(ctx) {
+		var z = demoTime*3;
+		vecSet(ctx.camPos,0,4,z);
+		vecSet(ctx.lookAt,lax,0,z+laz);
+		vecSet(ctx.up,0,0,1);
+		ctx.misc[8]= ctx.misc[2] = 0;
+		dsf(ctx,this.time);
+	};
+};
+var balls2CamCommon = function(ctx) {
+	var z = demoTime*5;
+	vecSet(ctx.camPos,Math.cos(demoTime)*12,8,Math.sin(demoTime)*12+z);
+	vecSet(ctx.lookAt,1,0,z);
+	vecSet(ctx.up,0,1,0);
+	ctx.toNearPlane = 2.5;
+	z = demoTime - direction[43].startTime;
+	ctx.misc[8]=z;
+};
+var balls2LightFunc = function(scale) {
+	return function(ctx,lctx) {
+		var z = demoTime*30;
+		vecSet(lctx.pos,scale*Math.cos(demoTime*2)*5,3,scale*Math.sin(demoTime*2)*5+z);
+		vecSet(lctx.colour,1,1,1);
+		lctx.distance = 4;
+		return true;
+	};
+};
+var fract1CamCommon = function(ctx) {
+	var z = demoTime;
+	vecSet(ctx.camPos,4,2.5+.025*z,6.7);
+	vecSet(ctx.lookAt,0,2.5-.05*z,6.7);
+	vecSet(ctx.up,0,0,1);
+	ctx.misc[8] = ctx.misc[9] = 0;
+	ctx.toNearPlane = 3;
+};
+var fract1CamFunc = function(desync) {
+	var dsf = desyncFunc(desync);
+	return function(ctx){
+		fract1CamCommon(ctx);
+		dsf(ctx,this.time);
+	};
+};
+var fract2CamCommon = function(ctx,bs) {
+	vecSet(ctx.camPos,5*Math.sin(demoTime*.2),9*Math.cos(demoTime*.41),7.8);
+	vecCopy(ctx.lookAt,ctx.camPos);
+	ctx.lookAt[0] = Math.cos(demoTime*.2);
+	ctx.lookAt[1] = Math.sin(demoTime*.33);
+	ctx.lookAt[2] -= 2;
+	vecSet(ctx.up,0,0,1);
+	ctx.toNearPlane = 3;
+	ctx.misc[8] = bs;
+	ctx.misc[9] = 1;
+};
+
+var drawText = function(str,x) {
+	twoDCtx.shadowBlur = c2height/5;
+	twoDCtx.fillText( str , x , c2height / 2 );
+	twoDCtx.shadowBlur = 0;
+	twoDCtx.strokeText( str , x , c2height / 2 );
+};
+var titleText = function(str,shake,alpha,r,g,b) {
+	drawText( str , canvasWidth/15 );
+	context.misc[5] = 1 - c2rHeight + Math.random() * shake - shake * .5;
+	context.misc[6] = alpha;
+	vecSet( context.textColour , r , g , b );
+};
+var greetings = "Greetings to ... Mog, Sycop, Tim & Wullon ... Adinpsz ... Alcatraz ... ASD ... Bits'n'Bites ... Brain Control ... Cocoon ... Conspiracy ... Ctrl+Alt+Test ... Fairlight ... Farbrausch ... Kewlers ... LNX ... Loonies ... Mercury ... Popsy Team ... Razor 1911 ... RGBA ... 7th Cube ... Still ... TPOLM ... TRBL ... Umlaut Design ... X-Men ... Youth Uprising ... Everyone here at DemoJS 2014!";
+var greetingsText = function() {
+	var t = ( demoTime - direction[34].startTime ) * canvasWidth * .5;
+	drawText( greetings , canvasWidth - t );
+	context.misc[5] = 1 - c2rHeight + Math.random() * .02 - .01;
+	context.misc[6] = 1;
+	vecSet( context.textColour , 1 , 1 , 1 );
+};
+
+var squaresCam = function(ctx) {
+	var t = demoTime - direction[25].startTime;
+	var z = t*10 - 80;
+	vecSet(ctx.camPos,z,0,0);
+	vecSet(ctx.lookAt,z+Math.cos(t*.5) * 80,Math.sin(t*.25)*40,100);
+	vecSet(ctx.up,0,1,0);
+};
+
+var squaresCam2 = function(ctx,s) {
+	var t = demoTime - direction[s].startTime;
+	var z = t*20 - 80;
+	vecSet(ctx.camPos,0,0,z);
+	vecSet(ctx.lookAt,Math.cos(t*.5) * 80,Math.sin(t*.25)*40,z+100);
+	vecSet(ctx.up,Math.sin(t),Math.cos(t),0);
+	ctx.misc[4] = Math.random() * .025 - .0125;
+};
+
+var tunnelLight = function(ctx,lctx) {
+	vecAdd(lctx.pos,vecNorm(lctx.pos,vecScale(lctx.pos,ctx.lookAt,-1)),ctx.camPos);
+	lctx.pos[1] -= .5;
+	vecSet(lctx.colour,3,3,3);
+	lctx.distance = 30;
+	return true;
+};
+var tunnelCam = function(ctx,mul) {
+	var z = demoTime*30*ctx.tunMul;
+	vecSet(ctx.camPos,1.1*Math.cos(z*.1),Math.sin(z*.02),z);
+	z += 5;
+	vecSet(ctx.lookAt,-Math.sin(z*.05),-.7*Math.cos(z*.033),z);
+	vecSet(ctx.up,0,1,0);
+	ctx.toNearPlane = 2;
+};
+var tunnelLightBall = function(ctx,lctx) {
+	vecSet(lctx.pos , 4*Math.sin(demoTime*.5)*Math.cos(demoTime*.7) ,
+			3*Math.cos(demoTime*1.5),
+			demoTime*30*ctx.tunMul+14+16*Math.sin(demoTime*3.3)*Math.cos(demoTime*.77)
+	);
+	vecSet(lctx.colour,1,1,1);
+	lctx.distance = 15;
+	return true;
+};
+
+var direction = [
+	{
+		// Music rows
+		rows: 36 ,
+		// Raymarcher id
+		rm: 'tunnel' ,
+		setGlobals: function( ctx ) {
+			var z = tun1CamCommon(ctx,this);
+			z *= z*z;
+			ctx.misc[2] = 1 - z;
+			ctx.toNearPlane = 5;
+		} ,
+		lights: [
+			lightFunc(3,20)
+		] ,
+		updateText: null
+	} , {
+		rows: 18 ,
+		rm: 'tunnel' ,
+		setGlobals: function( ctx ) {
+			var z = tun1CamCommon(ctx,this);
+			ctx.toNearPlane = 5 - 2.25 * z;
+			ctx.misc[2] = 0;
+		} ,
+		lights: [
+			lightFunc(3,20)
+		] ,
+		updateText: null
+	} , {
+		rows: 36 ,
+		rm: 'tunnel' ,
+		setGlobals: function( ctx ) {
+			var z = tun1CamCommon(ctx,this);
+			ctx.toNearPlane = 2.75 - 2.25 * z;
+			ctx.misc[2] = z;
+		} ,
+		lights: [
+			lightFunc(3,20)
+		] ,
+		updateText: null
+	} , {
+		rows: 18 ,
+		rm: 'balls' ,
+		setGlobals: function( ctx ) {
+			var z = demoTime*3;
+			vecSet(ctx.camPos,0,4,z);
+			vecSet(ctx.lookAt,4,0,z);
+			vecSet(ctx.up,0,0,1);
+			z = ctx.stepTime / this.time;
+			z *= z*z;
+			ctx.misc[2] = 1 - z;
+			ctx.toNearPlane = 2.5;
+		} ,
+		lights: [
+			lightFunc(.75,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc(4,0,0) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc(2,-2,0) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 6 , 0 , -.5 ) ,
+		lights: [
+			lightFunc(.5,4)
+		] ,
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 6 , 0 , .5 ) ,
+		lights: [
+			lightFunc(.5,4)
+		] ,
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 2 , 2 , -.2 ) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 2 , 2 , .2 ) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 2 , 5 , -.7 ) ,
+		lights: [
+			lightFunc(1,2)
+		] ,
+		updateText: null
+	} , {
+		rows: 7 ,
+		rm: 'balls' ,
+		setGlobals: balls1CamFunc( 2 , 2 , .7 ) ,
+		lights: [
+			lightFunc(1,2)
+		] ,
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 'balls' ,
+		setGlobals: function(ctx) {
+			var z = demoTime*3;
+			ctx.misc[2] = ctx.stepTime / this.time;
+			vecSet(ctx.camPos,0,4+ctx.misc[2]*2,z);
+			vecSet(ctx.lookAt,2,0,z+2);
+			vecSet(ctx.up,0,0,1);
+			ctx.misc[3] = 1;
+		} ,
+		lights: [
+			lightFunc(1,2)
+		] ,
+		updateText: null
+	} , {
+		rows: 21 ,
+		rm: 'fractals' ,
+		setGlobals: function( ctx ) {
+			fract1CamCommon(ctx);
+			ctx.misc[3] = 1;
+			var z = ctx.stepTime / this.time;
+			ctx.misc[2] = 1 - z*z*z;
+		} , lights : [
+			fractLight = function(ctx,lctx) {
+				vecCopy(lctx.pos,ctx.camPos);
+				lctx.pos[2]+=2;
+				vecSet(lctx.colour,1,1,1);
+				lctx.distance = 3;
+				return true;
+			}
+		],
+		updateText: null
+	} , {
+		rows: 14 ,
+		rm: 'fractals' ,
+		setGlobals: fract1CamFunc(0) ,
+		lights : [
+			fractLight
+		],
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'fractals' ,
+		setGlobals: fract1CamFunc(-.4) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 'fractals' ,
+		setGlobals: fract1CamFunc(.4) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'fractals' ,
+		setGlobals: fract1CamFunc(-.2) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 'fractals' ,
+		setGlobals: fract1CamFunc(.2) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 12 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract1CamCommon(ctx);
+			ctx.misc[4] = -( 6 * ctx.stepTime / this.time ) % 1;
+			ctx.misc[4] *= Math.random( ) * .25 + .75;
+		} ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract1CamCommon(ctx);
+			ctx.misc[3] = .4;
+			ctx.misc[2] = ctx.stepTime / this.time;
+			ctx.toNearPlane = 3 - 2.5*Math.max(1,2*ctx.misc[2]);
+			ctx.misc[4] = ( 30 * ctx.misc[2] ) % 1;
+			ctx.misc[4] *= Math.random( ) * .15 + .85;
+		} ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 'fractals' ,
+		setGlobals: neutral = function(ctx) {
+			fract1CamCommon(ctx);
+			ctx.misc[3] = .4;
+			ctx.misc[2] = 1;
+			ctx.misc[4] = 0;
+		} ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 12 ,
+		rm: 'fractals' ,
+		setGlobals: neutral ,
+		lights : [ fractLight ],
+		updateText: function() {
+			titleText( "TheT(ourist)" , .08 , 1 , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 12 ,
+		rm: 'fractals' ,
+		setGlobals: neutral ,
+		lights : [ fractLight ],
+		updateText: function() {
+			titleText( "TheT(ourist)" , .08 , 1 - context.stepTime / this.time , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 12 ,
+		rm: 'fractals' ,
+		setGlobals: neutral ,
+		lights : [ fractLight ],
+		updateText: function() {
+			titleText( "presents" , .08 , 1 - context.stepTime / this.time , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 20 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam(ctx);
+			ctx.toNearPlane = 2.5;
+			ctx.misc[2] = 1 - ctx.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , context.stepTime / this.time , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 52 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam(ctx);
+			ctx.misc[2] = 0;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , 1 , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 12 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx){
+			squaresCam(ctx);
+			var z = context.stepTime / this.time;
+			ctx.misc[3] = 1;
+			ctx.misc[2] = Math.max(0,1-z*2);
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			var z = context.stepTime / this.time;
+			titleText( "Sine City" , .04 , 1 , 1 - z , 1 - z * .5 , 1 - z );
+		}
+	} , {
+		rows: 12 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam(ctx);
+			var z = context.stepTime / this.time;
+			ctx.misc[4] = ( 1 - z ) * .7 + Math.random() * .025 - .0125;
+			ctx.misc[1] = 1 - .5 * z;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , 1 , 0 , .5 , 0 );
+		}
+	} , {
+		rows: 9 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,29);
+			var z = context.stepTime / this.time;
+			ctx.misc[2] = Math.max(0,1-z*1.5);
+			ctx.misc[4] += ( z - 1 ) * .3;
+			ctx.misc[1] = .5 - .5 * z;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , 1 - context.stepTime / this.time , 0 , .5 , 0 );
+		}
+	} , {
+		rows: 69 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,29);
+			ctx.misc[1] = 0;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: null
+	} , {
+		rows: 11 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,29);
+			ctx.misc[3] = .2;
+			ctx.misc[2] = context.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: null
+	} , {
+		rows: 11 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			ctx.tunMul = 1;
+			tunnelCam(ctx);
+			ctx.misc[2] = 1 - context.stepTime / this.time;
+		} ,
+		lights : [ tunnelLight ],
+		updateText: null
+	} , {
+		rows: 17 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[2] = 0;
+			ctx.misc[4] = (1.2 - 1.2 * context.stepTime / this.time) * (.98 + .04*Math.random());
+		} ,
+		lights : [ tunnelLight ],
+		updateText: null
+	} , {
+		rows: 18 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[4] = 0;
+			ctx.misc[8] = context.stepTime / this.time;
+		} ,
+		lights : [ tunnelLight ],
+		updateText: greetingsText
+	} , {
+		rows: 36 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[2] = 1 - Math.min(4*context.stepTime / this.time,1);
+			ctx.misc[8] = 1;
+		} ,
+		lights : tunLights = [ tunnelLight , tunnelLightBall ],
+		updateText: greetingsText
+	} , {
+		rows: 33 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[2] = context.stepTime / this.time;
+			ctx.misc[3] = .7;
+			ctx.misc[4] = -((4*ctx.misc[2])%1)*(.95+Math.random()*.1);
+		} ,
+		lights : tunLights ,
+		updateText: greetingsText
+	} , {
+		rows: 9 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,0);
+			ctx.misc[2] = context.stepTime / this.time;
+			ctx.misc[3] = 1;
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 20 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,context.stepTime / this.time);
+			ctx.misc[2] = 0;
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 31 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.misc[2] = Math.min(0,1-5*context.stepTime / this.time);
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 5 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.misc[2] = 1-context.stepTime / this.time;
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 18 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.misc[2] = Math.min(0,1-5*context.stepTime / this.time);
+			ctx.misc[4] = Math.max(0,1.6*context.stepTime / this.time - .8 )*(.95+Math.random()*.1);
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 12 ,
+		rm: 'fractals' ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.misc[3] = .1;
+			ctx.misc[2] = context.stepTime / this.time;
+			ctx.misc[4] = .8*(1-ctx.misc[2])*(.9+Math.random()*.2);
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 22 ,
+		rm: 'balls' ,
+		setGlobals: function(ctx) {
+			balls2CamCommon(ctx);
+			ctx.misc[2] = 1-context.stepTime / this.time;
+			ctx.misc[4] = 0;
+		} ,
+		lights : ballsLights = [ lightFunc(.6,30) , balls2LightFunc(1),balls2LightFunc(-1) ],
+		updateText: greetingsText
+	} , {
+		rows: 59 ,
+		rm: 'balls' ,
+		setGlobals: function(ctx) {
+			balls2CamCommon(ctx);
+			ctx.misc[3] = .8;
+			ctx.misc[2] = Math.max(0,1-(12*context.stepTime / this.time)%4);
+		} ,
+		lights : ballsLights,
+		updateText: greetingsText
+	} , {
+		rows: 8 ,
+		rm: 'balls' ,
+		setGlobals: function(ctx) {
+			balls2CamCommon(ctx);
+			ctx.misc[3] = .1;
+			ctx.misc[2] = context.stepTime / this.time;
+			ctx.misc[4] = .1-Math.random()*.2;
+		} ,
+		lights : ballsLights,
+		updateText: null
+	} , {
+		rows: 7 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			ctx.tunMul = 2;
+			tunnelCam(ctx);
+			ctx.misc[2] = 1-context.stepTime / this.time;
+			ctx.misc[4] = .1-Math.random()*.2;
+		} ,
+		lights : tunLights ,
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[4] = .1-Math.random()*.2;
+		} ,
+		lights : tunLights ,
+		updateText: null
+	} , {
+		rows: 10 ,
+		rm: 'tunnel' ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[4] = context.stepTime*4+.1-Math.random()*.2;
+			ctx.misc[3] = 1;
+			ctx.misc[2] = context.stepTime / this.time;
+		} ,
+		lights : tunLights ,
+		updateText: null
+	} , {
+		rows: 10 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.misc[4] = (demoTime-direction[48].startTime)*4+.1-Math.random()*.2;
+			ctx.misc[2] = 1-context.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	} , {
+		rows: 40 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.misc[4] = -(demoTime-direction[48].startTime)*6;
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	} , {
+		rows: 40 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.misc[4] = (demoTime-direction[48].startTime)*8;
+			ctx.misc[3] = 0;
+			ctx.misc[2] = context.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	} , {
+		rows: 68 ,
+		rm: 'squares' ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.misc[2] = 1
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	}
+];
+var t = 0;
+var BPM = 120;
+for ( var i in direction ) {
+	direction[ i ].startTime = t;
+	t += ( direction[i].time = direction[ i ].rows * 60 / ( BPM * 4 ) );
+	direction[ i ].endTime = t;
+}
+rows = t * BPM * 4 / 60;
+t = 0;
+
+function createRaymarcherCode( def , nLights ) {
+	var w = 'uniform ';
+	var code = shaderHeader
+		+ [ w+'mat3 u0;' ,
+		    w+'sampler2D u1;' ,
+		    w+'!3 u2,u3;' ,
+		    w+'float u4[10];'
+		  ].join('\n');
+	var u = 5;
+	for ( var i in def.lights ) {
+		code += w+'!3 u' + u++ + ', u' + u++ + ';'+w+'float u' + u++ + ';';
+	}
+	code += [
+		"const !2 c=!2(1.,-1.)*"+def.normalDelta+";" ,
+		"float p,z,w,u,o,zy,q,x,a,zz;" ,
+		"!2 e,h;" ,
+		"!3 l=!3(zx,1.),m,r,s=u2,yx=!3(1.),n=!3(.0),b,v,xxx,xy,d,xx,xz,y;" ,
+		"!4 f;" ,
+
+		"float g(float x)" ,
+		"{" ,
+			"return fract(sin(x)*43758.5453);" ,
+		"}" ,
+
+		"float yy(!3 x)" ,
+		"{" ,
+			"m=floor(x),y=fract(x)," ,
+			"y*=y*(3.-2.*y)," ,
+			"z=m.x+m.y*57.+m.z*113.;" ,
+			"return mix(mix(mix(g(z),g(z+1.),y.x)," ,
+					"mix(g(z+57.),g(z+58.),y.x),y.y)," ,
+				"mix(mix(g(z+113.),g(z+114.),y.x)," ,
+					"mix(g(z+170.),g(z+171.),y.x),y.y),y.z);" ,
+		"}" ,
+
+		"float yyx(!2 x,float a)" ,
+		"{" ,
+			"e=pow(abs(x),!2(a));" ,
+			"return pow(e.x+e.y,1./a);" ,
+		"}" ,
+
+		"mat2 t(float x)" ,
+		"{" ,
+			"e=!2(cos(x),sin(x));" ,
+			"return mat2(-e.x,e.y,e.y,e.x);" ,
+		"}" ,
+
+		"float yz(!3 x)" ,
+		"{" ,
+			"return length(mod(x.xy,!2(15.))-!2(7.5))-.5+.05*sin(x.z*9.42477);" ,
+		"}" ,
+
+		"!2 k(!3 x,float a) {"
+	].join("\n");
+	code += def.map + '}';
+	code += [
+			"void main()" ,
+			"{" ,
+				"l.y+=mod(u4[4],1.)*2.2;" ,
+				"if(l.y>1.){" ,
+					"if(l.y < 1.2)discard;" ,
+					"l.y-=2.2;" ,
+				"}" ,
+				"l.x*=1.6," ,
+				"r=normalize(l*u0);" ,
+
+				"for(int j=0;j<2;j++){" ,
+					"v=r,xxx=s,xy=!3(.0)," ,
+					"x=.0,a=" + def.epsilon + ';' ,
+					"for(int i=0;i<" + def.depth + ";i++){" ,
+						"h=k(s+r*x,x);" ,
+						"if(h.x< a||i>" + def.depth + "/(j+1)||x>" + def.maxDistance + ".)break;" ,
+						"x+=h.x*" + def.step + ",a*=" + shaderFloat( def.epsilonMultiplier ) + ";" ,
+					"}" ,
+					"h.x=x;",
+
+					"if(x<"+ def.maxDistance+ ".){" ,
+						"d=s+r*x," ,
+						"f=!4(" ,
+							"k(d+c.xyy,x).x," ,
+							"k(d+c.yyx,x).x," ,
+							"k(d+c.yxy,x).x," ,
+							"k(d+c.xxx,x).x" ,
+						")," ,
+						"xx=normalize(f.x*c.xyy+f.y*c.yyx+f.z*c.yxy+f.w*c.xxx)," ,
+						"a=.0," ,
+						"p=" + def.aoWeight + ";" ,
+						"for(int i=1;i<="+def.aoSteps+";i++)" ,
+							"x=(float(i)/"+def.aoSteps+".)*"+ shaderFloat( def.aoDelta ) + "," ,
+							"m=d+xx*x," ,
+							"a+=p*(x-k(m,distance(m,s)).x)," ,
+							"p*=.5;" ,
+						"q=max(.1,1.-clamp(pow(a,1.),.0,1.));" ,
+		].join('\n');
+
+	for ( var i in def.materials ) {
+		if ( i > 0 ) {
+			code += 'else ';
+		}
+		var m = materials[ def.materials[i] ];
+		code += 'if(h.y==' + i + '.)'
+			+ 'xz=';
+		if ( m.noiseScale ) {
+			code += 'mix(!3(' + shaderVec( m.albedo ) + '),!3('
+				+ shaderVec( m.noise ) + '),yy(d*'
+				+ shaderFloat( def.noiseScale * m.noiseScale ) + '))';
+		} else {
+			code += '!3(' + shaderVec( m.albedo ) + ')';
+		}
+		code += ',w=' + shaderFloat( m.metallic ) + ',u=' + m.smoothness + ',o=' + m.r0 + ';';
+	}
+
+	code += [
+						"v=reflect(r,xx)," ,
+						"z="+def.fogDensity+"*h.x," ,
+						"z=clamp(exp(-z*z*z*1.442695),.0,1.)," ,
+						"x=clamp((1.+dot(normalize(v+r),r)),.0,1.),a=x*x," ,
+						"zz=o+(1.-o)*x*a*a*(u*.9+.1)," ,
+						"y=mix(!3(1.),xz/dot(!3(.299,.587,.114),xz),w)," ,
+						"m=!3(.0)," ,
+						"zy=exp2(4.+6.*u)," ,
+		].join('\n');
+
+	u = 5;
+	for ( var l in def.lights ) {
+		var b = def.lights[l];
+		code += [
+			"p=length(b=u" + u + "-d)," ,
+			"b/=p," ,
+			"p=max(1.,p-u" + (u+2) + ")*" + b.attenuation + "," ,
+			"p=1./max(1.,p*p)," ,
+			"m+=mix((1.-w)*xz*q,y*pow(max(dot(reflect(r,xx),b),.0),zy)*(zy+2.)/8.,zz)*p*max(dot(b,xx),.0)*u" + (u+1) + ","
+		].join('\n');
+		u+=3;
+	}
+	code += [
+						"xy=yx*z*normalize(y)*o*(u*.9+.1)*zz," ,
+						"m=mix(!3(" + shaderFloat(def.fog) + "),m,z)," ,
+						"xxx+=normalize(v)*" + def.reflectionDistance + ";" ,
+					"}else" ,
+						"m=!3(" + shaderFloat(def.fog) + ');'
+	].join('\n');
+
+	u=5;
+	for ( var l in def.lights ) {
+		var b = def.lights[l];
+		var h = b.vRadius;
+		if ( h ) {
+			code += [
+					"b=s-u" + u + "," ,
+					"p=dot(r,r),a=2.*dot(b,r)," ,
+					"x=a*a-4.*p*(dot(b,b)-" + (h*h) + ")," ,
+					"e=x<.0?!2(-1.):(x=sqrt(x),-.5*!2(a+x,a-x)/p)," ,
+					"e=!2(min(e.x,e.y),max(e.x,e.y));" ,
+					"if(e.x>.0&&e.y<h.x)" ,
+						"m+=u" + (u+2) + "*u" + (u+1) + "*pow((e.y-e.x)/" + shaderFloat(h*2) + ",64.);"
+			].join( "\n" );
+		}
+		u+=3;
+	}
+
+	code += [
+					"n+=m*yx;" ,
+					"if(all(lessThan(xy,!3(.01))))break;" ,
+					"yx=xy," ,
+					"s=xxx," ,
+					"r=normalize(v);" ,
+				"}" ,
+
+				"h=!2(zx.x,l.y)*.5+.5," ,
+				"h.y=(1.-h.y-u4[5])/u4[7]," ,
+				"f=texture2D(u1,h)," ,
+				"n=max(!3(.0),mix(mix(mix(n,(n.x==n.y&&n.x==n.z)?n:!3(dot(n,!3(.299,.587,.114))),u4[1]),!3(u4[3]),smoothstep(.05,.95,u4[2])),f.rgb*u3,f.a*u4[6])-!3(.004)),",
+
+				"x=(l.x+1.)*(l.y+1.)*(u4[0]*10.),",
+				"gl_FragColor=!4((1.-(smoothstep(.98,1.,yy(l*8.+u4[0]*20.))+smoothstep(.95,1.,yy(l*1.5+u4[0]*10.))))*smoothstep(1.042+.008*cos(u4[0]*40.),.8,yyx(zx,8.))*(1.-(mod((mod(x,13.)+1.)*(mod(x,47.)+1.),.01))*8.)*((.95+.05*cos(u4[0]*41.))*(n*(6.2*n+.5))/(n*(6.2*n+!3(1.7))+!3(.06))+!3(smoothstep(.98,1.,yy(l*8.-u4[0]*40.)))),1.);",
+			"}" ,
+	].join('\n');
+	return [ code , 5+def.lights.length*3 ];
+}
+
+function buildRaymarchers( )
+{
+	var ml = 1;
+	var sn = 1;
+	for ( var n in raymarchers ) {
+		var rm = raymarchers[n];
+		var nl = rm.lights.length;
+		ml=nl>ml?nl:ml;
+		for ( var i=1;i<=nl;i++) {
+			var sd = createRaymarcherCode(rm,i);
+			shaders[sn] = [glCtx.FRAGMENT_SHADER,sd[0]];
+			programs[n + '_' + i] = [ sd[1] , 0 , sn++ ];
+		}
+	}
+	var context = {
+		camPos: vomNew(3),
+		lookAt: vomNew(3),
+		up: vomNew(3),
+		toNearPlane: 0 ,
+		misc: vomNew(10) ,
+		textColour: vomNew(3) ,
+		lights: []
+	};
+	for ( var i = 0;i<ml;i++ ) {
+		context.lights.push({
+			pos: vomNew(3),
+			colour: vomNew(3) ,
+			distance: 0
+		});
+	}
+	return context;
+}
+
+var cmU=vomNew(3),
+    cmV=vomNew(3),
+    cmW=vomNew(3),
+    cd=vomNew(3),
+    cu=vomNew(3),
+    cm=vomNew(9);
+function prepareRaymarcher( ds )
+{
+	var rm = raymarchers[ds.rm], ctx = context;
+	ds.setGlobals( ctx );
+	vecNorm(cmW,vecSub(cmW,ctx.lookAt,ctx.camPos));
+	vecNorm(cmU,vecCross(cmU,ctx.up,cmW));
+	vecNorm(cmV,vecCross(cmV,cmW,cmU));
+	vecScale(cmW,cmW,ctx.toNearPlane);
+	vecs2Mat3(cm,cmU,cmV,cmW);
+
+	var active = [];
+	for ( var i in ds.lights ) {
+		if ( ds.lights[i] && ds.lights[ i ](ctx,ctx.lights[ i ]) ) {
+			active.push( ctx.lights[ i ] );
+		}
+	}
+
+	var p = programs[ds.rm + '_' + active.length ];
+	glCtx.useProgram( p[ 0 ] );
+	glCtx.enableVertexAttribArray( 0 );
+	glCtx.vertexAttribPointer( 0 , 2 , glCtx.FLOAT , false , 8 , 0 );
+	p = p[1];
+
+	var u = 0;
+	glCtx.uniformMatrix3fv( p[u++] , false , cm );
+	glCtx.uniform1i( p[u++] , 0 );
+	glCtx.uniform3fv( p[u++] , ctx.camPos );
+	glCtx.uniform3fv( p[u++] , ctx.textColour );
+	glCtx.uniform1fv( p[u++] , ctx.misc );
+	for ( var i in active ) {
+		glCtx.uniform3fv( p[u++] , active[ i ].pos );
+		glCtx.uniform3fv( p[u++] , active[ i ].colour );
+		glCtx.uniform1f( p[u++] , active[ i ].distance );
+	}
+	glCtx.drawArrays( 4 , 0 , 3 );
+}
+
+
+// Main
+
+function resize() {
+	var vw=window.innerWidth,vh=window.innerHeight;
+	var cw=Math.floor(vh*1.6),ch=Math.floor(vw*.625);
+	if(cw>vw){
+		C1.width=canvasWidth=vw;
+		C1.height=canvasHeight=ch;
+	}else{
+		C1.width=canvasWidth=cw;
+		C1.height=canvasHeight=vh;
+	}
+	C2.style.width=C2.width=canvasWidth;
+	c2height=C2.style.height=C2.height=Math.max(canvasHeight/8,100);
+	c2rHeight=c2height/canvasHeight;
+	twoDCtx.shadowColor = "#ccc";
+	twoDCtx.font = "normal small-caps bold " + Math.floor(c2height/2) + "px monospace";
+	twoDCtx.fillStyle = "#111";
+	twoDCtx.strokeStyle = "#ddd";
+	C1.style.left=Math.floor((vw-canvasWidth)*.5);
+	C1.style.top=Math.floor((vh-canvasHeight)*.5);
+	glCtx.viewport(0,0,canvasWidth,canvasHeight);
+}
+
+// FIXME: re-enable! document.body.style.cursor = 'none';
+document.body.style.background = 'black';
+document.body.innerHTML = '<canvas id=C1 style=position:fixed></canvas><canvas id=C2 style=display:none>';
+glCtx=C1.getContext('webgl');
+twoDCtx = C2.getContext('2d');
+(window.onresize=resize)();
+var shaders = [
+	[ glCtx.VERTEX_SHADER , shaderHeader + "attribute !2 i;void main(){gl_Position=!4(i,.0,1.),zx=i;}"
+	]
+];
+var programs = {};
+var context = buildRaymarchers( );
+for ( var i in shaders ) {
+	var def = shaders[i];
+	glCtx.shaderSource( i= shaders[i] = glCtx.createShader( def[0] ) , def[1].replace(/!/g,'vec') );
+	glCtx.compileShader( i );
+	if (!glCtx.getShaderParameter(i, glCtx.COMPILE_STATUS)) {
+		def[1] = def[1].split( /\n/ );
+		for ( var k in def[1] ) {
+			var j = parseInt(k)+1;
+			def[1][k] = j + ": " + def[1][k];
+		}
+		throw "SHADER ERROR\n" + glCtx.getShaderInfoLog(i) + "\n" + def[1].join('\n');
+	}
+}
+for ( var name in programs ) {
+	var p = glCtx.createProgram( );
+	var d = programs[name];
+	var ul = d.shift();
+	while( d.length ) {
+		glCtx.attachShader( p , shaders[ d.shift() ] );
+	}
+	glCtx.linkProgram( p );
+	var nul = [];
+	while ( ul-- ) {
+		nul[ul] = glCtx.getUniformLocation( p , 'u' + ul );
+	}
+	programs[name] = [p,nul];
+}
+vtxBuffer = glCtx.createBuffer( );
+glCtx.bindBuffer( glCtx.ARRAY_BUFFER , glCtx.createBuffer( ) );
+glCtx.bufferData( glCtx.ARRAY_BUFFER , vomNew([1,4,1,-1,-4,-1]) , glCtx.STATIC_DRAW );
+glCtx.clearColor(0,0,0,1);
+
+textTexture = glCtx.createTexture( );
+glCtx.bindTexture( glCtx.TEXTURE_2D , textTexture );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_S, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_T, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MIN_FILTER, glCtx.NEAREST );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MAG_FILTER, glCtx.NEAREST );
+glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+
+timeStart = previousFrame = 0;
+FRAME_TIME = 100/3;
+
+paused = 0;
+document.body.onkeypress = function(e) {
+	if ( e.keyCode == 32 ) {
+		var now = Date.now();
+		if ( paused ) {
+			timeStart += now - paused;
+			paused = 0;
+			requestAnimationFrame(draw);
+			A.play( );
+		} else {
+			paused = now;
+			A.pause( );
+		}
+	}
+};
+
+var demoTime;
+mainfunc = function(){
+requestAnimationFrame(draw=function(time){
+	if ( ! paused ) {
+		requestAnimationFrame(draw);
+	}
+	if ( timeStart == 0 ) {
+		A.play( );
+		timeStart = time;
+		previousFrame = timeStart - FRAME_TIME;
+	}
+	var delta = time - previousFrame;
+	demoTime = .001*(time - timeStart);
+	if ( delta < FRAME_TIME ) {
+		return;
+	}
+	previousFrame = time - ( delta % FRAME_TIME );
+
+	var ds = direction[t];
+	while ( ds && ds.endTime < demoTime ) {
+		ds=direction[++t];
+	}
+	if ( ! ds ) {
+		A.pause( );
+		return;
+	}
+	context.misc[0] = demoTime;
+	context.misc[7] = c2rHeight;
+	context.stepTime = demoTime - ds.startTime;
+	if ( ds.updateText ) {
+		twoDCtx.clearRect( 0 , 0 , canvasWidth , 100 );
+		ds.updateText();
+		glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+	}
+	prepareRaymarcher( ds );
+})
+}
+
+if ( USE_SYNTH ) {
+	synth = new CPlayer();
+	synth.init(song);
+	synthGen = setInterval(function(){
+		if ( synth.generate() == 1 ) {
+			clearInterval(synthGen);
+			var s = '' , a = synth.createWave();
+			for(var i=0;i<a.length;i++)
+				s+= String.fromCharCode(a[i]);
+			A = document.createElement("audio");
+			A.src= 'data:audio/wav;base64,' + btoa(s);
+			A.oncanplaythrough=mainfunc;
+		}
+
+	}, 0);
+} else {
+	A = document.createElement("audio");
+	A.oncanplaythrough=mainfunc;
+	A.src= 'music.ogg';
+}
diff --git a/201410_-_Sine_City/sine-city-packing-2-raymarchers.html b/201410_-_Sine_City/sine-city-packing-2-raymarchers.html
new file mode 100644
index 0000000..1f73a54
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-2-raymarchers.html
@@ -0,0 +1,5 @@
+<body>
+<script language="javascript" src="music.js"></script>
+<script language="javascript" src="player-small.js"></script>
+<script language="javascript" src="sine-city-packing-2-raymarchers.js"></script>
+
diff --git a/201410_-_Sine_City/sine-city-packing-2-raymarchers.js b/201410_-_Sine_City/sine-city-packing-2-raymarchers.js
new file mode 100644
index 0000000..7496515
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-2-raymarchers.js
@@ -0,0 +1,1123 @@
+var USE_SYNTH = 1;
+
+// Vector stuff
+function vecOp(code) {
+	return eval('(function(o,a,b){for(var i=o.length;--i>=0;)' + code + ';return o})')
+}
+function vomNew(s) {
+	return new Float32Array(s)
+}
+var vecDot = function(a,b) {
+	var s = 0;
+	for ( var i in a ) {
+		s += a[i]*b[i];
+	}
+	return s;
+};
+var vecLen = function(a) {
+	return Math.sqrt( vecDot(a,a) )
+};
+var vecNorm = function(o,a) {
+	var l = vecLen(a);
+	return l ? vecScale(o,a,1/l) : vecCopy(o,a);
+};
+var vecCross = function(o,a,b) {
+	return vecSet(o,
+		a[1]*b[2]-a[2]*b[1] ,
+		a[2]*b[0]-a[0]*b[2] ,
+		a[0]*b[1]-a[1]*b[0]
+	);
+};
+var vecs2Mat3 = function(o,a,b,c){
+	for ( var i = 0 ; i < 3 ; i ++ ) {
+		o[i*3+0] = a[i];
+		o[i*3+1] = b[i];
+		o[i*3+2] = c[i];
+	}
+};
+var vecSet = vecOp('o[i]=arguments[i+1]') ,
+    vecCopy = vecOp('o[i]=a[i]') ,
+    vecAdd = vecOp('o[i]=a[i]+b[i]') ,
+    vecSub = vecOp('o[i]=a[i]-b[i]') ,
+    vecScale = vecOp('o[i]=a[i]*b');
+
+
+// Shaders
+var shaderHeader = 'precision highp float;varying !2 zx;';
+
+
+function shaderFloat( v ) {
+	return '' + v + ( v == Math.floor(v) ? '.' : '' );
+}
+function shaderVec( v ) {
+	return v.map(shaderFloat).join(',');
+}
+
+
+// Raymarchers
+
+var materials = [[[.05],.7,.02,.01],[[.2],.7,.9,.01,5,[.1]],[[1],.5,.4,.02],[[3,0,0],.3,.1,.6,6,[.6,0,0]],[[0,2,0],.9,.5,.4,15,[0,.2,0]],[[3,1.5,0],.95,.6,.9,.3,[.3,.6,0]],[[.1],0,.04,.002,3,[3]],[[0,1.5,2],.9,.3,.4]];
+var raymarchers = [[100,.025,1,.7,64,.0005,.5,.3,.4,.015,4,2,.75,[0,1,2,3],'y=x+.1*(sin(x.zxy*.17+u4[0]*.5)+sin(x.yzx*.7+u4[0]*1.5))*8.5*(1.+cos(sin(x.z*.1)+x.z*.3)),z=14.-length(y.xy),w=x.x==.0?1.570795*(x.y>.0?1.:-1.):atan(x.y,x.x),q=8.35-u4[8]*1.35,y=!3(9.*(mod(w+x.z*.02,.628)-.314),length(x.xy)-9.,mod(x.z,12.56)-6.28),u=min(length(y.xy)-.25+.1*cos(x.z*8.+u4[0]*.1),length(y.yz)-.5),y=!3(q*(mod(w+x.z*.02,1.256636)-.628318),y.y+9.-q,mod(x.z,62.8318)-31.4159),o=step(u,z)+1.,z=min(u,z),u=length(y)-1.3;if(u<z)z=u,o=3.;y.y+=q-9.,u=yyx(y.yz,8.)-2.;if(u<z)z=u,o=.0;return !2(z,o);',[[.25,0],[.5,.5]]],[6,.00025,1.08,.7,100,.000008,10,.03,2.1,.2,6,.4,5.1,[0,2,5],'z=1.,y=x;for(int i=0;i<7;i++)x=2.*clamp(x,-!3(.58,.9,1.1),!3(.58,.9,1.1))-x,w=max((1.3+u4[9]*.1*cos(u4[0]*.5))/dot(x,x),1.),x*=w,z*=w;w=length(x.xy),e=!2(w-3.,-w*x.z/length(x)-2.*log(1.+.01*a))/abs(z),w=max(e.x,e.y),o=step(e.y,e.x),y+=!3(.1,.3,-.4)*u0-u2+.25*sin(x*1.),e.x=length(y)-.1*u4[8];if(e.x<w)w=e.x,o=2.;return !2(w,o);',[[.05]]],[100,.000025,1,.75,80,.00005,.5,.3,3,.01,4,.75,4.75,[6,0,4],'x.xy*=t(a*.009),w=min(min(yz(x.xzy),yz(x)),yz(x.yzx)),y=mod(x,!3(15.))-!3(7.5),o=step(z=max(length(max(abs(y)-!3(2.5),!3(.0)))-.25,3.5-length(y)),w),w=min(w,z),z=length(y+.1*sin(y*5.5+u4[0]))-2.;if(z<w)w=z,o=2.;return !2(w,o);',[[.05]]],[20,.0005,1,.6,128,.0001,.5,.002,.01,.08,4,.5,1.75,[2,7],'y=x,y.xz=mod(x.xz,8.)-4.,y.yz*=t(u4[8]+.1*a),y.xy*=t(u4[8]*.5+.2*a),y.y*=.9+.1*sin(u4[8]*5.),w=max(length(y)-3.,-min(length(y)-2.8,max(mod(y.y,.8)-.4,-mod(y.y+.4,.8)+.4))),z=x.y+1.+sin(x.x*4.+u4[8]*2.)*sin(x.z+u4[8])*.1,o=clamp(.5+.5*(z-w)/1.,.0,1.),w=mix(z,w,o)-1.*o*(1.-o),y=x,y.xz=mod(y.xz,8.)-4.,y/=1.25+.25*sin(u4[8]*5.),y.xy*=t(u4[8]*5.),y.yz*=t(u4[8]*2.5),z=max(length(y)-1.,.04-length(max(abs(mod(y,.5)-.25)-!3(.15),!3(.0))));return !2(min(w,z),step(z,w));',[[.02],[.05,.5],[.05,.5]]]];
+
+var lightFunc = function(intensity,distance) {
+	return function(ctx,lctx) {
+		vecCopy(lctx[0],ctx.camPos);
+		vecSet(lctx[1],intensity,intensity,intensity);
+		lctx[2] = distance;
+	}
+};
+var tun1CamCommon = function(ctx,dir) {
+	var z = demoTime*6;
+	vecSet(ctx.camPos,-6,0,z);
+	vecSet(ctx.lookAt,1,0,z);
+	vecSet(ctx.up,0,1,0);
+	ctx.misc[1] = 1;
+	ctx.misc[8] = 0;
+	return ctx.stepTime / dir.time;
+};
+var desyncFunc = function(desync) {
+	return function(ctx,tt) {
+		var z = ctx.stepTime / tt;
+		ctx.misc[4] = -z * desync;
+		if ( desync > 0 ) {
+			ctx.misc[4] += desync;
+		}
+		ctx.misc[4] *= Math.random( ) * .25 + .75;
+	};
+};
+var balls1CamFunc = function(lax,laz,desync) {
+	var dsf = desyncFunc(desync);
+	return function(ctx) {
+		var z = demoTime*3;
+		vecSet(ctx.camPos,0,4,z);
+		vecSet(ctx.lookAt,lax,0,z+laz);
+		vecSet(ctx.up,0,0,1);
+		ctx.misc[8]= ctx.misc[2] = 0;
+		dsf(ctx,this.time);
+	};
+};
+var balls2CamCommon = function(ctx) {
+	var z = demoTime*5;
+	vecSet(ctx.camPos,Math.cos(demoTime)*12,8,Math.sin(demoTime)*12+z);
+	vecSet(ctx.lookAt,1,0,z);
+	vecSet(ctx.up,0,1,0);
+	ctx.toNearPlane = 2.5;
+	z = demoTime - direction[43].startTime;
+	ctx.misc[8]=z;
+};
+var balls2LightFunc = function(scale) {
+	return function(ctx,lctx) {
+		var z = demoTime*30;
+		vecSet(lctx[0],scale*Math.cos(demoTime*2)*5,3,scale*Math.sin(demoTime*2)*5+z);
+		vecSet(lctx[1],1,1,1);
+		lctx[2] = 4;
+	};
+};
+var fract1CamCommon = function(ctx) {
+	var z = demoTime;
+	vecSet(ctx.camPos,4,2.5+.025*z,6.7);
+	vecSet(ctx.lookAt,0,2.5-.05*z,6.7);
+	vecSet(ctx.up,0,0,1);
+	ctx.misc[8] = ctx.misc[9] = 0;
+	ctx.toNearPlane = 3;
+};
+var fract1CamFunc = function(desync) {
+	var dsf = desyncFunc(desync);
+	return function(ctx){
+		fract1CamCommon(ctx);
+		dsf(ctx,this.time);
+	};
+};
+var fract2CamCommon = function(ctx,bs) {
+	vecSet(ctx.camPos,5*Math.sin(demoTime*.2),9*Math.cos(demoTime*.41),7.8);
+	vecCopy(ctx.lookAt,ctx.camPos);
+	ctx.lookAt[0] = Math.cos(demoTime*.2);
+	ctx.lookAt[1] = Math.sin(demoTime*.33);
+	ctx.lookAt[2] -= 2;
+	vecSet(ctx.up,0,0,1);
+	ctx.toNearPlane = 3;
+	ctx.misc[8] = bs;
+	ctx.misc[9] = 1;
+};
+
+var drawText = function(str,x) {
+	twoDCtx.shadowBlur = c2height/5;
+	twoDCtx.fillText( str , x , c2height / 2 );
+	twoDCtx.shadowBlur = 0;
+	twoDCtx.strokeText( str , x , c2height / 2 );
+};
+var titleText = function(str,shake,alpha,r,g,b) {
+	drawText( str , canvasWidth/15 );
+	context.misc[5] = 1 - c2rHeight + Math.random() * shake - shake * .5;
+	context.misc[6] = alpha;
+	vecSet( context.textColour , r , g , b );
+};
+var greetings = "Greetings to ... Mog, Sycop, Tim & Wullon ... Adinpsz ... Alcatraz ... ASD ... Bits'n'Bites ... Brain Control ... Cocoon ... Conspiracy ... Ctrl+Alt+Test ... Fairlight ... Farbrausch ... Kewlers ... LNX ... Loonies ... Mercury ... Popsy Team ... Razor 1911 ... RGBA ... 7th Cube ... Still ... TPOLM ... TRBL ... Umlaut Design ... X-Men ... Youth Uprising ... Everyone here at DemoJS 2014!";
+var greetingsText = function() {
+	var t = ( demoTime - direction[34].startTime ) * canvasWidth * .5;
+	drawText( greetings , canvasWidth - t );
+	context.misc[5] = 1 - c2rHeight + Math.random() * .02 - .01;
+	context.misc[6] = 1;
+	vecSet( context.textColour , 1 , 1 , 1 );
+};
+
+var squaresCam = function(ctx) {
+	var t = demoTime - direction[25].startTime;
+	var z = t*10 - 80;
+	vecSet(ctx.camPos,z,0,0);
+	vecSet(ctx.lookAt,z+Math.cos(t*.5) * 80,Math.sin(t*.25)*40,100);
+	vecSet(ctx.up,0,1,0);
+};
+
+var squaresCam2 = function(ctx,s) {
+	var t = demoTime - direction[s].startTime;
+	var z = t*20 - 80;
+	vecSet(ctx.camPos,0,0,z);
+	vecSet(ctx.lookAt,Math.cos(t*.5) * 80,Math.sin(t*.25)*40,z+100);
+	vecSet(ctx.up,Math.sin(t),Math.cos(t),0);
+	ctx.misc[4] = Math.random() * .025 - .0125;
+};
+
+var tunnelLight = function(ctx,lctx) {
+	vecAdd(lctx[0],vecNorm(lctx[0],vecScale(lctx[0],ctx.lookAt,-1)),ctx.camPos);
+	lctx[0][1] -= .5;
+	vecSet(lctx[1],3,3,3);
+	lctx[2] = 30;
+};
+var tunnelCam = function(ctx,mul) {
+	var z = demoTime*30*ctx.tunMul;
+	vecSet(ctx.camPos,1.1*Math.cos(z*.1),Math.sin(z*.02),z);
+	z += 5;
+	vecSet(ctx.lookAt,-Math.sin(z*.05),-.7*Math.cos(z*.033),z);
+	vecSet(ctx.up,0,1,0);
+	ctx.toNearPlane = 2;
+};
+var tunnelLightBall = function(ctx,lctx) {
+	vecSet(lctx[0] , 4*Math.sin(demoTime*.5)*Math.cos(demoTime*.7) ,
+			3*Math.cos(demoTime*1.5),
+			demoTime*30*ctx.tunMul+14+16*Math.sin(demoTime*3.3)*Math.cos(demoTime*.77)
+	);
+	vecSet(lctx[1],1,1,1);
+	lctx[2] = 15;
+};
+
+var direction = [
+	{
+		// Music rows
+		rows: 36 ,
+		// Raymarcher id
+		rm: 0 ,
+		setGlobals: function( ctx ) {
+			var z = tun1CamCommon(ctx,this);
+			z *= z*z;
+			ctx.misc[2] = 1 - z;
+			ctx.toNearPlane = 5;
+		} ,
+		lights: [
+			lightFunc(3,20)
+		] ,
+		updateText: null
+	} , {
+		rows: 18 ,
+		rm: 0 ,
+		setGlobals: function( ctx ) {
+			var z = tun1CamCommon(ctx,this);
+			ctx.toNearPlane = 5 - 2.25 * z;
+			ctx.misc[2] = 0;
+		} ,
+		lights: [
+			lightFunc(3,20)
+		] ,
+		updateText: null
+	} , {
+		rows: 36 ,
+		rm: 0 ,
+		setGlobals: function( ctx ) {
+			var z = tun1CamCommon(ctx,this);
+			ctx.toNearPlane = 2.75 - 2.25 * z;
+			ctx.misc[2] = z;
+		} ,
+		lights: [
+			lightFunc(3,20)
+		] ,
+		updateText: null
+	} , {
+		rows: 18 ,
+		rm: 3 ,
+		setGlobals: function( ctx ) {
+			var z = demoTime*3;
+			vecSet(ctx.camPos,0,4,z);
+			vecSet(ctx.lookAt,4,0,z);
+			vecSet(ctx.up,0,0,1);
+			z = ctx.stepTime / this.time;
+			z *= z*z;
+			ctx.misc[2] = 1 - z;
+			ctx.toNearPlane = 2.5;
+		} ,
+		lights: [
+			lightFunc(.75,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 3 ,
+		setGlobals: balls1CamFunc(4,0,0) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 3 ,
+		setGlobals: balls1CamFunc(2,-2,0) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 3 ,
+		setGlobals: balls1CamFunc( 6 , 0 , -.5 ) ,
+		lights: [
+			lightFunc(.5,4)
+		] ,
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 3 ,
+		setGlobals: balls1CamFunc( 6 , 0 , .5 ) ,
+		lights: [
+			lightFunc(.5,4)
+		] ,
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 3 ,
+		setGlobals: balls1CamFunc( 2 , 2 , -.2 ) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 3 ,
+		setGlobals: balls1CamFunc( 2 , 2 , .2 ) ,
+		lights: [
+			lightFunc(1,8)
+		] ,
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 3 ,
+		setGlobals: balls1CamFunc( 2 , 5 , -.7 ) ,
+		lights: [
+			lightFunc(1,2)
+		] ,
+		updateText: null
+	} , {
+		rows: 7 ,
+		rm: 3 ,
+		setGlobals: balls1CamFunc( 2 , 2 , .7 ) ,
+		lights: [
+			lightFunc(1,2)
+		] ,
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 3 ,
+		setGlobals: function(ctx) {
+			var z = demoTime*3;
+			ctx.misc[2] = ctx.stepTime / this.time;
+			vecSet(ctx.camPos,0,4+ctx.misc[2]*2,z);
+			vecSet(ctx.lookAt,2,0,z+2);
+			vecSet(ctx.up,0,0,1);
+			ctx.misc[3] = 1;
+		} ,
+		lights: [
+			lightFunc(1,2)
+		] ,
+		updateText: null
+	} , {
+		rows: 21 ,
+		rm: 1 ,
+		setGlobals: function( ctx ) {
+			fract1CamCommon(ctx);
+			ctx.misc[3] = 1;
+			var z = ctx.stepTime / this.time;
+			ctx.misc[2] = 1 - z*z*z;
+		} , lights : [
+			fractLight = function(ctx,lctx) {
+				vecCopy(lctx[0],ctx.camPos);
+				lctx[0][2]+=2;
+				vecSet(lctx[1],1,1,1);
+				lctx[2] = 3;
+			}
+		],
+		updateText: null
+	} , {
+		rows: 14 ,
+		rm: 1 ,
+		setGlobals: fract1CamFunc(0) ,
+		lights : [
+			fractLight
+		],
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 1 ,
+		setGlobals: fract1CamFunc(-.4) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 1 ,
+		setGlobals: fract1CamFunc(.4) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 1 ,
+		setGlobals: fract1CamFunc(-.2) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 9 ,
+		rm: 1 ,
+		setGlobals: fract1CamFunc(.2) ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 12 ,
+		rm: 1 ,
+		setGlobals: function(ctx) {
+			fract1CamCommon(ctx);
+			ctx.misc[4] = -( 6 * ctx.stepTime / this.time ) % 1;
+			ctx.misc[4] *= Math.random( ) * .25 + .75;
+		} ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 1 ,
+		setGlobals: function(ctx) {
+			fract1CamCommon(ctx);
+			ctx.misc[3] = .4;
+			ctx.misc[2] = ctx.stepTime / this.time;
+			ctx.toNearPlane = 3 - 2.5*Math.max(1,2*ctx.misc[2]);
+			ctx.misc[4] = ( 30 * ctx.misc[2] ) % 1;
+			ctx.misc[4] *= Math.random( ) * .15 + .85;
+		} ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 3 ,
+		rm: 1 ,
+		setGlobals: neutral = function(ctx) {
+			fract1CamCommon(ctx);
+			ctx.misc[3] = .4;
+			ctx.misc[2] = 1;
+			ctx.misc[4] = 0;
+		} ,
+		lights : [ fractLight ],
+		updateText: null
+	} , {
+		rows: 12 ,
+		rm: 1 ,
+		setGlobals: neutral ,
+		lights : [ fractLight ],
+		updateText: function() {
+			titleText( "TheT(ourist)" , .08 , 1 , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 12 ,
+		rm: 1 ,
+		setGlobals: neutral ,
+		lights : [ fractLight ],
+		updateText: function() {
+			titleText( "TheT(ourist)" , .08 , 1 - context.stepTime / this.time , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 12 ,
+		rm: 1 ,
+		setGlobals: neutral ,
+		lights : [ fractLight ],
+		updateText: function() {
+			titleText( "presents" , .08 , 1 - context.stepTime / this.time , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 20 ,
+		rm: 2 ,
+		setGlobals: function(ctx) {
+			squaresCam(ctx);
+			ctx.toNearPlane = 2.5;
+			ctx.misc[2] = 1 - ctx.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , context.stepTime / this.time , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 52 ,
+		rm: 2 ,
+		setGlobals: function(ctx) {
+			squaresCam(ctx);
+			ctx.misc[2] = 0;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , 1 , 1 , 1 , 1 );
+		}
+	} , {
+		rows: 12 ,
+		rm: 2 ,
+		setGlobals: function(ctx){
+			squaresCam(ctx);
+			var z = context.stepTime / this.time;
+			ctx.misc[3] = 1;
+			ctx.misc[2] = Math.max(0,1-z*2);
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			var z = context.stepTime / this.time;
+			titleText( "Sine City" , .04 , 1 , 1 - z , 1 - z * .5 , 1 - z );
+		}
+	} , {
+		rows: 12 ,
+		rm: 2 ,
+		setGlobals: function(ctx) {
+			squaresCam(ctx);
+			var z = context.stepTime / this.time;
+			ctx.misc[4] = ( 1 - z ) * .7 + Math.random() * .025 - .0125;
+			ctx.misc[1] = 1 - .5 * z;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , 1 , 0 , .5 , 0 );
+		}
+	} , {
+		rows: 9 ,
+		rm: 2 ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,29);
+			var z = context.stepTime / this.time;
+			ctx.misc[2] = Math.max(0,1-z*1.5);
+			ctx.misc[4] += ( z - 1 ) * .3;
+			ctx.misc[1] = .5 - .5 * z;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: function() {
+			titleText( "Sine City" , .04 , 1 - context.stepTime / this.time , 0 , .5 , 0 );
+		}
+	} , {
+		rows: 69 ,
+		rm: 2 ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,29);
+			ctx.misc[1] = 0;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: null
+	} , {
+		rows: 11 ,
+		rm: 2 ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,29);
+			ctx.misc[3] = .2;
+			ctx.misc[2] = context.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ],
+		updateText: null
+	} , {
+		rows: 11 ,
+		rm: 0 ,
+		setGlobals: function(ctx) {
+			ctx.tunMul = 1;
+			tunnelCam(ctx);
+			ctx.misc[2] = 1 - context.stepTime / this.time;
+		} ,
+		lights : [ tunnelLight ],
+		updateText: null
+	} , {
+		rows: 17 ,
+		rm: 0 ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[2] = 0;
+			ctx.misc[4] = (1.2 - 1.2 * context.stepTime / this.time) * (.98 + .04*Math.random());
+		} ,
+		lights : [ tunnelLight ],
+		updateText: null
+	} , {
+		rows: 18 ,
+		rm: 0 ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[4] = 0;
+			ctx.misc[8] = context.stepTime / this.time;
+		} ,
+		lights : [ tunnelLight ],
+		updateText: greetingsText
+	} , {
+		rows: 36 ,
+		rm: 0 ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[2] = 1 - Math.min(4*context.stepTime / this.time,1);
+			ctx.misc[8] = 1;
+		} ,
+		lights : tunLights = [ tunnelLight , tunnelLightBall ],
+		updateText: greetingsText
+	} , {
+		rows: 33 ,
+		rm: 0 ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[2] = context.stepTime / this.time;
+			ctx.misc[3] = .7;
+			ctx.misc[4] = -((4*ctx.misc[2])%1)*(.95+Math.random()*.1);
+		} ,
+		lights : tunLights ,
+		updateText: greetingsText
+	} , {
+		rows: 9 ,
+		rm: 1 ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,0);
+			ctx.misc[2] = context.stepTime / this.time;
+			ctx.misc[3] = 1;
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 20 ,
+		rm: 1 ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,context.stepTime / this.time);
+			ctx.misc[2] = 0;
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 31 ,
+		rm: 1 ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.misc[2] = Math.min(0,1-5*context.stepTime / this.time);
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 5 ,
+		rm: 1 ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.misc[2] = 1-context.stepTime / this.time;
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 18 ,
+		rm: 1 ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.misc[2] = Math.min(0,1-5*context.stepTime / this.time);
+			ctx.misc[4] = Math.max(0,1.6*context.stepTime / this.time - .8 )*(.95+Math.random()*.1);
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 12 ,
+		rm: 1 ,
+		setGlobals: function(ctx) {
+			fract2CamCommon(ctx,1);
+			ctx.misc[3] = .1;
+			ctx.misc[2] = context.stepTime / this.time;
+			ctx.misc[4] = .8*(1-ctx.misc[2])*(.9+Math.random()*.2);
+		} ,
+		lights : [ fractLight ],
+		updateText: greetingsText
+	} , {
+		rows: 22 ,
+		rm: 3 ,
+		setGlobals: function(ctx) {
+			balls2CamCommon(ctx);
+			ctx.misc[2] = 1-context.stepTime / this.time;
+			ctx.misc[4] = 0;
+		} ,
+		lights : ballsLights = [ lightFunc(.6,30) , balls2LightFunc(1),balls2LightFunc(-1) ],
+		updateText: greetingsText
+	} , {
+		rows: 59 ,
+		rm: 3 ,
+		setGlobals: function(ctx) {
+			balls2CamCommon(ctx);
+			ctx.misc[3] = .8;
+			ctx.misc[2] = Math.max(0,1-(12*context.stepTime / this.time)%4);
+		} ,
+		lights : ballsLights,
+		updateText: greetingsText
+	} , {
+		rows: 8 ,
+		rm: 3 ,
+		setGlobals: function(ctx) {
+			balls2CamCommon(ctx);
+			ctx.misc[3] = .1;
+			ctx.misc[2] = context.stepTime / this.time;
+			ctx.misc[4] = .1-Math.random()*.2;
+		} ,
+		lights : ballsLights,
+		updateText: null
+	} , {
+		rows: 7 ,
+		rm: 0 ,
+		setGlobals: function(ctx) {
+			ctx.tunMul = 2;
+			tunnelCam(ctx);
+			ctx.misc[2] = 1-context.stepTime / this.time;
+			ctx.misc[4] = .1-Math.random()*.2;
+		} ,
+		lights : tunLights ,
+		updateText: null
+	} , {
+		rows: 22 ,
+		rm: 0 ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[4] = .1-Math.random()*.2;
+		} ,
+		lights : tunLights ,
+		updateText: null
+	} , {
+		rows: 10 ,
+		rm: 0 ,
+		setGlobals: function(ctx) {
+			tunnelCam(ctx);
+			ctx.misc[4] = context.stepTime*4+.1-Math.random()*.2;
+			ctx.misc[3] = 1;
+			ctx.misc[2] = context.stepTime / this.time;
+		} ,
+		lights : tunLights ,
+		updateText: null
+	} , {
+		rows: 10 ,
+		rm: 2 ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.misc[4] = (demoTime-direction[48].startTime)*4+.1-Math.random()*.2;
+			ctx.misc[2] = 1-context.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	} , {
+		rows: 40 ,
+		rm: 2 ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.misc[4] = -(demoTime-direction[48].startTime)*6;
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	} , {
+		rows: 40 ,
+		rm: 2 ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.misc[4] = (demoTime-direction[48].startTime)*8;
+			ctx.misc[3] = 0;
+			ctx.misc[2] = context.stepTime / this.time;
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	} , {
+		rows: 68 ,
+		rm: 2 ,
+		setGlobals: function(ctx) {
+			squaresCam2(ctx,49);
+			ctx.misc[2] = 1
+		} ,
+		lights : [ lightFunc(1,30) ] ,
+		updateText: null
+	}
+];
+var t = 0;
+var BPM = 120;
+for ( var i in direction ) {
+	direction[ i ].startTime = t;
+	t += ( direction[i].time = direction[ i ].rows * 60 / ( BPM * 4 ) );
+	direction[ i ].endTime = t;
+}
+rows = t * BPM * 4 / 60;
+t = 0;
+
+function createRaymarcherCode( def ) {
+	var w = 'uniform ';
+	var code = shaderHeader
+		+ [ w+'mat3 u0;' ,
+		    w+'sampler2D u1;' ,
+		    w+'!3 u2,u3;' ,
+		    w+'float u4[10];'
+		  ].join('\n');
+	var u = 5;
+	for ( var i in def[15] ) {
+		code += w+'!3 u' + u++ + ', u' + u++ + ';'+w+'float u' + u++ + ';';
+	}
+	code += [
+		"const !2 c=!2(1.,-1.)*"+def[5]+";" ,
+		"float p,z,w,u,o,zy,q,x,a,zz;" ,
+		"!2 e,h;" ,
+		"!3 l=!3(zx,1.),m,r,s=u2,yx=!3(1.),n=!3(.0),b,v,xxx,xy,d,xx,xz,y;" ,
+		"!4 f;" ,
+
+		"float g(float x)" ,
+		"{" ,
+			"return fract(sin(x)*43758.5453);" ,
+		"}" ,
+
+		"float yy(!3 x)" ,
+		"{" ,
+			"m=floor(x),y=fract(x)," ,
+			"y*=y*(3.-2.*y)," ,
+			"z=m.x+m.y*57.+m.z*113.;" ,
+			"return mix(mix(mix(g(z),g(z+1.),y.x)," ,
+					"mix(g(z+57.),g(z+58.),y.x),y.y)," ,
+				"mix(mix(g(z+113.),g(z+114.),y.x)," ,
+					"mix(g(z+170.),g(z+171.),y.x),y.y),y.z);" ,
+		"}" ,
+
+		"float yyx(!2 x,float a)" ,
+		"{" ,
+			"e=pow(abs(x),!2(a));" ,
+			"return pow(e.x+e.y,1./a);" ,
+		"}" ,
+
+		"mat2 t(float x)" ,
+		"{" ,
+			"e=!2(cos(x),sin(x));" ,
+			"return mat2(-e.x,e.y,e.y,e.x);" ,
+		"}" ,
+
+		"float yz(!3 x)" ,
+		"{" ,
+			"return length(mod(x.xy,!2(15.))-!2(7.5))-.5+.05*sin(x.z*9.42477);" ,
+		"}" ,
+
+		"!2 k(!3 x,float a) {"
+	].join("\n");
+	code += def[14] + '}';
+	code += [
+			"void main()" ,
+			"{" ,
+				"l.y+=mod(u4[4],1.)*2.2;" ,
+				"if(l.y>1.){" ,
+					"if(l.y < 1.2)discard;" ,
+					"l.y-=2.2;" ,
+				"}" ,
+				"l.x*=1.6," ,
+				"r=normalize(l*u0);" ,
+
+				"for(int j=0;j<2;j++){" ,
+					"v=r,xxx=s,xy=!3(.0)," ,
+					"x=.0,a=" + def[1] + ';' ,
+					"for(int i=0;i<" + def[4] + ";i++){" ,
+						"h=k(s+r*x,x);" ,
+						"if(h.x< a||i>" + def[4] + "/(j+1)||x>" + def[0] + ".)break;" ,
+						"x+=h.x*" + def[3] + ",a*=" + shaderFloat( def[2] ) + ";" ,
+					"}" ,
+					"h.x=x;",
+
+					"if(x<"+ def[0]+ ".){" ,
+						"d=s+r*x," ,
+						"f=!4(" ,
+							"k(d+c.xyy,x).x," ,
+							"k(d+c.yyx,x).x," ,
+							"k(d+c.yxy,x).x," ,
+							"k(d+c.xxx,x).x" ,
+						")," ,
+						"xx=normalize(f.x*c.xyy+f.y*c.yyx+f.z*c.yxy+f.w*c.xxx)," ,
+						"a=.0," ,
+						"p=" + def[12] + ";" ,
+						"for(int i=1;i<="+def[10]+";i++)" ,
+							"x=(float(i)/"+def[10]+".)*"+ shaderFloat( def[11] ) + "," ,
+							"m=d+xx*x," ,
+							"a+=p*(x-k(m,distance(m,s)).x)," ,
+							"p*=.5;" ,
+						"q=max(.1,1.-clamp(pow(a,1.),.0,1.));" ,
+		].join('\n');
+
+	for(var i in def[13])
+		w=materials[def[13][i]],code+=(i>0?'else ':'')+'if(h.y==' + i + '.)xz='+(w[4]?('mix(!3('+shaderVec(w[0])+'),!3('+shaderVec(w[5])+'),yy(d*'+shaderFloat(def[6]*w[4])+'))'):('!3('+shaderVec(w[0])+')'))+',w='+shaderFloat(w[1])+',u='+w[2]+',o='+w[3]+';';
+
+	code += [
+						"v=reflect(r,xx)," ,
+						"z="+def[9]+"*h.x," ,
+						"z=clamp(exp(-z*z*z*1.442695),.0,1.)," ,
+						"x=clamp((1.+dot(normalize(v+r),r)),.0,1.),a=x*x," ,
+						"zz=o+(1.-o)*x*a*a*(u*.9+.1)," ,
+						"y=mix(!3(1.),xz/dot(!3(.299,.587,.114),xz),w)," ,
+						"m=!3(.0)," ,
+						"zy=exp2(4.+6.*u)," ,
+		].join('\n');
+
+	u = 5;
+	for ( var l in def[15] ) {
+		var b = def[15][l];
+		code += [
+			"p=length(b=u" + u + "-d)," ,
+			"b/=p," ,
+			"p=max(1.,p-u" + (u+2) + ")*" + b[0] + "," ,
+			"p=1./max(1.,p*p)," ,
+			"m+=mix((1.-w)*xz*q,y*pow(max(dot(reflect(r,xx),b),.0),zy)*(zy+2.)/8.,zz)*p*max(dot(b,xx),.0)*u" + (u+1) + ","
+		].join('\n');
+		u+=3;
+	}
+	code += [
+						"xy=yx*z*normalize(y)*o*(u*.9+.1)*zz," ,
+						"m=mix(!3(" + shaderFloat(def[8]) + "),m,z)," ,
+						"xxx+=normalize(v)*" + def[7] + ";" ,
+					"}else" ,
+						"m=!3(" + shaderFloat(def[8]) + ');'
+	].join('\n');
+
+	u=5;
+	for ( var l in def[15] ) {
+		var b = def[15][l];
+		var h = b[1];
+		if ( h ) {
+			code += [
+					"b=s-u" + u + "," ,
+					"p=dot(r,r),a=2.*dot(b,r)," ,
+					"x=a*a-4.*p*(dot(b,b)-" + (h*h) + ")," ,
+					"e=x<.0?!2(-1.):(x=sqrt(x),-.5*!2(a+x,a-x)/p)," ,
+					"e=!2(min(e.x,e.y),max(e.x,e.y));" ,
+					"if(e.x>.0&&e.y<h.x)" ,
+						"m+=u" + (u+2) + "*u" + (u+1) + "*pow((e.y-e.x)/" + shaderFloat(h*2) + ",64.);"
+			].join( "\n" );
+		}
+		u+=3;
+	}
+
+	code += [
+					"n+=m*yx;" ,
+					"if(all(lessThan(xy,!3(.01))))break;" ,
+					"yx=xy," ,
+					"s=xxx," ,
+					"r=normalize(v);" ,
+				"}" ,
+
+				"h=!2(zx.x,l.y)*.5+.5," ,
+				"h.y=(1.-h.y-u4[5])/u4[7]," ,
+				"f=texture2D(u1,h)," ,
+				"n=max(!3(.0),mix(mix(mix(n,(n.x==n.y&&n.x==n.z)?n:!3(dot(n,!3(.299,.587,.114))),u4[1]),!3(u4[3]),smoothstep(.05,.95,u4[2])),f.rgb*u3,f.a*u4[6])-!3(.004)),",
+
+				"x=(l.x+1.)*(l.y+1.)*(u4[0]*10.),",
+				"gl_FragColor=!4((1.-(smoothstep(.98,1.,yy(l*8.+u4[0]*20.))+smoothstep(.95,1.,yy(l*1.5+u4[0]*10.))))*smoothstep(1.042+.008*cos(u4[0]*40.),.8,yyx(zx,8.))*(1.-(mod((mod(x,13.)+1.)*(mod(x,47.)+1.),.01))*8.)*((.95+.05*cos(u4[0]*41.))*(n*(6.2*n+.5))/(n*(6.2*n+!3(1.7))+!3(.06))+!3(smoothstep(.98,1.,yy(l*8.-u4[0]*40.)))),1.);",
+			"}" ,
+	].join('\n');
+	return code;
+}
+
+var cmU=vomNew(3),
+    cmV=vomNew(3),
+    cmW=vomNew(3),
+    cd=vomNew(3),
+    cu=vomNew(3),
+    cm=vomNew(9);
+
+
+// Main
+
+function resize() {
+	var vw=window.innerWidth,vh=window.innerHeight;
+	var cw=Math.floor(vh*1.6),ch=Math.floor(vw*.625);
+	if(cw>vw){
+		C1.width=canvasWidth=vw;
+		C1.height=canvasHeight=ch;
+	}else{
+		C1.width=canvasWidth=cw;
+		C1.height=canvasHeight=vh;
+	}
+	C2.style.width=C2.width=canvasWidth;
+	c2height=C2.style.height=C2.height=Math.max(canvasHeight/8,100);
+	c2rHeight=c2height/canvasHeight;
+	twoDCtx.shadowColor = "#ccc";
+	twoDCtx.font = "normal small-caps bold " + Math.floor(c2height/2) + "px monospace";
+	twoDCtx.fillStyle = "#111";
+	twoDCtx.strokeStyle = "#ddd";
+	C1.style.left=Math.floor((vw-canvasWidth)*.5);
+	C1.style.top=Math.floor((vh-canvasHeight)*.5);
+	glCtx.viewport(0,0,canvasWidth,canvasHeight);
+}
+
+// FIXME: re-enable! document.body.style.cursor = 'none';
+document.body.style.background = 'black';
+document.body.innerHTML = '<canvas id=C1 style=position:fixed></canvas><canvas id=C2 style=display:none>';
+glCtx=C1.getContext('webgl');
+twoDCtx = C2.getContext('2d');
+(window.onresize=resize)();
+var shaders = [
+	[ glCtx.VERTEX_SHADER , shaderHeader + "attribute !2 i;void main(){gl_Position=!4(i,.0,1.),zx=i;}"
+	]
+];
+var programs = {};
+var context = {
+	camPos: vomNew(3),
+	lookAt: vomNew(3),
+	up: vomNew(3),
+	toNearPlane: 0 ,
+	misc: vomNew(10) ,
+	textColour: vomNew(3) ,
+	lights: [[vomNew(3),vomNew(3),0],[vomNew(3),vomNew(3),0],[vomNew(3),vomNew(3),0]]
+};
+var sn = 1;
+for ( var i in raymarchers ) {
+	var rm = raymarchers[i];
+	shaders[sn] = [glCtx.FRAGMENT_SHADER,createRaymarcherCode(rm)];
+	programs[i] = [ 5+rm[15].length*3 , 0 , sn++ ];
+}
+for ( var i in shaders ) {
+	var def = shaders[i];
+	glCtx.shaderSource( i= shaders[i] = glCtx.createShader( def[0] ) , def[1].replace(/!/g,'vec') );
+	glCtx.compileShader( i );
+	if (!glCtx.getShaderParameter(i, glCtx.COMPILE_STATUS)) {
+		def[1] = def[1].split( /\n/ );
+		for ( var k in def[1] ) {
+			var j = parseInt(k)+1;
+			def[1][k] = j + ": " + def[1][k];
+		}
+		throw "SHADER ERROR\n" + glCtx.getShaderInfoLog(i) + "\n" + def[1].join('\n');
+	}
+}
+for ( var name in programs ) {
+	var p = glCtx.createProgram( );
+	var d = programs[name];
+	var ul = d.shift();
+	while( d.length ) {
+		glCtx.attachShader( p , shaders[ d.shift() ] );
+	}
+	glCtx.linkProgram( p );
+	var nul = [];
+	while ( ul-- ) {
+		nul[ul] = glCtx.getUniformLocation( p , 'u' + ul );
+	}
+	programs[name] = [p,nul];
+}
+vtxBuffer = glCtx.createBuffer( );
+glCtx.bindBuffer( glCtx.ARRAY_BUFFER , glCtx.createBuffer( ) );
+glCtx.bufferData( glCtx.ARRAY_BUFFER , vomNew([1,4,1,-1,-4,-1]) , glCtx.STATIC_DRAW );
+glCtx.clearColor(0,0,0,1);
+
+textTexture = glCtx.createTexture( );
+glCtx.bindTexture( glCtx.TEXTURE_2D , textTexture );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_S, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_T, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MIN_FILTER, glCtx.NEAREST );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MAG_FILTER, glCtx.NEAREST );
+glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+
+timeStart = previousFrame = 0;
+FRAME_TIME = 100/3;
+
+paused = 0;
+document.body.onkeypress = function(e) {
+	if ( e.keyCode == 32 ) {
+		var now = Date.now();
+		if ( paused ) {
+			timeStart += now - paused;
+			paused = 0;
+			requestAnimationFrame(draw);
+			A.play( );
+		} else {
+			paused = now;
+			A.pause( );
+		}
+	}
+};
+
+var demoTime;
+mainfunc = function(){
+requestAnimationFrame(draw=function(time){
+	if ( ! paused ) {
+		requestAnimationFrame(draw);
+	}
+	if ( timeStart == 0 ) {
+		A.play( );
+		timeStart = time;
+		previousFrame = timeStart - FRAME_TIME;
+	}
+	var delta = time - previousFrame;
+	demoTime = .001*(time - timeStart);
+	if ( delta < FRAME_TIME ) {
+		return;
+	}
+	previousFrame = time - ( delta % FRAME_TIME );
+
+	var ds = direction[t];
+	while ( ds && ds.endTime < demoTime ) {
+		ds=direction[++t];
+	}
+	if ( ! ds ) {
+		A.pause( );
+		return;
+	}
+	context.misc[0] = demoTime;
+	context.misc[7] = c2rHeight;
+	context.stepTime = demoTime - ds.startTime;
+	if ( ds.updateText ) {
+		twoDCtx.clearRect( 0 , 0 , canvasWidth , 100 );
+		ds.updateText();
+		glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+	}
+
+	var rm = raymarchers[ds.rm], ctx = context;
+	ds.setGlobals( ctx );
+	vecNorm(cmW,vecSub(cmW,ctx.lookAt,ctx.camPos));
+	vecNorm(cmU,vecCross(cmU,ctx.up,cmW));
+	vecNorm(cmV,vecCross(cmV,cmW,cmU));
+	vecScale(cmW,cmW,ctx.toNearPlane);
+	vecs2Mat3(cm,cmU,cmV,cmW);
+
+	for ( var i in ds.lights ) {
+		ds.lights[ i ](ctx,ctx.lights[ i ]);
+	}
+
+	var p = programs[ds.rm];
+	glCtx.useProgram( p[ 0 ] );
+	glCtx.enableVertexAttribArray( 0 );
+	glCtx.vertexAttribPointer( 0 , 2 , glCtx.FLOAT , false , 8 , 0 );
+	p = p[1];
+
+	var u = 0;
+	glCtx.uniformMatrix3fv( p[u++] , false , cm );
+	glCtx.uniform1i( p[u++] , 0 );
+	glCtx.uniform3fv( p[u++] , ctx.camPos );
+	glCtx.uniform3fv( p[u++] , ctx.textColour );
+	glCtx.uniform1fv( p[u++] , ctx.misc );
+	for ( var i in ds.lights ) {
+		glCtx.uniform3fv( p[u++] , context.lights[ i ][0] );
+		glCtx.uniform3fv( p[u++] , context.lights[ i ][1] );
+		glCtx.uniform1f( p[u++] , context.lights[ i ][2] );
+	}
+	glCtx.drawArrays( 4 , 0 , 3 );
+})
+}
+
+if ( USE_SYNTH ) {
+	synth = new CPlayer();
+	synth.init(song);
+	synthGen = setInterval(function(){
+		if ( synth.generate() == 1 ) {
+			clearInterval(synthGen);
+			var s = '' , a = synth.createWave();
+			for(var i=0;i<a.length;i++)
+				s+= String.fromCharCode(a[i]);
+			A = document.createElement("audio");
+			A.src= 'data:audio/wav;base64,' + btoa(s);
+			A.oncanplaythrough=mainfunc;
+		}
+
+	}, 0);
+} else {
+	A = document.createElement("audio");
+	A.oncanplaythrough=mainfunc;
+	A.src= 'music.ogg';
+}
diff --git a/201410_-_Sine_City/sine-city-packing-3-direction.html b/201410_-_Sine_City/sine-city-packing-3-direction.html
new file mode 100644
index 0000000..68667c7
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-3-direction.html
@@ -0,0 +1,5 @@
+<body>
+<script language="javascript" src="music.js"></script>
+<script language="javascript" src="player-small.js"></script>
+<script language="javascript" src="sine-city-packing-3-direction.js"></script>
+
diff --git a/201410_-_Sine_City/sine-city-packing-3-direction.js b/201410_-_Sine_City/sine-city-packing-3-direction.js
new file mode 100644
index 0000000..c20a09c
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-3-direction.js
@@ -0,0 +1,1062 @@
+var USE_SYNTH = 1;
+
+// Vector stuff
+function vecOp(code) {
+	return eval('(function(o,a,b){for(var i=o.length;--i>=0;)' + code + ';return o})')
+}
+function vomNew(s) {
+	return new Float32Array(s)
+}
+var vecNorm = function(o,a) {
+	var l = Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
+	return l ? vecScale(o,a,1/l) : vecCopy(o,a);
+};
+var vecCross = function(o,a,b) {
+	return vecSet(o,
+		a[1]*b[2]-a[2]*b[1] ,
+		a[2]*b[0]-a[0]*b[2] ,
+		a[0]*b[1]-a[1]*b[0]
+	);
+};
+var vecs2Mat3 = function(o,a,b,c){
+	for ( var i = 0 ; i < 3 ; i ++ ) {
+		o[i*3+0] = a[i];
+		o[i*3+1] = b[i];
+		o[i*3+2] = c[i];
+	}
+};
+var vecSet = vecOp('o[i]=arguments[i+1]') ,
+    vecCopy = vecOp('o[i]=a[i]') ,
+    vecSub = vecOp('o[i]=a[i]-b[i]') ,
+    vecScale = vecOp('o[i]=a[i]*b');
+
+
+// Shaders
+var shaderHeader = 'precision highp float;varying !2 zx;';
+
+
+function shaderFloat( v ) {
+	return '' + v + ( v == Math.floor(v) ? '.' : '' );
+}
+function shaderVec( v ) {
+	return v.map(shaderFloat).join(',');
+}
+
+
+// Raymarchers
+
+var materials = [[[.05],.7,.02,.01],[[.2],.7,.9,.01,5,[.1]],[[1],.5,.4,.02],[[3,0,0],.3,.1,.6,6,[.6,0,0]],[[0,2,0],.9,.5,.4,15,[0,.2,0]],[[3,1.5,0],.95,.6,.9,.3,[.3,.6,0]],[[.1],0,.04,.002,3,[3]],[[0,1.5,2],.9,.3,.4]];
+var raymarchers = [[100,.025,1,.7,64,.0005,.5,.3,.4,.015,4,2,.75,[0,1,2,3],'y=x+.1*(sin(x.zxy*.17+u4[0]*.5)+sin(x.yzx*.7+u4[0]*1.5))*8.5*(1.+cos(sin(x.z*.1)+x.z*.3)),z=14.-length(y.xy),w=x.x==.0?1.570795*(x.y>.0?1.:-1.):atan(x.y,x.x),q=8.35-u4[8]*1.35,y=!3(9.*(mod(w+x.z*.02,.628)-.314),length(x.xy)-9.,mod(x.z,12.56)-6.28),u=min(length(y.xy)-.25+.1*cos(x.z*8.+u4[0]*.1),length(y.yz)-.5),y=!3(q*(mod(w+x.z*.02,1.256636)-.628318),y.y+9.-q,mod(x.z,62.8318)-31.4159),o=step(u,z)+1.,z=min(u,z),u=length(y)-1.3;if(u<z)z=u,o=3.;y.y+=q-9.,u=yyx(y.yz,8.)-2.;if(u<z)z=u,o=.0;return !2(z,o);',[[.25,0],[.5,.5]]],[6,.00025,1.08,.7,100,.000008,10,.03,2.1,.2,6,.4,5.1,[0,2,5],'z=1.,y=x;for(int i=0;i<7;i++)x=2.*clamp(x,-!3(.58,.9,1.1),!3(.58,.9,1.1))-x,w=max((1.3+u4[9]*.1*cos(u4[0]*.5))/dot(x,x),1.),x*=w,z*=w;w=length(x.xy),e=!2(w-3.,-w*x.z/length(x)-2.*log(1.+.01*a))/abs(z),w=max(e.x,e.y),o=step(e.y,e.x),y+=!3(.1,.3,-.4)*u0-u2+.25*sin(x*1.),e.x=length(y)-.1*u4[8];if(e.x<w)w=e.x,o=2.;return !2(w,o);',[[.05]]],[100,.000025,1,.75,80,.00005,.5,.3,3,.01,4,.75,4.75,[6,0,4],'x.xy*=t(a*.009),w=min(min(yz(x.xzy),yz(x)),yz(x.yzx)),y=mod(x,!3(15.))-!3(7.5),o=step(z=max(length(max(abs(y)-!3(2.5),!3(.0)))-.25,3.5-length(y)),w),w=min(w,z),z=length(y+.1*sin(y*5.5+u4[0]))-2.;if(z<w)w=z,o=2.;return !2(w,o);',[[.05]]],[20,.0005,1,.6,128,.0001,.5,.002,.01,.08,4,.5,1.75,[2,7],'y=x,y.xz=mod(x.xz,8.)-4.,y.yz*=t(u4[8]+.1*a),y.xy*=t(u4[8]*.5+.2*a),y.y*=.9+.1*sin(u4[8]*5.),w=max(length(y)-3.,-min(length(y)-2.8,max(mod(y.y,.8)-.4,-mod(y.y+.4,.8)+.4))),z=x.y+1.+sin(x.x*4.+u4[8]*2.)*sin(x.z+u4[8])*.1,o=clamp(.5+.5*(z-w)/1.,.0,1.),w=mix(z,w,o)-1.*o*(1.-o),y=x,y.xz=mod(y.xz,8.)-4.,y/=1.25+.25*sin(u4[8]*5.),y.xy*=t(u4[8]*5.),y.yz*=t(u4[8]*2.5),z=max(length(y)-1.,.04-length(max(abs(mod(y,.5)-.25)-!3(.15),!3(.0))));return !2(min(w,z),step(z,w));',[[.02],[.05,.5],[.05,.5]]]];
+
+var tunMul=1;
+var randAround = function(c,d) { return c - d + Math.random()*d*2 };
+var lightFunc = function(intensity,distance) {
+	return function(lctx) {
+		vecCopy(lctx[0],camPos);
+		lctx[1]=intensity;
+		lctx[2] = distance;
+	}
+};
+var tun1CamCommon = function(dir) {
+	var z = demoTime*6;
+	vecSet(camPos,-6,0,z);
+	vecSet(lookAt,1,0,z);
+	vecSet(camUp,0,1,0);
+	misc[1] = 1;
+	misc[8] = 0;
+};
+var desyncFunc = function(desync) {
+	return function(tt) {
+		var z = stepTime / direction[t][6];
+		misc[4] = -z * desync;
+		if ( desync > 0 ) {
+			misc[4] += desync;
+		}
+		misc[4] *= randAround(.875,.125);
+	};
+};
+var balls1CamFunc = function(lax,laz,desync) {
+	var dsf = desyncFunc(desync);
+	return function() {
+		var z = demoTime*3;
+		vecSet(camPos,0,4,z);
+		vecSet(lookAt,lax,0,z+laz);
+		vecSet(camUp,0,0,1);
+		misc[8]= misc[2] = 0;
+		dsf();
+	};
+};
+var balls2CamCommon = function() {
+	var z = demoTime*5;
+	vecSet(camPos,Math.cos(demoTime)*12,8,Math.sin(demoTime)*12+z);
+	vecSet(lookAt,1,0,z);
+	vecSet(camUp,0,1,0);
+	toNearPlane = 2.5;
+	z = demoTime - direction[43][5];
+	misc[8]=z;
+};
+var balls2LightFunc = function(scale) {
+	return function(lctx) {
+		var z = demoTime*30;
+		vecSet(lctx[0],scale*Math.cos(demoTime*2)*5,3,scale*Math.sin(demoTime*2)*5+z);
+		lctx[1] = 1;
+		lctx[2] = 4;
+	};
+};
+var fract1CamCommon = function() {
+	var z = demoTime;
+	vecSet(camPos,4,2.5+.025*z,6.7);
+	vecSet(lookAt,0,2.5-.05*z,6.7);
+	vecSet(camUp,0,0,1);
+	misc[8] = misc[9] = 0;
+	toNearPlane = 3;
+};
+var fract1CamFunc = function(desync) {
+	var dsf = desyncFunc(desync);
+	return function(){
+		fract1CamCommon();
+		dsf();
+	};
+};
+var fract2CamCommon = function(bs) {
+	vecSet(camPos,5*Math.sin(demoTime*.2),9*Math.cos(demoTime*.41),7.8);
+	vecCopy(lookAt,camPos);
+	lookAt[0] = Math.cos(demoTime*.2);
+	lookAt[1] = Math.sin(demoTime*.33);
+	lookAt[2] -= 2;
+	vecSet(camUp,0,0,1);
+	toNearPlane = 3;
+	misc[8] = bs;
+	misc[9] = 1;
+};
+
+var drawText = function(str,x) {
+	twoDCtx.shadowBlur = c2height/5;
+	twoDCtx.fillText( str , x , c2height / 2 );
+	twoDCtx.shadowBlur = 0;
+	twoDCtx.strokeText( str , x , c2height / 2 );
+};
+var titleText = function(str,shake,alpha,r,g,b) {
+	drawText( str , canvasWidth/15 );
+	misc[5] = 1 - c2rHeight + randAround(0,shake);
+	misc[6] = alpha;
+	vecSet( textColour , r , g , b );
+};
+var greetingsText = function() {
+	var t = ( demoTime - direction[34][5] ) * canvasWidth * .5;
+	drawText( "Greetings to ... Mog, Sycop, Tim & Wullon ... Adinpsz ... Alcatraz ... ASD ... Bits'n'Bites ... Brain Control ... Cocoon ... Conspiracy ... Ctrl+Alt+Test ... Fairlight ... Farbrausch ... Kewlers ... LNX ... Loonies ... Mercury ... Popsy Team ... Razor 1911 ... RGBA ... 7th Cube ... Still ... TPOLM ... TRBL ... Umlaut Design ... X-Men ... Youth Uprising ... Everyone here at DemoJS 2014!" , canvasWidth - t );
+	misc[5] = 1 - c2rHeight + randAround(.01,.01);
+	misc[6] = 1;
+	vecSet( textColour , 1 , 1 , 1 );
+};
+
+var squaresCam = function() {
+	var t = demoTime - direction[25][5];
+	var z = t*10 - 80;
+	vecSet(camPos,z,0,0);
+	vecSet(lookAt,z+Math.cos(t*.5) * 80,Math.sin(t*.25)*40,100);
+	vecSet(camUp,0,1,0);
+};
+
+var squaresCam2 = function(s) {
+	var t = demoTime - direction[s][5];
+	var z = t*20 - 80;
+	vecSet(camPos,0,0,z);
+	vecSet(lookAt,Math.cos(t*.5) * 80,Math.sin(t*.25)*40,z+100);
+	vecSet(camUp,Math.sin(t),Math.cos(t),0);
+	misc[4] = randAround(.0125,.0125);
+};
+
+var tunnelLight = function(lctx) {
+	vecSub(lctx[0],camPos,vecNorm(lctx[0],lookAt));
+	lctx[0][1] -= .5;
+	lctx[1] = 3;
+	lctx[2] = 30;
+};
+var tunnelCam = function(mul) {
+	var z = demoTime*30*tunMul;
+	vecSet(camPos,1.1*Math.cos(z*.1),Math.sin(z*.02),z);
+	z += 5;
+	vecSet(lookAt,-Math.sin(z*.05),-.7*Math.cos(z*.033),z);
+	vecSet(camUp,0,1,0);
+	toNearPlane = 2;
+};
+var tunnelLightBall = function(lctx) {
+	vecSet(lctx[0] , 4*Math.sin(demoTime*.5)*Math.cos(demoTime*.7) ,
+			3*Math.cos(demoTime*1.5),
+			demoTime*30*tunMul+14+16*Math.sin(demoTime*3.3)*Math.cos(demoTime*.77)
+	);
+	lctx[1] = 1;
+	lctx[2] = 15;
+};
+
+// direction    0<->rows / 1<->rm / 2<->setGlobals / 3<->lights / 4<->updateText / 5<->startTime / 6<->time / 7<->endTime
+var direction = [
+	[
+		// Music rows
+		36 ,
+		// Raymarcher id
+		0 ,
+		function( ) {
+			tun1CamCommon();
+			misc[2] = 1 - rStepTime*rStepTime*rStepTime;
+			toNearPlane = 5;
+		} ,
+		[
+			lightFunc(3,20)
+		]
+	] , [
+		18 ,
+		0 ,
+		function( ) {
+			tun1CamCommon();
+			toNearPlane = 5 - 2.25 * rStepTime;
+			misc[2] = 0;
+		} ,
+		[
+			lightFunc(3,20)
+		]
+	] , [
+		36 ,
+		0 ,
+		function( ) {
+			tun1CamCommon();
+			toNearPlane = 2.75 - 2.25 * rStepTime;
+			misc[2] = rStepTime;
+		} ,
+		[
+			lightFunc(3,20)
+		]
+	] , [
+		18 ,
+		3 ,
+		function( ) {
+			var z = demoTime*3;
+			vecSet(camPos,0,4,z);
+			vecSet(lookAt,4,0,z);
+			vecSet(camUp,0,0,1);
+			z = rStepTime;
+			z *= z*z;
+			misc[2] = 1 - z;
+			toNearPlane = 2.5;
+		} ,
+		[
+			lightFunc(.75,8)
+		]
+	] , [
+		22 ,
+		3 ,
+		balls1CamFunc(4,0,0) ,
+		[
+			lightFunc(1,8)
+		]
+	] , [
+		22 ,
+		3 ,
+		balls1CamFunc(2,-2,0) ,
+		[
+			lightFunc(1,8)
+		]
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 6 , 0 , -.5 ) ,
+		[
+			lightFunc(.5,4)
+		]
+	] , [
+		9 ,
+		3 ,
+		balls1CamFunc( 6 , 0 , .5 ) ,
+		[
+			lightFunc(.5,4)
+		]
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , -.2 ) ,
+		[
+			lightFunc(1,8)
+		]
+	] , [
+		9 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , .2 ) ,
+		[
+			lightFunc(1,8)
+		]
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 2 , 5 , -.7 ) ,
+		[
+			lightFunc(1,2)
+		]
+	] , [
+		7 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , .7 ) ,
+		[
+			lightFunc(1,2)
+		]
+	] , [
+		9 ,
+		3 ,
+		function() {
+			var z = demoTime*3;
+			misc[2] = rStepTime;
+			vecSet(camPos,0,4+rStepTime*2,z);
+			vecSet(lookAt,2,0,z+2);
+			vecSet(camUp,0,0,1);
+			misc[3] = 1;
+		} ,
+		[
+			lightFunc(1,2)
+		]
+	] , [
+		21 ,
+		1 ,
+		function( ) {
+			fract1CamCommon();
+			misc[3] = 1;
+			misc[2] = 1 - rStepTime*rStepTime*rStepTime;
+		} , [
+			fractLight = function(lctx) {
+				vecCopy(lctx[0],camPos);
+				lctx[0][2]+=2;
+				lctx[1] = 1;
+				lctx[2] = 3;
+			}
+		]
+	] , [
+		14 ,
+		1 ,
+		fract1CamFunc(0) ,
+		[
+			fractLight
+		]
+	] , [
+		3 ,
+		1 ,
+		fract1CamFunc(-.4) ,
+		[ fractLight ]
+	] , [
+		9 ,
+		1 ,
+		fract1CamFunc(.4) ,
+		[ fractLight ]
+	] , [
+		3 ,
+		1 ,
+		fract1CamFunc(-.2) ,
+		[ fractLight ]
+	] , [
+		9 ,
+		1 ,
+		fract1CamFunc(.2) ,
+		[ fractLight ]
+	] , [
+		12 ,
+		1 ,
+		function() {
+			fract1CamCommon();
+			misc[4] = -( 6 * rStepTime ) % 1;
+			misc[4] *= randAround(.875,.125);
+		} ,
+		[ fractLight ]
+	] , [
+		22 ,
+		1 ,
+		function() {
+			fract1CamCommon();
+			misc[3] = .4;
+			misc[2] = rStepTime;
+			toNearPlane = 3 - 2.5*Math.max(1,2*rStepTime);
+			misc[4] = ( 30 * misc[2] ) % 1;
+			misc[4] *= randAround(.925,.075);
+		} ,
+		[ fractLight ]
+	] , [
+		3 ,
+		1 ,
+		neutral = function() {
+			fract1CamCommon();
+			misc[3] = .4;
+			misc[2] = 1;
+			misc[4] = 0;
+		} ,
+		[ fractLight ]
+	] , [
+		12 ,
+		1 ,
+		neutral ,
+		[ fractLight ],
+		function() {
+			titleText( "TheT(ourist)" , .08 , 1 , 1 , 1 , 1 );
+		}
+	] , [
+		12 ,
+		1 ,
+		neutral ,
+		[ fractLight ],
+		function() {
+			titleText( "TheT(ourist)" , .08 , 1 - rStepTime , 1 , 1 , 1 );
+		}
+	] , [
+		12 ,
+		1 ,
+		neutral ,
+		[ fractLight ],
+		function() {
+			titleText( "presents" , .08 , 1 - rStepTime , 1 , 1 , 1 );
+		}
+	] , [
+		20 ,
+		2 ,
+		function() {
+			squaresCam();
+			toNearPlane = 2.5;
+			misc[2] = 1 - rStepTime;
+		} ,
+		[ lightFunc(1,30) ],
+		function() {
+			titleText( "Sine City" , .04 , rStepTime , 1 , 1 , 1 );
+		}
+	] , [
+		52 ,
+		2 ,
+		function() {
+			squaresCam();
+			misc[2] = 0;
+		} ,
+		[ lightFunc(1,30) ],
+		function() {
+			titleText( "Sine City" , .04 , 1 , 1 , 1 , 1 );
+		}
+	] , [
+		12 ,
+		2 ,
+		function(){
+			squaresCam();
+			misc[3] = 1;
+			misc[2] = Math.max(0,1-rStepTime*2);
+		} ,
+		[ lightFunc(1,30) ],
+		function() {
+			titleText( "Sine City" , .04 , 1 , 1 - rStepTime , 1 - rStepTime * .5 , 1 - rStepTime );
+		}
+	] , [
+		12 ,
+		2 ,
+		function() {
+			squaresCam();
+			misc[4] = ( 1 - rStepTime ) * .7 + randAround(.0125,.0125);
+			misc[1] = 1 - .5 * rStepTime;
+		} ,
+		[ lightFunc(1,30) ],
+		function() {
+			titleText( "Sine City" , .04 , 1 , 0 , .5 , 0 );
+		}
+	] , [
+		9 ,
+		2 ,
+		function() {
+			squaresCam2(29);
+			misc[2] = Math.max(0,1-rStepTime*1.5);
+			misc[4] += ( rStepTime - 1 ) * .3;
+			misc[1] = .5 - .5 * rStepTime;
+		} ,
+		[ lightFunc(1,30) ],
+		function() {
+			titleText( "Sine City" , .04 , 1 - rStepTime , 0 , .5 , 0 );
+		}
+	] , [
+		69 ,
+		2 ,
+		function() {
+			squaresCam2(29);
+			misc[1] = 0;
+		} ,
+		[ lightFunc(1,30) ]
+	] , [
+		11 ,
+		2 ,
+		function() {
+			squaresCam2(29);
+			misc[3] = .2;
+			misc[2] = rStepTime;
+		} ,
+		[ lightFunc(1,30) ]
+	] , [
+		11 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[2] = 1 - rStepTime;
+		} ,
+		[ tunnelLight ]
+	] , [
+		17 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[2] = 0;
+			misc[4] = (1.2 - 1.2 * rStepTime) * randAround(1,.02);
+		} ,
+		[ tunnelLight ]
+	] , [
+		18 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[4] = 0;
+			misc[8] = rStepTime;
+		} ,
+		[ tunnelLight ],
+		greetingsText
+	] , [
+		36 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[2] = 1 - Math.min(4*rStepTime,1);
+			misc[8] = 1;
+		} ,
+		tunLights = [ tunnelLight , tunnelLightBall ],
+		greetingsText
+	] , [
+		33 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[2] = rStepTime;
+			misc[3] = .7;
+			misc[4] = -((4*rStepTime)%1)*randAround(1,.05);
+		} ,
+		tunLights ,
+		greetingsText
+	] , [
+		9 ,
+		1 ,
+		function() {
+			fract2CamCommon(0);
+			misc[2] = rStepTime;
+			misc[3] = 1;
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		20 ,
+		1 ,
+		function() {
+			fract2CamCommon(rStepTime);
+			misc[2] = 0;
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		31 ,
+		1 ,
+		function() {
+			fract2CamCommon(1);
+			misc[2] = Math.min(0,1-5*rStepTime);
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		5 ,
+		1 ,
+		function() {
+			fract2CamCommon(1);
+			misc[2] = 1-rStepTime;
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		18 ,
+		1 ,
+		function() {
+			fract2CamCommon(1);
+			misc[2] = Math.min(0,1-5*rStepTime);
+			misc[4] = Math.max(0,1.6*rStepTime - .8 )*randAround(1,.05);
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		12 ,
+		1 ,
+		function() {
+			fract2CamCommon(1);
+			misc[3] = .1;
+			misc[2] = rStepTime;
+			misc[4] = .8*(1-rStepTime)*randAround(1,.1);
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		22 ,
+		3 ,
+		function() {
+			balls2CamCommon();
+			misc[2] = 1-rStepTime;
+			misc[4] = 0;
+		} ,
+		ballsLights = [ lightFunc(.6,30) , balls2LightFunc(1),balls2LightFunc(-1) ],
+		greetingsText
+	] , [
+		59 ,
+		3 ,
+		function() {
+			balls2CamCommon();
+			misc[3] = .8;
+			misc[2] = Math.max(0,1-(12*rStepTime)%4);
+		} ,
+		ballsLights,
+		greetingsText
+	] , [
+		8 ,
+		3 ,
+		function() {
+			balls2CamCommon();
+			misc[3] = .1;
+			misc[2] = rStepTime;
+			misc[4] = randAround(.1,.1);
+		} ,
+		ballsLights
+	] , [
+		7 ,
+		0 ,
+		function() {
+			tunMul = 2;
+			tunnelCam();
+			misc[2] = 1-rStepTime;
+			misc[4] = randAround(.1,.1);
+		} ,
+		tunLights
+	] , [
+		22 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[4] = randAround(.1,.1);
+		} ,
+		tunLights
+	] , [
+		10 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[4] = stepTime*4+randAround(.1,.1);
+			misc[3] = 1;
+			misc[2] = rStepTime;
+		} ,
+		tunLights
+	] , [
+		10 ,
+		2 ,
+		function() {
+			squaresCam2(49);
+			misc[4] = (demoTime-direction[48][5])*4+randAround(.1,.1);
+			misc[2] = 1-rStepTime;
+		} ,
+		[ lightFunc(1,30) ]
+	] , [
+		40 ,
+		2 ,
+		function() {
+			squaresCam2(49);
+			misc[4] = -(demoTime-direction[48][5])*6;
+		} ,
+		[ lightFunc(1,30) ]
+	] , [
+		40 ,
+		2 ,
+		function() {
+			squaresCam2(49);
+			misc[4] = (demoTime-direction[48][5])*8;
+			misc[3] = 0;
+			misc[2] = rStepTime;
+		} ,
+		[ lightFunc(1,30) ]
+	] , [
+		68 ,
+		2 ,
+		function() {
+			squaresCam2(49);
+			misc[2] = 1
+		} ,
+		[ lightFunc(1,30) ]
+	]
+];
+var t = 0;
+for ( var i in direction ) {
+	direction[ i ][5] = t;
+	t += ( direction[i][6] = direction[ i ][0] * .125 );
+	direction[ i ][7] = t;
+}
+t = 0;
+
+function createRaymarcherCode( def ) {
+	var w = 'uniform ';
+	var code = shaderHeader
+		+ [ w+'mat3 u0;' ,
+		    w+'sampler2D u1;' ,
+		    w+'!3 u2,u3;' ,
+		    w+'float u4[10];'
+		  ].join('\n');
+	var u = 5;
+	for ( var i in def[15] ) {
+		code += w+'!3 u' + u++ + ';'+w+'float u' + u++ + ', u' + u++ + ';';
+	}
+	code += [
+		"const !2 c=!2(1.,-1.)*"+def[5]+";" ,
+		"float p,z,w,u,o,zy,q,x,a,zz;" ,
+		"!2 e,h;" ,
+		"!3 l=!3(zx,1.),m,r,s=u2,yx=!3(1.),n=!3(.0),b,v,xxx,xy,d,xx,xz,y;" ,
+		"!4 f;" ,
+
+		"float g(float x)" ,
+		"{" ,
+			"return fract(sin(x)*43758.5453);" ,
+		"}" ,
+
+		"float yy(!3 x)" ,
+		"{" ,
+			"m=floor(x),y=fract(x)," ,
+			"y*=y*(3.-2.*y)," ,
+			"z=m.x+m.y*57.+m.z*113.;" ,
+			"return mix(mix(mix(g(z),g(z+1.),y.x)," ,
+					"mix(g(z+57.),g(z+58.),y.x),y.y)," ,
+				"mix(mix(g(z+113.),g(z+114.),y.x)," ,
+					"mix(g(z+170.),g(z+171.),y.x),y.y),y.z);" ,
+		"}" ,
+
+		"float yyx(!2 x,float a)" ,
+		"{" ,
+			"e=pow(abs(x),!2(a));" ,
+			"return pow(e.x+e.y,1./a);" ,
+		"}" ,
+
+		"mat2 t(float x)" ,
+		"{" ,
+			"e=!2(cos(x),sin(x));" ,
+			"return mat2(-e.x,e.y,e.y,e.x);" ,
+		"}" ,
+
+		"float yz(!3 x)" ,
+		"{" ,
+			"return length(mod(x.xy,!2(15.))-!2(7.5))-.5+.05*sin(x.z*9.42477);" ,
+		"}" ,
+
+		"!2 k(!3 x,float a) {"
+	].join("\n");
+	code += def[14] + '}';
+	code += [
+			"void main()" ,
+			"{" ,
+				"l.y+=mod(u4[4],1.)*2.2;" ,
+				"if(l.y>1.){" ,
+					"if(l.y < 1.2)discard;" ,
+					"l.y-=2.2;" ,
+				"}" ,
+				"l.x*=1.6," ,
+				"r=normalize(l*u0);" ,
+
+				"for(int j=0;j<2;j++){" ,
+					"v=r,xxx=s,xy=!3(.0)," ,
+					"x=.0,a=" + def[1] + ';' ,
+					"for(int i=0;i<" + def[4] + ";i++){" ,
+						"h=k(s+r*x,x);" ,
+						"if(h.x< a||i>" + def[4] + "/(j+1)||x>" + def[0] + ".)break;" ,
+						"x+=h.x*" + def[3] + ",a*=" + shaderFloat( def[2] ) + ";" ,
+					"}" ,
+					"h.x=x;",
+
+					"if(x<"+ def[0]+ ".){" ,
+						"d=s+r*x," ,
+						"f=!4(" ,
+							"k(d+c.xyy,x).x," ,
+							"k(d+c.yyx,x).x," ,
+							"k(d+c.yxy,x).x," ,
+							"k(d+c.xxx,x).x" ,
+						")," ,
+						"xx=normalize(f.x*c.xyy+f.y*c.yyx+f.z*c.yxy+f.w*c.xxx)," ,
+						"a=.0," ,
+						"p=" + def[12] + ";" ,
+						"for(int i=1;i<="+def[10]+";i++)" ,
+							"x=(float(i)/"+def[10]+".)*"+ shaderFloat( def[11] ) + "," ,
+							"m=d+xx*x," ,
+							"a+=p*(x-k(m,distance(m,s)).x)," ,
+							"p*=.5;" ,
+						"q=max(.1,1.-clamp(pow(a,1.),.0,1.));" ,
+		].join('\n');
+
+	for(var i in def[13])
+		w=materials[def[13][i]],code+=(i>0?'else ':'')+'if(h.y==' + i + '.)xz='+(w[4]?('mix(!3('+shaderVec(w[0])+'),!3('+shaderVec(w[5])+'),yy(d*'+shaderFloat(def[6]*w[4])+'))'):('!3('+shaderVec(w[0])+')'))+',w='+shaderFloat(w[1])+',u='+w[2]+',o='+w[3]+';';
+
+	code += [
+						"v=reflect(r,xx)," ,
+						"z="+def[9]+"*h.x," ,
+						"z=clamp(exp(-z*z*z*1.442695),.0,1.)," ,
+						"x=clamp((1.+dot(normalize(v+r),r)),.0,1.),a=x*x," ,
+						"zz=o+(1.-o)*x*a*a*(u*.9+.1)," ,
+						"y=mix(!3(1.),xz/dot(!3(.299,.587,.114),xz),w)," ,
+						"m=!3(.0)," ,
+						"zy=exp2(4.+6.*u)," ,
+		].join('\n');
+
+	u = 5;
+	for ( var l in def[15] ) {
+		var b = def[15][l];
+		code += [
+			"p=length(b=u" + u + "-d)," ,
+			"b/=p," ,
+			"p=max(1.,p-u" + (u+2) + ")*" + b[0] + "," ,
+			"p=1./max(1.,p*p)," ,
+			"m+=mix((1.-w)*xz*q,y*pow(max(dot(reflect(r,xx),b),.0),zy)*(zy+2.)/8.,zz)*p*max(dot(b,xx),.0)*!3(u" + (u+1) + "),"
+		].join('\n');
+		u+=3;
+	}
+	code += [
+						"xy=yx*z*normalize(y)*o*(u*.9+.1)*zz," ,
+						"m=mix(!3(" + shaderFloat(def[8]) + "),m,z)," ,
+						"xxx+=normalize(v)*" + def[7] + ";" ,
+					"}else" ,
+						"m=!3(" + shaderFloat(def[8]) + ');'
+	].join('\n');
+
+	u=5;
+	for ( var l in def[15] ) {
+		var b = def[15][l];
+		var h = b[1];
+		if ( h ) {
+			code += [
+					"b=s-u" + u + "," ,
+					"p=dot(r,r),a=2.*dot(b,r)," ,
+					"x=a*a-4.*p*(dot(b,b)-" + (h*h) + ")," ,
+					"e=x<.0?!2(-1.):(x=sqrt(x),-.5*!2(a+x,a-x)/p)," ,
+					"e=!2(min(e.x,e.y),max(e.x,e.y));" ,
+					"if(e.x>.0&&e.y<h.x)" ,
+						"m+=u" + (u+2) + "*!3(u" + (u+1) + ")*pow((e.y-e.x)/" + shaderFloat(h*2) + ",64.);"
+			].join( "\n" );
+		}
+		u+=3;
+	}
+
+	code += [
+					"n+=m*yx;" ,
+					"if(all(lessThan(xy,!3(.01))))break;" ,
+					"yx=xy," ,
+					"s=xxx," ,
+					"r=normalize(v);" ,
+				"}" ,
+
+				"h=!2(zx.x,l.y)*.5+.5," ,
+				"h.y=(1.-h.y-u4[5])/u4[7]," ,
+				"f=texture2D(u1,h)," ,
+				"n=max(!3(.0),mix(mix(mix(n,(n.x==n.y&&n.x==n.z)?n:!3(dot(n,!3(.299,.587,.114))),u4[1]),!3(u4[3]),smoothstep(.05,.95,u4[2])),f.rgb*u3,f.a*u4[6])-!3(.004)),",
+
+				"x=(l.x+1.)*(l.y+1.)*(u4[0]*10.),",
+				"gl_FragColor=!4((1.-(smoothstep(.98,1.,yy(l*8.+u4[0]*20.))+smoothstep(.95,1.,yy(l*1.5+u4[0]*10.))))*smoothstep(1.042+.008*cos(u4[0]*40.),.8,yyx(zx,8.))*(1.-(mod((mod(x,13.)+1.)*(mod(x,47.)+1.),.01))*8.)*((.95+.05*cos(u4[0]*41.))*(n*(6.2*n+.5))/(n*(6.2*n+!3(1.7))+!3(.06))+!3(smoothstep(.98,1.,yy(l*8.-u4[0]*40.)))),1.);",
+			"}" ,
+	].join('\n');
+	return code;
+}
+
+var cmU=vomNew(3),
+    cmV=vomNew(3),
+    cmW=vomNew(3),
+    cd=vomNew(3),
+    cu=vomNew(3),
+    cm=vomNew(9);
+
+
+// Main
+
+function resize() {
+	var vw=window.innerWidth,vh=window.innerHeight;
+	var cw=Math.floor(vh*1.6),ch=Math.floor(vw*.625);
+	if(cw>vw){
+		C1.width=canvasWidth=vw;
+		C1.height=canvasHeight=ch;
+	}else{
+		C1.width=canvasWidth=cw;
+		C1.height=canvasHeight=vh;
+	}
+	C2.style.width=C2.width=canvasWidth;
+	c2height=C2.style.height=C2.height=Math.max(canvasHeight/8,100);
+	c2rHeight=c2height/canvasHeight;
+	twoDCtx.shadowColor = "#ccc";
+	twoDCtx.font = "normal small-caps bold " + Math.floor(c2height/2) + "px monospace";
+	twoDCtx.fillStyle = "#111";
+	twoDCtx.strokeStyle = "#ddd";
+	C1.style.left=Math.floor((vw-canvasWidth)*.5);
+	C1.style.top=Math.floor((vh-canvasHeight)*.5);
+	glCtx.viewport(0,0,canvasWidth,canvasHeight);
+}
+
+// FIXME: re-enable! document.body.style.cursor = 'none';
+document.body.style.background = 'black';
+document.body.innerHTML = '<canvas id=C1 style=position:fixed></canvas><canvas id=C2 style=display:none>';
+glCtx=C1.getContext('webgl');
+twoDCtx = C2.getContext('2d');
+(window.onresize=resize)();
+var shaders = [
+	[ glCtx.VERTEX_SHADER , shaderHeader + "attribute !2 i;void main(){gl_Position=!4(i,.0,1.),zx=i;}"
+	]
+];
+var programs = {};
+var misc = vomNew(10) , camPos = vomNew(3),lookAt=vomNew(3),camUp=vomNew(3),toNearPlane=0,textColour=vomNew(3) , lights= [[vomNew(3),0,0],[vomNew(3),0,0],[vomNew(3),0,0]];
+var sn = 1;
+for ( var i in raymarchers ) {
+	var rm = raymarchers[i];
+	shaders[sn] = [glCtx.FRAGMENT_SHADER,createRaymarcherCode(rm)];
+	programs[i] = [ 5+rm[15].length*3 , 0 , sn++ ];
+}
+for ( var i in shaders ) {
+	var def = shaders[i];
+	glCtx.shaderSource( i= shaders[i] = glCtx.createShader( def[0] ) , def[1].replace(/!/g,'vec') );
+	glCtx.compileShader( i );
+	if (!glCtx.getShaderParameter(i, glCtx.COMPILE_STATUS)) {
+		def[1] = def[1].split( /\n/ );
+		for ( var k in def[1] ) {
+			var j = parseInt(k)+1;
+			def[1][k] = j + ": " + def[1][k];
+		}
+		throw "SHADER ERROR\n" + glCtx.getShaderInfoLog(i) + "\n" + def[1].join('\n');
+	}
+}
+for ( var name in programs ) {
+	var p = glCtx.createProgram( );
+	var d = programs[name];
+	var ul = d.shift();
+	while( d.length ) {
+		glCtx.attachShader( p , shaders[ d.shift() ] );
+	}
+	glCtx.linkProgram( p );
+	var nul = [];
+	while ( ul-- ) {
+		nul[ul] = glCtx.getUniformLocation( p , 'u' + ul );
+	}
+	programs[name] = [p,nul];
+}
+vtxBuffer = glCtx.createBuffer( );
+glCtx.bindBuffer( glCtx.ARRAY_BUFFER , glCtx.createBuffer( ) );
+glCtx.bufferData( glCtx.ARRAY_BUFFER , vomNew([1,4,1,-1,-4,-1]) , glCtx.STATIC_DRAW );
+glCtx.clearColor(0,0,0,1);
+
+textTexture = glCtx.createTexture( );
+glCtx.bindTexture( glCtx.TEXTURE_2D , textTexture );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_S, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_T, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MIN_FILTER, glCtx.NEAREST );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MAG_FILTER, glCtx.NEAREST );
+glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+
+timeStart = previousFrame = 0;
+FRAME_TIME = 100/3;
+
+paused = 0;
+document.body.onkeypress = function(e) {
+	if ( e.keyCode == 32 ) {
+		var now = Date.now();
+		if ( paused ) {
+			timeStart += now - paused;
+			paused = 0;
+			requestAnimationFrame(draw);
+			A.play( );
+		} else {
+			paused = now;
+			A.pause( );
+		}
+	}
+};
+
+var demoTime, rStepTime,stepTime;
+mainfunc = function(){
+requestAnimationFrame(draw=function(time){
+	if ( ! paused ) {
+		requestAnimationFrame(draw);
+	}
+	if ( timeStart == 0 ) {
+		A.play( );
+		timeStart = time;
+		previousFrame = timeStart - FRAME_TIME;
+	}
+	var delta = time - previousFrame;
+	demoTime = .001*(time - timeStart);
+	if ( delta < FRAME_TIME ) {
+		return;
+	}
+	previousFrame = time - ( delta % FRAME_TIME );
+
+	var ds = direction[t];
+	while ( ds && ds[7] < demoTime ) {
+		ds=direction[++t];
+	}
+	if ( ! ds ) {
+		A.pause( );
+		return;
+	}
+	misc[0] = demoTime;
+	misc[7] = c2rHeight;
+	stepTime = demoTime - ds[5];
+	rStepTime = stepTime / ds[6];
+	if ( ds[4] ) {
+		twoDCtx.clearRect( 0 , 0 , canvasWidth , 100 );
+		ds[4]();
+		glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+	}
+
+	ds[2]();
+	vecNorm(cmW,vecSub(cmW,lookAt,camPos));
+	vecNorm(cmU,vecCross(cmU,camUp,cmW));
+	vecNorm(cmV,vecCross(cmV,cmW,cmU));
+	vecScale(cmW,cmW,toNearPlane);
+	vecs2Mat3(cm,cmU,cmV,cmW);
+
+	for ( var i in ds[3] ) {
+		ds[3][i](lights[ i ]);
+	}
+
+	var p = programs[ds[1]];
+	glCtx.useProgram( p[ 0 ] );
+	glCtx.enableVertexAttribArray( 0 );
+	glCtx.vertexAttribPointer( 0 , 2 , glCtx.FLOAT , false , 8 , 0 );
+	p = p[1];
+
+	var u = 0;
+	glCtx.uniformMatrix3fv( p[u++] , false , cm );
+	glCtx.uniform1i( p[u++] , 0 );
+	glCtx.uniform3fv( p[u++] , camPos );
+	glCtx.uniform3fv( p[u++] , textColour );
+	glCtx.uniform1fv( p[u++] , misc );
+	for ( var i in ds[3] ) {
+		glCtx.uniform3fv( p[u++] , lights[ i ][0] );
+		glCtx.uniform1f( p[u++] , lights[ i ][1] );
+		glCtx.uniform1f( p[u++] , lights[ i ][2] );
+	}
+	glCtx.drawArrays( 4 , 0 , 3 );
+})
+}
+
+if ( USE_SYNTH ) {
+	synth = new CPlayer();
+	synth.init(song);
+	synthGen = setInterval(function(){
+		if ( synth.generate() == 1 ) {
+			clearInterval(synthGen);
+			var s = '' , a = synth.createWave();
+			for(var i=0;i<a.length;i++)
+				s+= String.fromCharCode(a[i]);
+			A = document.createElement("audio");
+			A.src= 'data:audio/wav;base64,' + btoa(s);
+			A.oncanplaythrough=mainfunc;
+		}
+
+	}, 0);
+} else {
+	A = document.createElement("audio");
+	A.oncanplaythrough=mainfunc;
+	A.src= 'music.ogg';
+}
diff --git a/201410_-_Sine_City/sine-city-packing-4-sound.html b/201410_-_Sine_City/sine-city-packing-4-sound.html
new file mode 100644
index 0000000..543ae8d
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-4-sound.html
@@ -0,0 +1,3 @@
+<body>
+<script language="javascript" src="sine-city-packing-4-sound.js"></script>
+
diff --git a/201410_-_Sine_City/sine-city-packing-4-sound.js b/201410_-_Sine_City/sine-city-packing-4-sound.js
new file mode 100644
index 0000000..0e508b0
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-4-sound.js
@@ -0,0 +1,1069 @@
+var USE_SYNTH = 1;
+
+var song=[[[0,198,128,0,3,192,128,1,0,0,96,128,28,0,0,0,0,2,63,61,13,16,44,8,0,0],[1,2,3,4,5,2,3,4,6,7,1,2,3,4,5,2,3,4,5,2,3,4,1,2,3,8,9],[[[115,,,,,,,,,,,,117,,,,,,,,,,,,113],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[115,,,,,,,,,,,,,,,110],[12,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,148]],[[115,,,,,,,,,,,,117,,,,,,,,,,,,118],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[122,,,,,,,,,,,,,,,123,,,,,115],[12,,,,,,,,,,,,,,,12,,,,,12,,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,8,,,,,128]],[[118,,,,,,,,,,,,117,,,,,,,,,,,,113],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[115],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,255]],[[,,,,,,,,,,,,,,,,118,118,118],[,,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,128]],[[122,,,,,,,,,,,,,,,123,,,,,115],[12,,,,,,,,,,,,,,,12,,,,,13,12,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,8,,,,,95,61]],[[],[]]]],[[0,255,116,1,0,255,101,0,0,15,1,4,45,0,13,6,1,2,62,27,60,48,0,0,44,2],[,1,,2,,1,,2,,3,4,4,5,4,5,4,5,4,5,4,5,4,5,4,3,6],[[[,,,,,139,,,139,139,,,,,,139,,,,,,,,139,,,139,139,,,,,139,139,139],[]],[[,,139,139,,,,,139,139,,,,,139,139,,,,,,,,,,139,139,139,,,,,139,139,139],[]],[[,,,139,,,,,139,139,,,,,,139,,,,,139,139,,,,,,139,,,,139,139,139],[]],[[139,,,,139,,139,,,139,,,139,,,,139,,139,,,139,,,139,,,,139,,139,,,139],[]],[[139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139],[]],[[139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139,139],[]]]],[[0,0,140,0,0,0,140,0,0,128,4,10,34,0,187,5,0,1,239,135,34,19,108,8,8,4],[,,1,,1,,3,,1,3,2,2,2,2,2,3,2,3,2,3,2,3,2,3,1],[[[,,,,,,,,,,127,,,,,,,,,,,,127,,,,,,,,,,,,127],[]],[[,,,139,,,,,,139,139,,,,,139,,,,,,139,139,,,,,139,,,,,139,,139],[]],[[,,127,,,,,,,,127,,,,127,,,,,,,,127,,,,127,,,,,,,,127],[]]]],[[1,192,128,0,3,201,128,0,0,93,5,6,58,3,195,6,1,3,35,63,14,17,11,10,61,6],[,,,,1,2,3,4,5,6,7,5,8,9,10,11,8,9,10,11,12,13,14,15,16],[[[,,,,,,,,147,146,145,,,,,,,,,,145,147,146,,,,,,,,,,149,148,147],[]],[[,,,,,,151,151,151,,,,,,,146,142,138,,,,,,,,,,,,,,,147,150,147],[]],[[,,146,,,146,,,,,,,,,147,146,145,,,,,,,,,,146,145,142,,,142,,,142],[]],[[,,141,,,,,,,,,,,,141,140,139,,,146,,,146,,,127],[]],[[,139,,151,,,,,,,,,,151,,139,,,,,,,,,,139,,151],[]],[[,139,,151,150,149,,,,,,,,139,,149,148,147,,,,,,,,139,,,146,,,145,,,144],[]],[[,139,,,139,142,,,142,144,146,,144,,,,146,147,,,147,146,141,,137,,,,142,141,,141,,137],[]],[[139,,127,,142,,,130,,,144,142,141,,129,,141,,,144,,,141,144,142,,,,149,,,146,,,151],[]],[[,149,,149,,146,144,142,,,141,,142,,,139,,,,151,147,,,,146,147,,144,146,,142,144,141,146],[]],[[,,,,,,,,147,146,145,,,,,141,144,147,146,,144,,137,,,144,146,142,144,,,142,144,141,146],[]],[[,146,,151,,146,,,,144,142,144,146,,,,142,,,,,139,,,,,151,146,139,144,139,142,141,142,151],[]],[[,,147,,,149,146,,,142,,142,141,,,144,,144,,,144,146,142,144,142,,,,151,150,149,,137,,149],[]],[[,151,,,147,151,,,146,151,,,,,144,151,,149,147,149,151,,146,,,144,143,142,,,139,,151,139],[]],[[,,134,,,134,,,134,,,146,144,,,141,144,,,146,147,146,,,144,,139,140,141,,,153,,,141],[]],[[,142,,151,,,142,143,144,,,,151,,,139,,,137,,149,,137,,,,125,,,141,142,141,,,146],[]],[[139,,127,139,,127,139,,127,139,127],[]]]],[[2,160,128,1,0,160,128,0,1,60,4,7,41,0,60,4,1,3,14,0,35,32,31,12,89,1],[,,,,,,,,,,,,1,2,1,2,1,2,1,2,1,2,1,2,1,3],[[[,,139,,,,,,,,,,,,139,,,,,,,,,,,,139,,,,,139,139,,,139],[]],[[,,139,,,151,,,139,,,151,,,139,,,151,,,139,,,151,,,139,,,151,,,146,146,146,146],[]],[[,,139,,,151,,,139,,,151,,,139,,139,139,139,139,127],[]]]],[[2,100,128,0,3,201,128,0,0,0,0,6,29,0,195,6,1,3,28,229,119,77,147,6,61,2],[,,,,,,,,,6,1,2,3,4,5,2,3,4,1,2,3,4,1,2,3,7],[[[115,115,115,115,115,115,115,115,115,115,115,115,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],[]],[[115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110],[]],[[115,115,115,115,115,115,115,115,115,115,115,115,117,117,117,117,117,117,117,117,117,117,117,117,118,118,118,118,118,118,118,118,118,118,118,118],[]],[[110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115],[]],[[118,118,118,118,118,118,118,118,118,118,118,118,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],[]],[[,,,,,,,,,,,,,,,,,,130,,130,,130,,130,,130,,130,118,130,118,130,118,130,118],[,,,,,,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2]],[[110,122,,122,134,,110,122,,122,134,,110,122,,111,123,,111,123,115,127,139,127,115],[,,,,,,,,,,,,,,,,,,,,26,25,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,147]]]],[[2,100,128,0,3,201,128,0,0,0,5,6,58,0,195,6,1,2,135,0,0,32,147,6,121,6],[],[]],[[2,100,128,0,3,201,128,0,0,0,5,6,58,0,195,6,1,2,135,0,0,32,147,6,121,6],[],[]]];
+
+
+var getnotefreq=function(n){return .003959503758*Math.pow(2,(n-128)/12)};
+
+var mOscillators = [
+	function(v){return Math.sin(v*6.283184)},
+	function(v){return (v%1)<.5?1:-1},
+	function(v){return 2*(v%1)-1},
+	function(v){var v2=(v%1)*4;return(v2<2)?(v2-1):(3-v2)}
+];
+
+var mCurrentCol=0,mNumWords=10717272,mMixBuf=new Int32Array(mNumWords);
+
+
+// Vector stuff
+function vecOp(code) {
+	return eval('(function(o,a,b){for(var i=o.length;--i>=0;)' + code + ';return o})')
+}
+function vomNew(s) {
+	return new Float32Array(s)
+}
+var vecNorm = function(o,a) {
+	var l = Math.sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
+	return l ? vecScale(o,a,1/l) : vecCopy(o,a);
+};
+var vecCross = function(o,a,b) {
+	return vecSet(o,
+		a[1]*b[2]-a[2]*b[1] ,
+		a[2]*b[0]-a[0]*b[2] ,
+		a[0]*b[1]-a[1]*b[0]
+	);
+};
+var vecs2Mat3 = function(o,a,b,c){
+	for ( var i = 0 ; i < 3 ; i ++ ) {
+		o[i*3+0] = a[i];
+		o[i*3+1] = b[i];
+		o[i*3+2] = c[i];
+	}
+};
+var vecSet = vecOp('o[i]=arguments[i+1]') ,
+    vecCopy = vecOp('o[i]=a[i]') ,
+    vecSub = vecOp('o[i]=a[i]-b[i]') ,
+    vecScale = vecOp('o[i]=a[i]*b');
+
+
+// Shaders
+var shaderHeader = 'precision highp float;varying !2 zx;';
+
+
+function shaderFloat( v ) {
+	return '' + v + ( v == Math.floor(v) ? '.' : '' );
+}
+function shaderVec( v ) {
+	return v.map(shaderFloat).join(',');
+}
+
+
+// Raymarchers
+
+var materials = [[[.05],.7,.02,.01],[[.2],.7,.9,.01,5,[.1]],[[1],.5,.4,.02],[[3,0,0],.3,.1,.6,6,[.6,0,0]],[[0,2,0],.9,.5,.4,15,[0,.2,0]],[[3,1.5,0],.95,.6,.9,.3,[.3,.6,0]],[[.1],0,.04,.002,3,[3]],[[0,1.5,2],.9,.3,.4]];
+var raymarchers = [[100,.025,1,.7,64,.0005,.5,.3,.4,.015,4,2,.75,[0,1,2,3],'y=x+.1*(sin(x.zxy*.17+u4[0]*.5)+sin(x.yzx*.7+u4[0]*1.5))*8.5*(1.+cos(sin(x.z*.1)+x.z*.3)),z=14.-length(y.xy),w=x.x==.0?1.570795*(x.y>.0?1.:-1.):atan(x.y,x.x),q=8.35-u4[8]*1.35,y=!3(9.*(mod(w+x.z*.02,.628)-.314),length(x.xy)-9.,mod(x.z,12.56)-6.28),u=min(length(y.xy)-.25+.1*cos(x.z*8.+u4[0]*.1),length(y.yz)-.5),y=!3(q*(mod(w+x.z*.02,1.256636)-.628318),y.y+9.-q,mod(x.z,62.8318)-31.4159),o=step(u,z)+1.,z=min(u,z),u=length(y)-1.3;if(u<z)z=u,o=3.;y.y+=q-9.,u=yyx(y.yz,8.)-2.;if(u<z)z=u,o=.0;return !2(z,o);',[[.25,0],[.5,.5]]],[6,.00025,1.08,.7,100,.000008,10,.03,2.1,.2,6,.4,5.1,[0,2,5],'z=1.,y=x;for(int i=0;i<7;i++)x=2.*clamp(x,-!3(.58,.9,1.1),!3(.58,.9,1.1))-x,w=max((1.3+u4[9]*.1*cos(u4[0]*.5))/dot(x,x),1.),x*=w,z*=w;w=length(x.xy),e=!2(w-3.,-w*x.z/length(x)-2.*log(1.+.01*a))/abs(z),w=max(e.x,e.y),o=step(e.y,e.x),y+=!3(.1,.3,-.4)*u0-u2+.25*sin(x*1.),e.x=length(y)-.1*u4[8];if(e.x<w)w=e.x,o=2.;return !2(w,o);',[[.05]]],[100,.000025,1,.75,80,.00005,.5,.3,3,.01,4,.75,4.75,[6,0,4],'x.xy*=t(a*.009),w=min(min(yz(x.xzy),yz(x)),yz(x.yzx)),y=mod(x,!3(15.))-!3(7.5),o=step(z=max(length(max(abs(y)-!3(2.5),!3(.0)))-.25,3.5-length(y)),w),w=min(w,z),z=length(y+.1*sin(y*5.5+u4[0]))-2.;if(z<w)w=z,o=2.;return !2(w,o);',[[.05]]],[20,.0005,1,.6,128,.0001,.5,.002,.01,.08,4,.5,1.75,[2,7],'y=x,y.xz=mod(x.xz,8.)-4.,y.yz*=t(u4[8]+.1*a),y.xy*=t(u4[8]*.5+.2*a),y.y*=.9+.1*sin(u4[8]*5.),w=max(length(y)-3.,-min(length(y)-2.8,max(mod(y.y,.8)-.4,-mod(y.y+.4,.8)+.4))),z=x.y+1.+sin(x.x*4.+u4[8]*2.)*sin(x.z+u4[8])*.1,o=clamp(.5+.5*(z-w)/1.,.0,1.),w=mix(z,w,o)-1.*o*(1.-o),y=x,y.xz=mod(y.xz,8.)-4.,y/=1.25+.25*sin(u4[8]*5.),y.xy*=t(u4[8]*5.),y.yz*=t(u4[8]*2.5),z=max(length(y)-1.,.04-length(max(abs(mod(y,.5)-.25)-!3(.15),!3(.0))));return !2(min(w,z),step(z,w));',[[.02],[.05,.5],[.05,.5]]]];
+
+var tunMul=1;
+var randAround = function(c,d) { return c - d + Math.random()*d*2 };
+var lightFunc = function(intensity,distance) {
+	return function(lctx) {
+		vecCopy(lctx[0],camPos);
+		lctx[1]=intensity;
+		lctx[2] = distance;
+	}
+};
+var tun1CamCommon = function(dir) {
+	var z = demoTime*6;
+	vecSet(camPos,-6,0,z);
+	vecSet(lookAt,1,0,z);
+	vecSet(camUp,0,1,0);
+	misc[1] = 1;
+	misc[8] = 0;
+};
+var desyncFunc = function(desync) {
+	return function(tt) {
+		var z = stepTime / direction[t][6];
+		misc[4] = -z * desync;
+		if ( desync > 0 ) {
+			misc[4] += desync;
+		}
+		misc[4] *= randAround(.875,.125);
+	};
+};
+var balls1CamFunc = function(lax,laz,desync) {
+	var dsf = desyncFunc(desync);
+	return function() {
+		var z = demoTime*3;
+		vecSet(camPos,0,4,z);
+		vecSet(lookAt,lax,0,z+laz);
+		vecSet(camUp,0,0,1);
+		misc[8]= misc[2] = 0;
+		dsf();
+	};
+};
+var balls2CamCommon = function() {
+	var z = demoTime*5;
+	vecSet(camPos,Math.cos(demoTime)*12,8,Math.sin(demoTime)*12+z);
+	vecSet(lookAt,1,0,z);
+	vecSet(camUp,0,1,0);
+	toNearPlane = 2.5;
+	z = demoTime - direction[43][5];
+	misc[8]=z;
+};
+var balls2LightFunc = function(scale) {
+	return function(lctx) {
+		var z = demoTime*30;
+		vecSet(lctx[0],scale*Math.cos(demoTime*2)*5,3,scale*Math.sin(demoTime*2)*5+z);
+		lctx[1] = 1;
+		lctx[2] = 4;
+	};
+};
+var fract1CamCommon = function() {
+	var z = demoTime;
+	vecSet(camPos,4,2.5+.025*z,6.7);
+	vecSet(lookAt,0,2.5-.05*z,6.7);
+	vecSet(camUp,0,0,1);
+	misc[8] = misc[9] = 0;
+	toNearPlane = 3;
+};
+var fract1CamFunc = function(desync) {
+	var dsf = desyncFunc(desync);
+	return function(){
+		fract1CamCommon();
+		dsf();
+	};
+};
+var fract2CamCommon = function(bs) {
+	vecSet(camPos,5*Math.sin(demoTime*.2),9*Math.cos(demoTime*.41),7.8);
+	vecCopy(lookAt,camPos);
+	lookAt[0] = Math.cos(demoTime*.2);
+	lookAt[1] = Math.sin(demoTime*.33);
+	lookAt[2] -= 2;
+	vecSet(camUp,0,0,1);
+	toNearPlane = 3;
+	misc[8] = bs;
+	misc[9] = 1;
+};
+
+var drawText = function(str,x) {
+	twoDCtx.shadowBlur = c2height/5;
+	twoDCtx.fillText( str , x , c2height / 2 );
+	twoDCtx.shadowBlur = 0;
+	twoDCtx.strokeText( str , x , c2height / 2 );
+};
+var titleText = function(str,shake,alpha,r,g,b) {
+	drawText( str , canvasWidth/15 );
+	misc[5] = 1 - c2rHeight + randAround(0,shake);
+	misc[6] = alpha;
+	vecSet( textColour , r , g , b );
+};
+var greetingsText = function() {
+	var t = ( demoTime - direction[34][5] ) * canvasWidth * .5;
+	drawText( "Greetings to ... Mog, Sycop, Tim & Wullon ... Adinpsz ... Alcatraz ... ASD ... Bits'n'Bites ... Brain Control ... Cocoon ... Conspiracy ... Ctrl+Alt+Test ... Fairlight ... Farbrausch ... Kewlers ... LNX ... Loonies ... Mercury ... Popsy Team ... Razor 1911 ... RGBA ... 7th Cube ... Still ... TPOLM ... TRBL ... Umlaut Design ... X-Men ... Youth Uprising ... Everyone here at DemoJS 2014!" , canvasWidth - t );
+	misc[5] = 1 - c2rHeight + randAround(.01,.01);
+	misc[6] = 1;
+	vecSet( textColour , 1 , 1 , 1 );
+};
+
+var squaresCam = function() {
+	var t = demoTime - direction[25][5];
+	var z = t*10 - 80;
+	vecSet(camPos,z,0,0);
+	vecSet(lookAt,z+Math.cos(t*.5) * 80,Math.sin(t*.25)*40,100);
+	vecSet(camUp,0,1,0);
+};
+
+var squaresCam2 = function(s) {
+	var t = demoTime - direction[s][5];
+	var z = t*20 - 80;
+	vecSet(camPos,0,0,z);
+	vecSet(lookAt,Math.cos(t*.5) * 80,Math.sin(t*.25)*40,z+100);
+	vecSet(camUp,Math.sin(t),Math.cos(t),0);
+	misc[4] = randAround(.0125,.0125);
+};
+
+var tunnelLight = function(lctx) {
+	vecSub(lctx[0],camPos,vecNorm(lctx[0],lookAt));
+	lctx[0][1] -= .5;
+	lctx[1] = 3;
+	lctx[2] = 30;
+};
+var tunnelCam = function(mul) {
+	var z = demoTime*30*tunMul;
+	vecSet(camPos,1.1*Math.cos(z*.1),Math.sin(z*.02),z);
+	z += 5;
+	vecSet(lookAt,-Math.sin(z*.05),-.7*Math.cos(z*.033),z);
+	vecSet(camUp,0,1,0);
+	toNearPlane = 2;
+};
+var tunnelLightBall = function(lctx) {
+	vecSet(lctx[0] , 4*Math.sin(demoTime*.5)*Math.cos(demoTime*.7) ,
+			3*Math.cos(demoTime*1.5),
+			demoTime*30*tunMul+14+16*Math.sin(demoTime*3.3)*Math.cos(demoTime*.77)
+	);
+	lctx[1] = 1;
+	lctx[2] = 15;
+};
+
+// direction    0<->rows / 1<->rm / 2<->setGlobals / 3<->lights / 4<->updateText / 5<->startTime / 6<->time / 7<->endTime
+var direction = [
+	[
+		// Music rows
+		36 ,
+		// Raymarcher id
+		0 ,
+		function( ) {
+			tun1CamCommon();
+			misc[2] = 1 - rStepTime*rStepTime*rStepTime;
+			toNearPlane = 5;
+		} ,
+		[
+			lightFunc(3,20)
+		]
+	] , [
+		18 ,
+		0 ,
+		function( ) {
+			tun1CamCommon();
+			toNearPlane = 5 - 2.25 * rStepTime;
+			misc[2] = 0;
+		} ,
+		[
+			lightFunc(3,20)
+		]
+	] , [
+		36 ,
+		0 ,
+		function( ) {
+			tun1CamCommon();
+			toNearPlane = 2.75 - 2.25 * rStepTime;
+			misc[2] = rStepTime;
+		} ,
+		[
+			lightFunc(3,20)
+		]
+	] , [
+		18 ,
+		3 ,
+		function( ) {
+			var z = demoTime*3;
+			vecSet(camPos,0,4,z);
+			vecSet(lookAt,4,0,z);
+			vecSet(camUp,0,0,1);
+			z = rStepTime;
+			z *= z*z;
+			misc[2] = 1 - z;
+			toNearPlane = 2.5;
+		} ,
+		[
+			lightFunc(.75,8)
+		]
+	] , [
+		22 ,
+		3 ,
+		balls1CamFunc(4,0,0) ,
+		[
+			lightFunc(1,8)
+		]
+	] , [
+		22 ,
+		3 ,
+		balls1CamFunc(2,-2,0) ,
+		[
+			lightFunc(1,8)
+		]
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 6 , 0 , -.5 ) ,
+		[
+			lightFunc(.5,4)
+		]
+	] , [
+		9 ,
+		3 ,
+		balls1CamFunc( 6 , 0 , .5 ) ,
+		[
+			lightFunc(.5,4)
+		]
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , -.2 ) ,
+		[
+			lightFunc(1,8)
+		]
+	] , [
+		9 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , .2 ) ,
+		[
+			lightFunc(1,8)
+		]
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 2 , 5 , -.7 ) ,
+		[
+			lightFunc(1,2)
+		]
+	] , [
+		7 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , .7 ) ,
+		[
+			lightFunc(1,2)
+		]
+	] , [
+		9 ,
+		3 ,
+		function() {
+			var z = demoTime*3;
+			misc[2] = rStepTime;
+			vecSet(camPos,0,4+rStepTime*2,z);
+			vecSet(lookAt,2,0,z+2);
+			vecSet(camUp,0,0,1);
+			misc[3] = 1;
+		} ,
+		[
+			lightFunc(1,2)
+		]
+	] , [
+		21 ,
+		1 ,
+		function( ) {
+			fract1CamCommon();
+			misc[3] = 1;
+			misc[2] = 1 - rStepTime*rStepTime*rStepTime;
+		} , [
+			fractLight = function(lctx) {
+				vecCopy(lctx[0],camPos);
+				lctx[0][2]+=2;
+				lctx[1] = 1;
+				lctx[2] = 3;
+			}
+		]
+	] , [
+		14 ,
+		1 ,
+		fract1CamFunc(0) ,
+		[
+			fractLight
+		]
+	] , [
+		3 ,
+		1 ,
+		fract1CamFunc(-.4) ,
+		[ fractLight ]
+	] , [
+		9 ,
+		1 ,
+		fract1CamFunc(.4) ,
+		[ fractLight ]
+	] , [
+		3 ,
+		1 ,
+		fract1CamFunc(-.2) ,
+		[ fractLight ]
+	] , [
+		9 ,
+		1 ,
+		fract1CamFunc(.2) ,
+		[ fractLight ]
+	] , [
+		12 ,
+		1 ,
+		function() {
+			fract1CamCommon();
+			misc[4] = -( 6 * rStepTime ) % 1;
+			misc[4] *= randAround(.875,.125);
+		} ,
+		[ fractLight ]
+	] , [
+		22 ,
+		1 ,
+		function() {
+			fract1CamCommon();
+			misc[3] = .4;
+			misc[2] = rStepTime;
+			toNearPlane = 3 - 2.5*Math.max(1,2*rStepTime);
+			misc[4] = ( 30 * misc[2] ) % 1;
+			misc[4] *= randAround(.925,.075);
+		} ,
+		[ fractLight ]
+	] , [
+		3 ,
+		1 ,
+		neutral = function() {
+			fract1CamCommon();
+			misc[3] = .4;
+			misc[2] = 1;
+			misc[4] = 0;
+		} ,
+		[ fractLight ]
+	] , [
+		12 ,
+		1 ,
+		neutral ,
+		[ fractLight ],
+		function() {
+			titleText( "TheT(ourist)" , .08 , 1 , 1 , 1 , 1 );
+		}
+	] , [
+		12 ,
+		1 ,
+		neutral ,
+		[ fractLight ],
+		function() {
+			titleText( "TheT(ourist)" , .08 , 1 - rStepTime , 1 , 1 , 1 );
+		}
+	] , [
+		12 ,
+		1 ,
+		neutral ,
+		[ fractLight ],
+		function() {
+			titleText( "presents" , .08 , 1 - rStepTime , 1 , 1 , 1 );
+		}
+	] , [
+		20 ,
+		2 ,
+		function() {
+			squaresCam();
+			toNearPlane = 2.5;
+			misc[2] = 1 - rStepTime;
+		} ,
+		[ lightFunc(1,30) ],
+		function() {
+			titleText( "Sine City" , .04 , rStepTime , 1 , 1 , 1 );
+		}
+	] , [
+		52 ,
+		2 ,
+		function() {
+			squaresCam();
+			misc[2] = 0;
+		} ,
+		[ lightFunc(1,30) ],
+		function() {
+			titleText( "Sine City" , .04 , 1 , 1 , 1 , 1 );
+		}
+	] , [
+		12 ,
+		2 ,
+		function(){
+			squaresCam();
+			misc[3] = 1;
+			misc[2] = Math.max(0,1-rStepTime*2);
+		} ,
+		[ lightFunc(1,30) ],
+		function() {
+			titleText( "Sine City" , .04 , 1 , 1 - rStepTime , 1 - rStepTime * .5 , 1 - rStepTime );
+		}
+	] , [
+		12 ,
+		2 ,
+		function() {
+			squaresCam();
+			misc[4] = ( 1 - rStepTime ) * .7 + randAround(.0125,.0125);
+			misc[1] = 1 - .5 * rStepTime;
+		} ,
+		[ lightFunc(1,30) ],
+		function() {
+			titleText( "Sine City" , .04 , 1 , 0 , .5 , 0 );
+		}
+	] , [
+		9 ,
+		2 ,
+		function() {
+			squaresCam2(29);
+			misc[2] = Math.max(0,1-rStepTime*1.5);
+			misc[4] += ( rStepTime - 1 ) * .3;
+			misc[1] = .5 - .5 * rStepTime;
+		} ,
+		[ lightFunc(1,30) ],
+		function() {
+			titleText( "Sine City" , .04 , 1 - rStepTime , 0 , .5 , 0 );
+		}
+	] , [
+		69 ,
+		2 ,
+		function() {
+			squaresCam2(29);
+			misc[1] = 0;
+		} ,
+		[ lightFunc(1,30) ]
+	] , [
+		11 ,
+		2 ,
+		function() {
+			squaresCam2(29);
+			misc[3] = .2;
+			misc[2] = rStepTime;
+		} ,
+		[ lightFunc(1,30) ]
+	] , [
+		11 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[2] = 1 - rStepTime;
+		} ,
+		[ tunnelLight ]
+	] , [
+		17 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[2] = 0;
+			misc[4] = (1.2 - 1.2 * rStepTime) * randAround(1,.02);
+		} ,
+		[ tunnelLight ]
+	] , [
+		18 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[4] = 0;
+			misc[8] = rStepTime;
+		} ,
+		[ tunnelLight ],
+		greetingsText
+	] , [
+		36 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[2] = 1 - Math.min(4*rStepTime,1);
+			misc[8] = 1;
+		} ,
+		tunLights = [ tunnelLight , tunnelLightBall ],
+		greetingsText
+	] , [
+		33 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[2] = rStepTime;
+			misc[3] = .7;
+			misc[4] = -((4*rStepTime)%1)*randAround(1,.05);
+		} ,
+		tunLights ,
+		greetingsText
+	] , [
+		9 ,
+		1 ,
+		function() {
+			fract2CamCommon(0);
+			misc[2] = rStepTime;
+			misc[3] = 1;
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		20 ,
+		1 ,
+		function() {
+			fract2CamCommon(rStepTime);
+			misc[2] = 0;
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		31 ,
+		1 ,
+		function() {
+			fract2CamCommon(1);
+			misc[2] = Math.min(0,1-5*rStepTime);
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		5 ,
+		1 ,
+		function() {
+			fract2CamCommon(1);
+			misc[2] = 1-rStepTime;
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		18 ,
+		1 ,
+		function() {
+			fract2CamCommon(1);
+			misc[2] = Math.min(0,1-5*rStepTime);
+			misc[4] = Math.max(0,1.6*rStepTime - .8 )*randAround(1,.05);
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		12 ,
+		1 ,
+		function() {
+			fract2CamCommon(1);
+			misc[3] = .1;
+			misc[2] = rStepTime;
+			misc[4] = .8*(1-rStepTime)*randAround(1,.1);
+		} ,
+		[ fractLight ],
+		greetingsText
+	] , [
+		22 ,
+		3 ,
+		function() {
+			balls2CamCommon();
+			misc[2] = 1-rStepTime;
+			misc[4] = 0;
+		} ,
+		ballsLights = [ lightFunc(.6,30) , balls2LightFunc(1),balls2LightFunc(-1) ],
+		greetingsText
+	] , [
+		59 ,
+		3 ,
+		function() {
+			balls2CamCommon();
+			misc[3] = .8;
+			misc[2] = Math.max(0,1-(12*rStepTime)%4);
+		} ,
+		ballsLights,
+		greetingsText
+	] , [
+		8 ,
+		3 ,
+		function() {
+			balls2CamCommon();
+			misc[3] = .1;
+			misc[2] = rStepTime;
+			misc[4] = randAround(.1,.1);
+		} ,
+		ballsLights
+	] , [
+		7 ,
+		0 ,
+		function() {
+			tunMul = 2;
+			tunnelCam();
+			misc[2] = 1-rStepTime;
+			misc[4] = randAround(.1,.1);
+		} ,
+		tunLights
+	] , [
+		22 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[4] = randAround(.1,.1);
+		} ,
+		tunLights
+	] , [
+		10 ,
+		0 ,
+		function() {
+			tunnelCam();
+			misc[4] = stepTime*4+randAround(.1,.1);
+			misc[3] = 1;
+			misc[2] = rStepTime;
+		} ,
+		tunLights
+	] , [
+		10 ,
+		2 ,
+		function() {
+			squaresCam2(49);
+			misc[4] = (demoTime-direction[48][5])*4+randAround(.1,.1);
+			misc[2] = 1-rStepTime;
+		} ,
+		[ lightFunc(1,30) ]
+	] , [
+		40 ,
+		2 ,
+		function() {
+			squaresCam2(49);
+			misc[4] = -(demoTime-direction[48][5])*6;
+		} ,
+		[ lightFunc(1,30) ]
+	] , [
+		40 ,
+		2 ,
+		function() {
+			squaresCam2(49);
+			misc[4] = (demoTime-direction[48][5])*8;
+			misc[3] = 0;
+			misc[2] = rStepTime;
+		} ,
+		[ lightFunc(1,30) ]
+	] , [
+		68 ,
+		2 ,
+		function() {
+			squaresCam2(49);
+			misc[2] = 1
+		} ,
+		[ lightFunc(1,30) ]
+	]
+];
+var t = 0;
+for ( var i in direction ) {
+	direction[ i ][5] = t;
+	t += ( direction[i][6] = direction[ i ][0] * .125 );
+	direction[ i ][7] = t;
+}
+t = 0;
+
+function createRaymarcherCode( def ) {
+	var w = 'uniform ';
+	var code = shaderHeader
+		+ [ w+'mat3 u0;' ,
+		    w+'sampler2D u1;' ,
+		    w+'!3 u2,u3;' ,
+		    w+'float u4[10];'
+		  ].join('\n');
+	var u = 5;
+	for ( var i in def[15] ) {
+		code += w+'!3 u' + u++ + ';'+w+'float u' + u++ + ', u' + u++ + ';';
+	}
+	code += [
+		"const !2 c=!2(1.,-1.)*"+def[5]+";" ,
+		"float p,z,w,u,o,zy,q,x,a,zz;" ,
+		"!2 e,h;" ,
+		"!3 l=!3(zx,1.),m,r,s=u2,yx=!3(1.),n=!3(.0),b,v,xxx,xy,d,xx,xz,y;" ,
+		"!4 f;" ,
+
+		"float g(float x)" ,
+		"{" ,
+			"return fract(sin(x)*43758.5453);" ,
+		"}" ,
+
+		"float yy(!3 x)" ,
+		"{" ,
+			"m=floor(x),y=fract(x)," ,
+			"y*=y*(3.-2.*y)," ,
+			"z=m.x+m.y*57.+m.z*113.;" ,
+			"return mix(mix(mix(g(z),g(z+1.),y.x)," ,
+					"mix(g(z+57.),g(z+58.),y.x),y.y)," ,
+				"mix(mix(g(z+113.),g(z+114.),y.x)," ,
+					"mix(g(z+170.),g(z+171.),y.x),y.y),y.z);" ,
+		"}" ,
+
+		"float yyx(!2 x,float a)" ,
+		"{" ,
+			"e=pow(abs(x),!2(a));" ,
+			"return pow(e.x+e.y,1./a);" ,
+		"}" ,
+
+		"mat2 t(float x)" ,
+		"{" ,
+			"e=!2(cos(x),sin(x));" ,
+			"return mat2(-e.x,e.y,e.y,e.x);" ,
+		"}" ,
+
+		"float yz(!3 x)" ,
+		"{" ,
+			"return length(mod(x.xy,!2(15.))-!2(7.5))-.5+.05*sin(x.z*9.42477);" ,
+		"}" ,
+
+		"!2 k(!3 x,float a) {"
+	].join("\n");
+	code += def[14] + '}';
+	code += [
+			"void main()" ,
+			"{" ,
+				"l.y+=mod(u4[4],1.)*2.2;" ,
+				"if(l.y>1.){" ,
+					"if(l.y < 1.2)discard;" ,
+					"l.y-=2.2;" ,
+				"}" ,
+				"l.x*=1.6," ,
+				"r=normalize(l*u0);" ,
+
+				"for(int j=0;j<2;j++){" ,
+					"v=r,xxx=s,xy=!3(.0)," ,
+					"x=.0,a=" + def[1] + ';' ,
+					"for(int i=0;i<" + def[4] + ";i++){" ,
+						"h=k(s+r*x,x);" ,
+						"if(h.x< a||i>" + def[4] + "/(j+1)||x>" + def[0] + ".)break;" ,
+						"x+=h.x*" + def[3] + ",a*=" + shaderFloat( def[2] ) + ";" ,
+					"}" ,
+					"h.x=x;",
+
+					"if(x<"+ def[0]+ ".){" ,
+						"d=s+r*x," ,
+						"f=!4(" ,
+							"k(d+c.xyy,x).x," ,
+							"k(d+c.yyx,x).x," ,
+							"k(d+c.yxy,x).x," ,
+							"k(d+c.xxx,x).x" ,
+						")," ,
+						"xx=normalize(f.x*c.xyy+f.y*c.yyx+f.z*c.yxy+f.w*c.xxx)," ,
+						"a=.0," ,
+						"p=" + def[12] + ";" ,
+						"for(int i=1;i<="+def[10]+";i++)" ,
+							"x=(float(i)/"+def[10]+".)*"+ shaderFloat( def[11] ) + "," ,
+							"m=d+xx*x," ,
+							"a+=p*(x-k(m,distance(m,s)).x)," ,
+							"p*=.5;" ,
+						"q=max(.1,1.-clamp(pow(a,1.),.0,1.));" ,
+		].join('\n');
+
+	for(var i in def[13])
+		w=materials[def[13][i]],code+=(i>0?'else ':'')+'if(h.y==' + i + '.)xz='+(w[4]?('mix(!3('+shaderVec(w[0])+'),!3('+shaderVec(w[5])+'),yy(d*'+shaderFloat(def[6]*w[4])+'))'):('!3('+shaderVec(w[0])+')'))+',w='+shaderFloat(w[1])+',u='+w[2]+',o='+w[3]+';';
+
+	code += [
+						"v=reflect(r,xx)," ,
+						"z="+def[9]+"*h.x," ,
+						"z=clamp(exp(-z*z*z*1.442695),.0,1.)," ,
+						"x=clamp((1.+dot(normalize(v+r),r)),.0,1.),a=x*x," ,
+						"zz=o+(1.-o)*x*a*a*(u*.9+.1)," ,
+						"y=mix(!3(1.),xz/dot(!3(.299,.587,.114),xz),w)," ,
+						"m=!3(.0)," ,
+						"zy=exp2(4.+6.*u)," ,
+		].join('\n');
+
+	u = 5;
+	for ( var l in def[15] ) {
+		var b = def[15][l];
+		code += [
+			"p=length(b=u" + u + "-d)," ,
+			"b/=p," ,
+			"p=max(1.,p-u" + (u+2) + ")*" + b[0] + "," ,
+			"p=1./max(1.,p*p)," ,
+			"m+=mix((1.-w)*xz*q,y*pow(max(dot(reflect(r,xx),b),.0),zy)*(zy+2.)/8.,zz)*p*max(dot(b,xx),.0)*!3(u" + (u+1) + "),"
+		].join('\n');
+		u+=3;
+	}
+	code += [
+						"xy=yx*z*normalize(y)*o*(u*.9+.1)*zz," ,
+						"m=mix(!3(" + shaderFloat(def[8]) + "),m,z)," ,
+						"xxx+=normalize(v)*" + def[7] + ";" ,
+					"}else" ,
+						"m=!3(" + shaderFloat(def[8]) + ');'
+	].join('\n');
+
+	u=5;
+	for ( var l in def[15] ) {
+		var b = def[15][l];
+		var h = b[1];
+		if ( h ) {
+			code += [
+					"b=s-u" + u + "," ,
+					"p=dot(r,r),a=2.*dot(b,r)," ,
+					"x=a*a-4.*p*(dot(b,b)-" + (h*h) + ")," ,
+					"e=x<.0?!2(-1.):(x=sqrt(x),-.5*!2(a+x,a-x)/p)," ,
+					"e=!2(min(e.x,e.y),max(e.x,e.y));" ,
+					"if(e.x>.0&&e.y<h.x)" ,
+						"m+=u" + (u+2) + "*!3(u" + (u+1) + ")*pow((e.y-e.x)/" + shaderFloat(h*2) + ",64.);"
+			].join( "\n" );
+		}
+		u+=3;
+	}
+
+	code += [
+					"n+=m*yx;" ,
+					"if(all(lessThan(xy,!3(.01))))break;" ,
+					"yx=xy," ,
+					"s=xxx," ,
+					"r=normalize(v);" ,
+				"}" ,
+
+				"h=!2(zx.x,l.y)*.5+.5," ,
+				"h.y=(1.-h.y-u4[5])/u4[7]," ,
+				"f=texture2D(u1,h)," ,
+				"n=max(!3(.0),mix(mix(mix(n,(n.x==n.y&&n.x==n.z)?n:!3(dot(n,!3(.299,.587,.114))),u4[1]),!3(u4[3]),smoothstep(.05,.95,u4[2])),f.rgb*u3,f.a*u4[6])-!3(.004)),",
+
+				"x=(l.x+1.)*(l.y+1.)*(u4[0]*10.),",
+				"gl_FragColor=!4((1.-(smoothstep(.98,1.,yy(l*8.+u4[0]*20.))+smoothstep(.95,1.,yy(l*1.5+u4[0]*10.))))*smoothstep(1.042+.008*cos(u4[0]*40.),.8,yyx(zx,8.))*(1.-(mod((mod(x,13.)+1.)*(mod(x,47.)+1.),.01))*8.)*((.95+.05*cos(u4[0]*41.))*(n*(6.2*n+.5))/(n*(6.2*n+!3(1.7))+!3(.06))+!3(smoothstep(.98,1.,yy(l*8.-u4[0]*40.)))),1.);",
+			"}" ,
+	].join('\n');
+	return code;
+}
+
+var cmU=vomNew(3),
+    cmV=vomNew(3),
+    cmW=vomNew(3),
+    cd=vomNew(3),
+    cu=vomNew(3),
+    cm=vomNew(9);
+
+
+// Main
+
+function resize() {
+	var vw=window.innerWidth,vh=window.innerHeight;
+	var cw=Math.floor(vh*1.6),ch=Math.floor(vw*.625);
+	if(cw>vw){
+		C1.width=canvasWidth=vw;
+		C1.height=canvasHeight=ch;
+	}else{
+		C1.width=canvasWidth=cw;
+		C1.height=canvasHeight=vh;
+	}
+	C2.style.width=C2.width=canvasWidth;
+	c2height=C2.style.height=C2.height=Math.max(canvasHeight/8,100);
+	c2rHeight=c2height/canvasHeight;
+	twoDCtx.shadowColor = "#ccc";
+	twoDCtx.font = "normal small-caps bold " + Math.floor(c2height/2) + "px monospace";
+	twoDCtx.fillStyle = "#111";
+	twoDCtx.strokeStyle = "#ddd";
+	C1.style.left=Math.floor((vw-canvasWidth)*.5);
+	C1.style.top=Math.floor((vh-canvasHeight)*.5);
+	glCtx.viewport(0,0,canvasWidth,canvasHeight);
+}
+
+// FIXME: re-enable! document.body.style.cursor = 'none';
+document.body.style.background = 'black';
+document.body.innerHTML = '<canvas id=C1 style=position:fixed></canvas><canvas id=C2 style=display:none>';
+glCtx=C1.getContext('webgl');
+twoDCtx = C2.getContext('2d');
+(window.onresize=resize)();
+var shaders = [
+	[ glCtx.VERTEX_SHADER , shaderHeader + "attribute !2 i;void main(){gl_Position=!4(i,.0,1.),zx=i;}"
+	]
+];
+var programs = {};
+var misc = vomNew(10) , camPos = vomNew(3),lookAt=vomNew(3),camUp=vomNew(3),toNearPlane=0,textColour=vomNew(3) , lights= [[vomNew(3),0,0],[vomNew(3),0,0],[vomNew(3),0,0]];
+var sn = 1;
+for ( var i in raymarchers ) {
+	var rm = raymarchers[i];
+	shaders[sn] = [glCtx.FRAGMENT_SHADER,createRaymarcherCode(rm)];
+	programs[i] = [ 5+rm[15].length*3 , 0 , sn++ ];
+}
+for ( var i in shaders ) {
+	var def = shaders[i];
+	glCtx.shaderSource( i= shaders[i] = glCtx.createShader( def[0] ) , def[1].replace(/!/g,'vec') );
+	glCtx.compileShader( i );
+	if (!glCtx.getShaderParameter(i, glCtx.COMPILE_STATUS)) {
+		def[1] = def[1].split( /\n/ );
+		for ( var k in def[1] ) {
+			var j = parseInt(k)+1;
+			def[1][k] = j + ": " + def[1][k];
+		}
+		throw "SHADER ERROR\n" + glCtx.getShaderInfoLog(i) + "\n" + def[1].join('\n');
+	}
+}
+for ( var name in programs ) {
+	var p = glCtx.createProgram( );
+	var d = programs[name];
+	var ul = d.shift();
+	while( d.length ) {
+		glCtx.attachShader( p , shaders[ d.shift() ] );
+	}
+	glCtx.linkProgram( p );
+	var nul = [];
+	while ( ul-- ) {
+		nul[ul] = glCtx.getUniformLocation( p , 'u' + ul );
+	}
+	programs[name] = [p,nul];
+}
+vtxBuffer = glCtx.createBuffer( );
+glCtx.bindBuffer( glCtx.ARRAY_BUFFER , glCtx.createBuffer( ) );
+glCtx.bufferData( glCtx.ARRAY_BUFFER , vomNew([1,4,1,-1,-4,-1]) , glCtx.STATIC_DRAW );
+glCtx.clearColor(0,0,0,1);
+
+textTexture = glCtx.createTexture( );
+glCtx.bindTexture( glCtx.TEXTURE_2D , textTexture );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_S, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_T, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MIN_FILTER, glCtx.NEAREST );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MAG_FILTER, glCtx.NEAREST );
+glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+
+timeStart = previousFrame = 0;
+FRAME_TIME = 100/3;
+
+paused = 0;
+document.body.onkeypress = function(e) {
+	if ( e.keyCode == 32 ) {
+		var now = Date.now();
+		if ( paused ) {
+			timeStart += now - paused;
+			paused = 0;
+			requestAnimationFrame(draw);
+			A.play( );
+		} else {
+			paused = now;
+			A.pause( );
+		}
+	}
+};
+
+var demoTime, rStepTime,stepTime;
+mainfunc = function(){setTimeout(function(){
+requestAnimationFrame(draw=function(time){
+	if ( ! paused ) {
+		requestAnimationFrame(draw);
+	}
+	if ( timeStart == 0 ) {
+		A.currentTime = 0;
+		A.play( );
+		timeStart = time;
+		previousFrame = timeStart - FRAME_TIME;
+	}
+	var delta = time - previousFrame;
+	demoTime = .001*(time - timeStart);
+	if ( delta < FRAME_TIME ) {
+		return;
+	}
+	previousFrame = time - ( delta % FRAME_TIME );
+
+	var ds = direction[t];
+	while ( ds && ds[7] < demoTime ) {
+		ds=direction[++t];
+	}
+	if ( ! ds ) {
+		A.pause( );
+		return;
+	}
+	misc[0] = demoTime;
+	misc[7] = c2rHeight;
+	stepTime = demoTime - ds[5];
+	rStepTime = stepTime / ds[6];
+	if ( ds[4] ) {
+		twoDCtx.clearRect( 0 , 0 , canvasWidth , 100 );
+		ds[4]();
+		glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+	}
+
+	ds[2]();
+	vecNorm(cmW,vecSub(cmW,lookAt,camPos));
+	vecNorm(cmU,vecCross(cmU,camUp,cmW));
+	vecNorm(cmV,vecCross(cmV,cmW,cmU));
+	vecScale(cmW,cmW,toNearPlane);
+	vecs2Mat3(cm,cmU,cmV,cmW);
+
+	for ( var i in ds[3] ) {
+		ds[3][i](lights[ i ]);
+	}
+
+	var p = programs[ds[1]];
+	glCtx.useProgram( p[ 0 ] );
+	glCtx.enableVertexAttribArray( 0 );
+	glCtx.vertexAttribPointer( 0 , 2 , glCtx.FLOAT , false , 8 , 0 );
+	p = p[1];
+
+	var u = 0;
+	glCtx.uniformMatrix3fv( p[u++] , false , cm );
+	glCtx.uniform1i( p[u++] , 0 );
+	glCtx.uniform3fv( p[u++] , camPos );
+	glCtx.uniform3fv( p[u++] , textColour );
+	glCtx.uniform1fv( p[u++] , misc );
+	for ( var i in ds[3] ) {
+		glCtx.uniform3fv( p[u++] , lights[ i ][0] );
+		glCtx.uniform1f( p[u++] , lights[ i ][1] );
+		glCtx.uniform1f( p[u++] , lights[ i ][2] );
+	}
+	glCtx.drawArrays( 4 , 0 , 3 );
+})
+},500)};
+
+if ( USE_SYNTH ) {
+	synthGen = setInterval(function(){
+		var i,j,a,n,b,k,t,e,c,d=new Int32Array(mNumWords),f=song[mCurrentCol],g,h,l,m,o=[],q,r,s,u,v,p;
+		for(g=h=m=p=0;p<=26;p++)for(b=f[1][p],a=0;a<36;a++){((e=b?f[2][b-1][1][a]:0)?((f[0][e-1]=f[2][b-1][1][a+36]||0),e<14?(o=[]):0):0),c=(p*36+a)*5513;for(j=0;j<4;j++)if(n=b?f[2][b-1][0][a+j*36]:0){if(!o[n])for(q=f[0][10],r=f[0][11],s=f[0][12],t=getnotefreq(n+f[0][2]-128),l=getnotefreq(n+f[0][6]-128)*(1+.0008*f[0][7]),u=v=0,q*=q*4,r*=r*4,s*=s*4,o[n]=new Int32Array(q+r+s),k=0;k<q+r+s;k++)e=k<q?(k/q):(1-(k<q+r?0:((k-q-r)/s))),o[n][k]=(80*(mOscillators[f[0][0]](u+=t*(f[0][3]?(e*e):1))*f[0][1]+mOscillators[f[0][4]](v+=l*(f[0][8]?(e*e):1))*f[0][5]+randAround(0,1)*f[0][9])*e)|0;for(k=0,i=c*2;k<o[n].length;k++,i+=2)d[i]+=o[n][k]}q=f[0][20]*1e-5,r=f[0][24]/255,s=f[0][25]*5513;for(j=0;j<5513;j++)(((n=e=d[k=(c+j)*2])||m)?(t=1.5*Math.sin(f[0][18]*.00307999186353015873*(f[0][16]?(mOscillators[f[0][13]](Math.pow(2,f[0][15]-9)*k/5513)*f[0][14]/512+.5):1)),g+=t*h,l=(1-f[0][19]/255)*(e-h)-g,h+=t*l,e=f[0][17]==3?h:f[0][17]==1?l:g,q?(e*=q,e=(e<1?e>-1?mOscillators[0](e*.25):-1:1)/q):0,e*=f[0][21]/32,m=e*e>1e-5,t=Math.sin(6.283184*Math.pow(2,f[0][23]-9)*k/5513)*f[0][22]/512+.5,n=e*(1-t),e*=t):0),(k>=s?(n+=d[k-s+1]*r,e+=d[k-s]*r):0),mMixBuf[k]+=(d[k]=n|0),mMixBuf[k+1]+=(d[k+1]=e|0)}
+		if(++mCurrentCol==8)for(clearInterval(synthGen),s=(f=String.fromCharCode).apply(String,[82,73,70,70,168,16,71,1,87,65,86,69,102,109,116,32,16,0,0,0,1,0,2,0,68,172,0,0,16,177,2,0,4,0,16,0,100,97,116,97,132,16,71,1]),i=0;i<mNumWords||(((A=document.createElement("audio")).src='data:audio/wav;base64,'+btoa(s),A.oncanplaythrough=mainfunc)&&0);i++)e=mMixBuf[i],e=e<-32767?-32767:(e>32767?32767:e),s+=f(e&255,(e>>8)&255)
+	}, 0);
+} else {
+	A = document.createElement("audio");
+	A.oncanplaythrough=mainfunc;
+	A.src= 'music.ogg';
+}
diff --git a/201410_-_Sine_City/sine-city-packing-5-misc.html b/201410_-_Sine_City/sine-city-packing-5-misc.html
new file mode 100644
index 0000000..fc0a717
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-5-misc.html
@@ -0,0 +1,3 @@
+<body>
+<script language="javascript" src="sine-city-packing-5-misc.js"></script>
+
diff --git a/201410_-_Sine_City/sine-city-packing-5-misc.js b/201410_-_Sine_City/sine-city-packing-5-misc.js
new file mode 100644
index 0000000..1cc5f01
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-5-misc.js
@@ -0,0 +1,489 @@
+var USE_SYNTH = 0;
+
+with(Math)S=sin,C=cos,M=max,N=min,P=pow;
+
+
+f = function(a,b,c){return eval('(function('+a+'){'+b+(b?';':'')+(c?('return '+c):'')+'})')},
+
+getnotefreq=f('a','','.003959503758*P(2,(a-128)/12)'),
+mOscillators=[
+	f('a','','S(a*6.283184)'),
+	f('a','','(a%1)<.5?1:-1'),
+	f('a','','2*(a%1)-1'),
+	f('a,b','b=(a%1)*4','(b<2)?(b-1):(3-b)')
+],
+
+// Vector stuff
+vecOp=f('a','','f(\'a,b,c\',\'for(var i=a.length;--i>=0;)\'+a,\'a\')'),
+vomNew=f('a','','new Float32Array(a)'),
+vecNorm=f('a,b,c','c=Math.sqrt(b[0]*b[0]+b[1]*b[1]+b[2]*b[2])','c?vecScale(a,b,1/c):vecCopy(a,b)'),
+vecCross=f('a,b,c','','vecSet(a,b[1]*c[2]-b[2]*c[1],b[2]*c[0]-b[0]*c[2],b[0]*c[1]-b[1]*c[0])'),
+vecSet=vecOp('a[i]=arguments[i+1]'),
+vecCopy=vecOp('a[i]=b[i]'),
+vecSub=vecOp('a[i]=b[i]-c[i]'),
+vecScale=vecOp('a[i]=b[i]*c'),
+
+
+// Shaders
+shaderHeader='precision highp %;varying !2 zx;',
+shaderFloat=f('a','','a+(a==(a|0)?\'.\':\'\')'),
+shaderVec=f('a','','a.map(shaderFloat).join(\',\')');
+
+
+// Raymarchers
+
+materials = [[[.05],.7,.02,.01],[[.2],.7,.9,.01,5,[.1]],[[1],.5,.4,.02],[[3,0,0],.3,.1,.6,6,[.6,0,0]],[[0,2,0],.9,.5,.4,15,[0,.2,0]],[[3,1.5,0],.95,.6,.9,.3,[.3,.6,0]],[[.1],0,.04,.002,3,[3]],[[0,1.5,2],.9,.3,.4]];
+raymarchers = [[100,.025,1,.7,64,.0005,.5,.3,.4,.015,4,2,.75,[0,1,2,3],'y=x+.1*(sin(x.zxy*.17+u4[0]*.5)+sin(x.yzx*.7+u4[0]*1.5))*8.5*(1.+cos(sin(x.z*.1)+x.z*.3)),z=14.-length(y.xy),w=x.x==.0?1.570795*(x.y>.0?1.:-1.):atan(x.y,x.x),q=8.35-u4[8]*1.35,y=!3(9.*(mod(w+x.z*.02,.628)-.314),length(x.xy)-9.,mod(x.z,12.56)-6.28),u=min(length(y.xy)-.25+.1*cos(x.z*8.+u4[0]*.1),length(y.yz)-.5),y=!3(q*(mod(w+x.z*.02,1.256636)-.628318),y.y+9.-q,mod(x.z,62.8318)-31.4159),o=step(u,z)+1.,z=min(u,z),u=length(y)-1.3;if(u<z)z=u,o=3.;y.y+=q-9.,u=yyx(y.yz,8.)-2.;if(u<z)z=u,o=.0;return !2(z,o);',[[.25,0],[.5,.5]]],[6,.00025,1.08,.7,100,.000008,10,.03,2.1,.2,6,.4,5.1,[0,2,5],'z=1.,y=x;for(int i=0;i<7;i++)x=2.*clamp(x,-!3(.58,.9,1.1),!3(.58,.9,1.1))-x,w=max((1.3+u4[9]*.1*cos(u4[0]*.5))/dot(x,x),1.),x*=w,z*=w;w=length(x.xy),e=!2(w-3.,-w*x.z/length(x)-2.*log(1.+.01*a))/abs(z),w=max(e.x,e.y),o=step(e.y,e.x),y+=!3(.1,.3,-.4)*u0-u2+.25*sin(x*1.),e.x=length(y)-.1*u4[8];if(e.x<w)w=e.x,o=2.;return !2(w,o);',[[.05]]],[100,.000025,1,.75,80,.00005,.5,.3,3,.01,4,.75,4.75,[6,0,4],'x.xy*=t(a*.009),w=min(min(yz(x.xzy),yz(x)),yz(x.yzx)),y=mod(x,!3(15.))-!3(7.5),o=step(z=max(length(max(abs(y)-!3(2.5),!3(.0)))-.25,3.5-length(y)),w),w=min(w,z),z=length(y+.1*sin(y*5.5+u4[0]))-2.;if(z<w)w=z,o=2.;return !2(w,o);',[[.05]]],[20,.0005,1,.6,128,.0001,.5,.002,.01,.08,4,.5,1.75,[2,7],'y=x,y.xz=mod(x.xz,8.)-4.,y.yz*=t(u4[8]+.1*a),y.xy*=t(u4[8]*.5+.2*a),y.y*=.9+.1*sin(u4[8]*5.),w=max(length(y)-3.,-min(length(y)-2.8,max(mod(y.y,.8)-.4,-mod(y.y+.4,.8)+.4))),z=x.y+1.+sin(x.x*4.+u4[8]*2.)*sin(x.z+u4[8])*.1,o=clamp(.5+.5*(z-w)/1.,.0,1.),w=mix(z,w,o)-1.*o*(1.-o),y=x,y.xz=mod(y.xz,8.)-4.,y/=1.25+.25*sin(u4[8]*5.),y.xy*=t(u4[8]*5.),y.yz*=t(u4[8]*2.5),z=max(length(y)-1.,.04-length(max(abs(mod(y,.5)-.25)-!3(.15),!3(.0))));return !2(min(w,z),step(z,w));',[[.02],[.05,.5],[.05,.5]]]];
+
+tunMul=1,
+R=f('a,b','','a-b+Math.random()*b*2'),
+lightFunc=f('a,b','','f(\'a\',\'vecCopy(a[0],camPos),a[1]=\'+a+\',a[2]=\'+b)'),
+
+tun1CamCommon=f('a','vecSet(camPos,-6,0,a=demoTime*6),vecSet(lookAt,misc[1]=1,misc[8]=0,a),vecSet(camUp,0,1,0)'),
+desyncFunc=f('a','','f(\'\',\'misc[4]=(\'+(a>0?a:\'\')+\'-stepTime*\'+a+\'/direction[t][6])*R(.875,.125)\')'),
+balls1CamFunc=f('a,b,c,d','c=desyncFunc(c),d=f(\'a,b,c,d\',\'vecSet(camPos,misc[2]=misc[8]=0,4,d=demoTime*3),vecSet(lookAt,a,0,d+b),vecSet(camUp,0,0,1),c()\')','function(){d(a,b,c)}'),
+balls2CamCommon=f('a','a=demoTime*5,vecSet(camPos,C(demoTime)*12,8,S(demoTime)*12+a),vecSet(lookAt,1,0,a),vecSet(camUp,0,1,0),toNearPlane=2.5,misc[8]=demoTime-direction[43][5]'),
+balls2LightFunc=f('a','','f(\'a\',\'vecSet(a[0],\'+a+\'*C(demoTime*2)*5,3,\'+a+\'*S(demoTime*2)*5+demoTime*30),a[1]=1,a[2]=4\')'),
+fract1CamCommon=f('','vecSet(camPos,4,2.5+.025*demoTime,6.7),vecSet(lookAt,misc[8]=misc[9]=0,2.5-.05*demoTime,6.7),vecSet(camUp,0,0,1),toNearPlane=3'),
+fract1CamFunc=f('a','a=desyncFunc(a)','function(){fract1CamCommon(),a()}'),
+fract2CamCommon=f('a,b','vecSet(camPos,5*S(b=demoTime*.2),9*C(demoTime*.41),7.8),vecSet(lookAt,C(b),S(demoTime*.33),camPos[2]-2),vecSet(camUp,0,0,misc[9]=1),misc[8]=a,toNearPlane=3'),
+
+drawText=f('a,b,c','with(twoDCtx)shadowBlur=c2height/5,fillText(a,b,c=c2height/2),shadowBlur=0,strokeText(a,b,c)'),
+titleParts=['TheT(ourist)','presents','Sine City'],
+titleText=f('a,b,c,d,e,f','drawText(titleParts[a],canvasWidth/15),misc[5]=1-c2rHeight+R(0,b),misc[6]=c,vecSet(textColour,d,e,f)'),
+greetingsText=f('','drawText(\'Greetings to ... Mog, Sycop, Tim & Wullon ... Adinpsz ... Alcatraz ... ASD ... Bits\\\'n\\\'Bites ... Brain Control ... Cocoon ... Conspiracy ... Ctrl+Alt+Test ... Fairlight ... Farbrausch ... Kewlers ... LNX ... Loonies ... Mercury ... Popsy Team ... Razor 1911 ... RGBA ... 7th Cube ... Still ... TPOLM ... TRBL ... Umlaut Design ... X-Men ... Youth Uprising ... Everyone here at DemoJS 2014!\',canvasWidth*(1-(demoTime-direction[34][5])/2)),misc[5]=1-c2rHeight+R(.01,.01),vecSet(textColour,misc[6]=1,1,1)'),
+squaresCam=f('a,b','a=demoTime-direction[25][5],vecSet(camPos,b=a*10-80,0,0),vecSet(lookAt,b+C(a*.5)*80,S(a*.25)*40,100),vecSet(camUp,0,toNearPlane=2.5,0)'),
+squaresCam2=f('a,b','a=demoTime-direction[a][5],vecSet(camPos,0,0,b=a*20-80),vecSet(lookAt,C(a*.5)*80,S(a*.25)*40,100+b),vecSet(camUp,0,1,0),misc[4]=R(a=.0125,a)'),
+tunnelLight=f('a','vecSub(a[0],camPos,vecNorm(a[0],lookAt)),a[0][1]-=.5,a[1]=3,a[2]=30'),
+tunnelCam=f('a','a=(demoTime-direction[a][5])*30*tunMul,vecSet(camPos,1.1*C(a*.1),S(a*.02),a),a+=5,vecSet(lookAt,-S(a*.05),-.7*C(a*.033),a),vecSet(camUp,0,toNearPlane=2,0)'),
+tunnelLightBall=f('a','','f(\'a,b\',\'b=demoTime-direction[\'+a+\'][5],vecSet(a[0],4*S(b*.5)*C(b*.7),3*C(b*1.5),b*30*tunMul+14+16*S(b*3.3)*C(b*.77)),a[1]=1,a[2]=2\')'),
+
+// direction    0<->rows / 1<->rm / 2<->setGlobals / 3<->lights / 4<->updateText / 5<->startTime / 6<->time / 7<->endTime
+direction = [
+	[
+		36 ,
+		0 ,
+		f('','tun1CamCommon(misc[2]=1-rStepTime*rStepTime*rStepTime,toNearPlane=5)') ,
+		a=[lightFunc(3,20)]
+	] , [
+		18 ,
+		0 ,
+		f('','tun1CamCommon(misc[2]=0,toNearPlane=5-2.25*rStepTime)') ,
+		a
+	] , [
+		36 ,
+		0 ,
+		f('','tun1CamCommon(misc[2]=rStepTime,toNearPlane=2.75-2.25*rStepTime)') ,
+		a
+	] , [
+		18 ,
+		3 ,
+		f('a','vecSet(camPos,0,4,a=demoTime*3),vecSet(lookAt,4,0,a),vecSet(camUp,0,0,1),misc[2]=1-rStepTime*rStepTime*rStepTime,toNearPlane=2.5') ,
+		[ lightFunc(.75,8) ]
+	] , [
+		22 ,
+		3 ,
+		balls1CamFunc(4,0,0) ,
+		a=[lightFunc(1,8)]
+	] , [
+		22 ,
+		3 ,
+		balls1CamFunc(2,-2,0) ,
+		a
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 6 , 0 , -.5 ) ,
+		b=[lightFunc(.5,4)]
+	] , [
+		9 ,
+		3 ,
+		balls1CamFunc( 6 , 0 , .5 ) ,
+		b
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , -.2 ) ,
+		a
+	] , [
+		9 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , .2 ) ,
+		a
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 2 , 5 , -.7 ) ,
+		a=[ lightFunc(1,2) ]
+	] , [
+		7 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , .7 ) ,
+		a
+	] , [
+		9 ,
+		3 ,
+		f('a','vecSet(camPos,0,4+rStepTime*2,a=demoTime*3),vecSet(lookAt,2,0,a+2),vecSet(camUp,0,0,misc[3]=1),misc[2]=rStepTime') ,
+		a
+	] , [
+		21 ,
+		1 ,
+		f('','fract1CamCommon(misc[2]=1-rStepTime*rStepTime*rStepTime,misc[3]=1)'),
+		a=[f('a','vecCopy(a[0],camPos),a[0][2]+=2,a[1]=1,a[2]=3')]
+	] , [
+		14 ,
+		1 ,
+		fract1CamFunc(0) ,
+		a
+	] , [
+		3 ,
+		1 ,
+		fract1CamFunc(-.4) ,
+		a
+	] , [
+		9 ,
+		1 ,
+		fract1CamFunc(.4) ,
+		a
+	] , [
+		3 ,
+		1 ,
+		fract1CamFunc(-.2) ,
+		a
+	] , [
+		9 ,
+		1 ,
+		fract1CamFunc(.2) ,
+		a
+	] , [
+		12 ,
+		1 ,
+		f('','fract1CamCommon(misc[4]=(-(6*rStepTime)%1)*R(.875,.125))'),
+		a
+	] , [
+		22 ,
+		1 ,
+		f('','fract1CamCommon(misc[4]=((30*rStepTime)%1)*R(.925,.075),misc[2]=rStepTime,misc[3]=.4),toNearPlane=3-2.5*M(1,2*rStepTime)'),
+		a
+	] , [
+		3 ,
+		1 ,
+		b=f('','fract1CamCommon(misc[4]=0,misc[2]=1)'),
+		a
+	] , [
+		12 ,
+		1 ,
+		b ,
+		a,
+		f('','titleText(0,.08,1,1,1,1)')
+	] , [
+		12 ,
+		1 ,
+		b ,
+		a,
+		f('','titleText(0,.08,1-rStepTime,1,1,1)')
+	] , [
+		12 ,
+		1 ,
+		b ,
+		a,
+		f('','titleText(1,.08,1-rStepTime,1,1,1)')
+	] , [
+		20 ,
+		2 ,
+		f('','squaresCam(misc[2]=1-rStepTime)') ,
+		b=[lightFunc(1,30)],
+		f('','titleText(2,.04,rStepTime,1,1,1)')
+	] , [
+		52 ,
+		2 ,
+		f('','squaresCam(misc[2]=0)'),
+		b,
+		f('','titleText(2,.04,1,1,1,1)')
+	] , [
+		12 ,
+		2 ,
+		f('','squaresCam(misc[2]=1-M(0,rStepTime*2),misc[3]=1)'),
+		b,
+		f('','titleText(2,.04,1,1-rStepTime,1-rStepTime/2,1-rStepTime)')
+	] , [
+		12 ,
+		2 ,
+		f('a','squaresCam(misc[1]=1-rStepTime/2,misc[4]=(1-rStepTime)*.7+R(a=.0125,a))') ,
+		b,
+		f('','titleText(2,.04,1,0,.5,0)')
+	] , [
+		9 ,
+		2 ,
+		f('','squaresCam2(29,misc[1]=(1-rStepTime)/2,misc[2]=1-M(0,rStepTime*1.5)),misc[4]+=misc[1]*.6'),
+		b,
+		f('','titleText(2,.04,1-rStepTime,0,.5,0)')
+	] , [
+		69 ,
+		2 ,
+		f('','squaresCam2(29,misc[1]=0)') ,
+		b
+	] , [
+		11 ,
+		2 ,
+		f('','squaresCam2(29,misc[2]=rStepTime,misc[3]=.2)'),
+		b
+	] , [
+		11 ,
+		0 ,
+		f('','tunnelCam(32,misc[2]=1-rStepTime)'),
+		b=[ tunnelLight ]
+	] , [
+		17 ,
+		0 ,
+		f('','tunnelCam(32,misc[2]=0,misc[4]=(1-rStepTime)*1.2*R(1,.02))') ,
+		b
+	] , [
+		18 ,
+		0 ,
+		f('','tunnelCam(32,misc[4]=0,misc[8]=rStepTime)') ,
+		b ,
+		greetingsText
+	] , [
+		36 ,
+		0 ,
+		f('','tunnelCam(32,misc[2]=1-N(misc[8]=1,4*rStepTime))'),
+		b = [ tunnelLight , tunnelLightBall(32) ],
+		greetingsText
+	] , [
+		33 ,
+		0 ,
+		f('','tunnelCam(32,misc[2]=rStepTime,misc[3]=.7,misc[4]=-((4*rStepTime)%1)*R(1,.05))'),
+		b ,
+		greetingsText
+	] , [
+		9 ,
+		1 ,
+		f('','fract2CamCommon(misc[4]=0,misc[2]=rStepTime,misc[3]=1)'),
+		a,
+		greetingsText
+	] , [
+		20 ,
+		1 ,
+		f('','fract2CamCommon(rStepTime,misc[2]=0)'),
+		a,
+		greetingsText
+	] , [
+		31 ,
+		1 ,
+		f('','fract2CamCommon(1,misc[2]=1-N(1,5*rStepTime))'),
+		a,
+		greetingsText
+	] , [
+		5 ,
+		1 ,
+		f('','fract2CamCommon(1,misc[2]=1-rStepTime)'),
+		a,
+		greetingsText
+	] , [
+		18 ,
+		1 ,
+		f('','fract2CamCommon(1,misc[2]=1-N(1,5*rStepTime),misc[4]=M(0,1.6*rStepTime-.8)*R(1,.05))'),
+		a,
+		greetingsText
+	] , [
+		12 ,
+		1 ,
+		f('','fract2CamCommon(1,misc[2]=rStepTime,misc[4]=(1-rStepTime)*.8*R(1,.05),misc[3]=.1)'),
+		a,
+		greetingsText
+	] , [
+		22 ,
+		3 ,
+		f('','balls2CamCommon(misc[2]=1-rStepTime,misc[4]=0)'),
+		a = [ lightFunc(.6,30) , balls2LightFunc(1),balls2LightFunc(-1) ],
+		greetingsText
+	] , [
+		59 ,
+		3 ,
+		f('','balls2CamCommon(misc[2]=1-N(1,(12*rStepTime)%4),misc[3]=.8)'),
+		a,
+		greetingsText
+	] , [
+		8 ,
+		3 ,
+		f('','balls2CamCommon(misc[2]=rStepTime,misc[4]=R(0,misc[3]=.1))'),
+		a
+	] , [
+		7 ,
+		0 ,
+		f('','misc[tunMul=2]=1-rStepTime,tunnelCam(46,misc[4]=R(0,.1),misc[8]=1)'),
+		a = [ tunnelLight , tunnelLightBall(46) ]
+	] , [
+		22 ,
+		0 ,
+		f('','tunnelCam(46,misc[4]=R(0,.1))'),
+		a
+	] , [
+		10 ,
+		0 ,
+		f('','tunnelCam(46,misc[4]=R(0,.1+rStepTime*.4)+stepTime*4,misc[2]=rStepTime,misc[3]=1)'),
+		a
+	] , [
+		10 ,
+		2 ,
+		f('','squaresCam2(49,misc[2]=1-rStepTime),misc[4]=R(0,.5)+(demoTime-direction[48][5])*4'),
+		a=[ lightFunc(1,30) ]
+	] , [
+		40 ,
+		2 ,
+		f('','squaresCam2(49),misc[4]=R(0,.5)-(demoTime-direction[48][5])*6'),
+		a
+	] , [
+		40 ,
+		2 ,
+		f('','squaresCam2(49),misc[4]=R(misc[3]=0,.5)+(demoTime-direction[48][5])*8,misc[2]=rStepTime'),
+		a
+	] , [
+		68 ,
+		2 ,
+		f('','squaresCam2(49,misc[2]=1)'),
+		a
+	]
+];
+
+cmU=vomNew(3),
+    cmV=vomNew(3),
+    cmW=vomNew(3),
+    cd=vomNew(3),
+    cu=vomNew(3),
+    cm=vomNew(9);
+
+
+// Main
+
+with(document.body)style.background='black',innerHTML='<canvas id=C1 style=position:fixed;cursor:none></canvas><canvas id=C2 style=display:none>';
+twoDCtx = C2.getContext('2d');
+glCtx=C1.getContext('webgl');
+(window.onresize=f('a,b,c,d,e','with(twoDCtx)a=innerWidth,b=innerHeight,c=(b*1.6)|0,d=(a*.625)|0,glCtx.viewport(0,0,C2.style.width=C2.width=C1.width=canvasWidth=c>a?a:c,C1.height=e=c>a?d:b),c2height=C2.style.height=C2.height=M(e/8,100),c2rHeight=c2height/e,C1.style.left=((a-canvasWidth)/2)|0,C1.style.top=((b-e)/2)|0,shadowColor=\'#ccc\',font=\'normal small-caps bold \'+((c2height/2)|0)+\'px monospace\',fillStyle=\'#111\',strokeStyle=\'#ddd\''))();
+
+
+for(shaders=[[glCtx.VERTEX_SHADER,shaderHeader+'attribute !2 i;void main(){gl_Position=!4(i,.0,1.),zx=i;}']],programs=[],i=0;i<4;i++)shaders[i+1]=[glCtx.FRAGMENT_SHADER,f('a,b,c,d,e','b=\'uniform \',d=5,c=shaderHeader+b+\'mat3 u0;\'+b+\'sampler2D u1;\'+b+\'!3 u2,u3;\'+b+\'% u4[10];\';for(e in a[15])c+=b+\'!3 u\'+d+++\';\'+b+\'% u\'+d+++\', u\'+d+++\';\';c+=\'const !2 c=!2(1.,-1.)*\'+a[5]+\';% p,z,w,u,o,zy,q,x,a,zz;!2 e,h;!3 l=!3(zx,1.),m,r,s=u2,yx=!3(1.),n=!3(.0),b,v,xxx,xy,d,xx,xz,y;!4 f;% g(% x){return fract(sin(x)*43758.5453);}% yy(!3 x){m=floor(x),y=fract(x),y*=y*(3.-2.*y),z=m.x+m.y*57.+m.z*113.;return mix(mix(mix(g(z),g(z+1.),y.x),mix(g(z+57.),g(z+58.),y.x),y.y),mix(mix(g(z+113.),g(z+114.),y.x),mix(g(z+170.),g(z+171.),y.x),y.y),y.z);}% yyx(!2 x,% a){e=pow(abs(x),!2(a));return pow(e.x+e.y,1./a);}mat2 t(% x){e=!2(cos(x),sin(x));return mat2(-e.x,e.y,e.y,e.x);}% yz(!3 x){return length(mod(x.xy,!2(15.))-!2(7.5))-.5+.05*sin(x.z*9.42477);}!2 k(!3 x,% a){\'+a[14]+\'}void main(){l.y+=mod(u4[4],1.)*2.2;if(l.y>1.){if(l.y<1.2)discard;l.y-=2.2;}l.x*=1.6,r=normalize(l*u0);for(int j=0;j<2;j++){v=r,xxx=s,xy=!3(.0),x=.0,a=\'+a[1]+\';for(int i=0;i<\'+a[4]+\';i++){h=k(s+r*x,x);if(h.x<a||i>\'+a[4]+\'/(j+1)||x>\'+a[0]+\'.)break;x+=h.x*\'+a[3]+\',a*=\'+shaderFloat(a[2])+\';}h.x=x;if(x<\'+a[0]+\'.){d=s+r*x,f=!4(k(d+c.xyy,x).x,k(d+c.yyx,x).x,k(d+c.yxy,x).x,k(d+c.xxx,x).x),xx=normalize(f.x*c.xyy+f.y*c.yyx+f.z*c.yxy+f.w*c.xxx),a=.0,p=\'+a[12]+\';for(int i=1;i<=\'+a[10]+\';i++)x=(%(i)/\'+a[10]+\'.)*\'+shaderFloat(a[11])+\',m=d+xx*x,q=max(.1,1.-clamp(pow(a+=p*(x-k(m,distance(m,s)).x),1.),.0,1.)),p*=.5;\';for(e in d=a[13])b=materials[d[e]],c+=(e>0?\'else \':\'\')+\'if(h.y==\'+e+\'.)xz=\'+(b[4]?(\'mix(!3(\'+shaderVec(b[0])+\'),!3(\'+shaderVec(b[5])+\'),yy(d*\'+shaderFloat(a[6]*b[4])+\'))\'):(\'!3(\'+shaderVec(b[0])+\')\'))+\',w=\'+shaderFloat(b[1])+\',u=\'+b[2]+\',o=\'+b[3]+\';\';d=5,c+=\'v=reflect(r,xx),z=\'+a[9]+\'*h.x,z=clamp(exp(-z*z*z*1.442695),.0,1.),x=clamp((1.+dot(normalize(v+r),r)),.0,1.),a=x*x,zz=o+(1.-o)*x*a*a*(u*.9+.1),y=mix(!3(1.),xz/dot(!3(.299,.587,.114),xz),w),m=!3(.0),zy=exp2(4.+6.*u),\';for(e in b=a[15])c+=\'p=length(b=u\'+d+\'-d),b/=p,p=max(1.,p-u\'+(d+2)+\')*\'+b[e][0]+\',p=1./max(1.,p*p),m+=mix((1.-w)*xz*q,y*pow(max(dot(reflect(r,xx),b),.0),zy)*(zy+2.)/8.,zz)*p*max(dot(b,xx),.0)*!3(u\'+(d+1)+\'),\',d+=3;d=5,c+=\'xy=yx*z*normalize(y)*o*(u*.9+.1)*zz,m=mix(!3(\'+shaderFloat(a[8])+\'),m,z),xxx+=normalize(v)*\'+a[7]+\';}else m=!3(\'+shaderFloat(a[8])+\');\';for(e in b=a[15])(a=b[e][1])?c+=\'b=s-u\'+d+\',p=dot(r,r),a=2.*dot(b,r),x=a*a-4.*p*(dot(b,b)-\'+(a*a)+\'),e=x<.0?!2(-1.):(x=sqrt(x),-.5*!2(a+x,a-x)/p),e=!2(min(e.x,e.y),max(e.x,e.y));if(e.x>.0&&e.y<h.x)m+=u\'+(d+2)+\'*!3(u\'+(d+1)+\')*pow((e.y-e.x)/\'+shaderFloat(a*2)+\',64.);\':0,d+=3','c+=\'n+=m*yx;if(all(lessThan(xy,!3(.01))))break;yx=xy,s=xxx,r=normalize(v);}h=!2(zx.x,l.y)*.5+.5,h.y=(1.-h.y-u4[5])/u4[7],f=texture2D(u1,h),n=max(!3(.0),mix(mix(mix(n,(n.x==n.y&&n.x==n.z)?n:!3(dot(n,!3(.299,.587,.114))),u4[1]),!3(u4[3]),smoothstep(.05,.95,u4[2])),f.rgb*u3,f.a*u4[6])-!3(.004)),x=(l.x+1.)*(l.y+1.)*(u4[0]*10.),gl_FragColor=!4((1.-(smoothstep(.98,1.,yy(l*8.+u4[0]*20.))+smoothstep(.95,1.,yy(l*1.5+u4[0]*10.))))*smoothstep(1.042+.008*cos(u4[0]*40.),.8,yyx(zx,8.))*(1.-(mod((mod(x,13.)+1.)*(mod(x,47.)+1.),.01))*8.)*((.95+.05*cos(u4[0]*41.))*(n*(6.2*n+.5))/(n*(6.2*n+!3(1.7))+!3(.06))+!3(smoothstep(.98,1.,yy(l*8.-u4[0]*40.)))),1.);}\';')(misc=raymarchers[i])],programs[i]=[5+misc[15].length*3,0,i+1];
+
+misc = vomNew(10) , camPos = vomNew(3),lookAt=vomNew(3),camUp=vomNew(3),toNearPlane=0,textColour=vomNew(3) , lights= [[vomNew(3),0,0],[vomNew(3),0,0],[vomNew(3),0,0]];
+for ( i in shaders ) {
+	var def = shaders[i];
+	glCtx.shaderSource( i= shaders[i] = glCtx.createShader( def[0] ) , def[1].replace(/!/g,'vec').replace(/%/g,'float') );
+	glCtx.compileShader( i );
+	if (!glCtx.getShaderParameter(i, glCtx.COMPILE_STATUS)) {
+		def[1] = def[1].split( /\n/ );
+		for ( var k in def[1] ) {
+			var j = parseInt(k)+1;
+			def[1][k] = j + ": " + def[1][k];
+		}
+		throw "SHADER ERROR\n" + glCtx.getShaderInfoLog(i) + "\n" + def[1].join('\n');
+	}
+}
+for ( var name in programs ) {
+	var p = glCtx.createProgram( );
+	var d = programs[name];
+	var ul = d.shift();
+	while( d.length ) {
+		glCtx.attachShader( p , shaders[ d.shift() ] );
+	}
+	glCtx.linkProgram( p );
+	var nul = [];
+	while ( ul-- ) {
+		nul[ul] = glCtx.getUniformLocation( p , 'u' + ul );
+	}
+	programs[name] = [p,nul];
+}
+glCtx.bindBuffer( glCtx.ARRAY_BUFFER , glCtx.createBuffer( ) );
+glCtx.bufferData( glCtx.ARRAY_BUFFER , vomNew([1,4,1,-1,-4,-1]) , glCtx.STATIC_DRAW );
+glCtx.clearColor(0,0,0,1);
+
+textTexture = glCtx.createTexture( );
+glCtx.bindTexture( glCtx.TEXTURE_2D , textTexture );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_S, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_WRAP_T, glCtx.CLAMP_TO_EDGE );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MIN_FILTER, glCtx.NEAREST );
+glCtx.texParameteri( glCtx.TEXTURE_2D , glCtx.TEXTURE_MAG_FILTER, glCtx.NEAREST );
+glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+
+
+mCurrentCol=timeStart = 0,mNumWords=10717272,mMixBuf=new Int32Array(mNumWords);
+
+mainfunc = function(){setTimeout(function(){
+requestAnimationFrame(draw=function(time){
+	requestAnimationFrame(draw);
+	if ( timeStart == 0 ) {
+		A.currentTime = 0;
+		A.play( );
+		timeStart = time;
+		previousFrame = timeStart - 33;
+	}
+	var delta = time - previousFrame;
+	demoTime = .001*(time - timeStart);
+	if ( delta < 33 ) {
+		return;
+	}
+	previousFrame = time - ( delta % 33 );
+
+	var ds = direction[t];
+	while ( ds && ds[7] < demoTime ) {
+		ds=direction[++t];
+	}
+	if ( ! ds ) {
+		A.pause( );
+		return;
+	}
+	misc[0] = demoTime;
+	misc[7] = c2rHeight;
+	stepTime = demoTime - ds[5];
+	rStepTime = stepTime / ds[6];
+	if ( ds[4] ) {
+		twoDCtx.clearRect( 0 , 0 , canvasWidth , 100 );
+		ds[4]();
+		glCtx.texImage2D( glCtx.TEXTURE_2D , 0 , glCtx.RGBA , glCtx.RGBA , glCtx.UNSIGNED_BYTE , C2 );
+	}
+
+	ds[2]();
+	vecNorm(cmW,vecSub(cmW,lookAt,camPos));
+	vecNorm(cmU,vecCross(cmU,camUp,cmW));
+	vecNorm(cmV,vecCross(cmV,cmW,cmU));
+	vecScale(cmW,cmW,toNearPlane);
+	for(var i=0;i<3;i++)cm[i*3]=cmU[i],cm[i*3+1]=cmV[i],cm[i*3+2]=cmW[i];
+
+	for ( var i in ds[3] ) {
+		ds[3][i](lights[ i ]);
+	}
+
+	var p = programs[ds[1]];
+	glCtx.useProgram( p[ 0 ] );
+	glCtx.enableVertexAttribArray( 0 );
+	glCtx.vertexAttribPointer( 0 , 2 , glCtx.FLOAT , false , 8 , 0 );
+	p = p[1];
+
+	var u = 0;
+	glCtx.uniformMatrix3fv( p[u++] , false , cm );
+	glCtx.uniform1i( p[u++] , 0 );
+	glCtx.uniform3fv( p[u++] , camPos );
+	glCtx.uniform3fv( p[u++] , textColour );
+	glCtx.uniform1fv( p[u++] , misc );
+	for ( var i in ds[3] ) {
+		glCtx.uniform3fv( p[u++] , lights[ i ][0] );
+		glCtx.uniform1f( p[u++] , lights[ i ][1] );
+		glCtx.uniform1f( p[u++] , lights[ i ][2] );
+	}
+	glCtx.drawArrays( 4 , 0 , 3 );
+})
+},500)};
+
+for(t=i=0;i<53;i++)direction[i][5]=t,t+=(direction[i][6]=direction[i][0]/8),direction[i][7]=t;
+t=0;
+
+if ( USE_SYNTH ) {
+	synthGen = setInterval(function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v){
+		for(d=new Int32Array(mNumWords),f=[[[0,198,128,0,3,192,128,1,0,0,96,128,28,0,0,0,0,2,63,61,13,16,44,8,0,0],[1,2,3,4,5,2,3,4,6,7,1,2,3,4,5,2,3,4,5,2,3,4,1,2,3,8,9],[[[115,,,,,,,,,,,,117,,,,,,,,,,,,113],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[115,,,,,,,,,,,,,,,110],[12,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,148]],[[115,,,,,,,,,,,,117,,,,,,,,,,,,118],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[122,,,,,,,,,,,,,,,123,,,,,115],[12,,,,,,,,,,,,,,,12,,,,,12,,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,8,,,,,128]],[[118,,,,,,,,,,,,117,,,,,,,,,,,,113],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[115],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,255]],[[,,,,,,,,,,,,,,,,118,118,118],[,,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,128]],[[122,,,,,,,,,,,,,,,123,,,,,115],[12,,,,,,,,,,,,,,,12,,,,,13,12,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,8,,,,,95,61]],[[],[]]]],[[0,255,116,1,0,255,101,0,0,15,1,4,45,0,13,6,1,2,62,27,60,48,0,0,44,2],[,1,,2,,1,,2,,3,4,4,5,4,5,4,5,4,5,4,5,4,5,4,3,6],[[[,,,,,139,,,139,139,,,,,,139,,,,,,,,139,,,139,139,,,,,139,139,139],[]],[[,,139,139,,,,,139,139,,,,,139,139,,,,,,,,,,139,139,139,,,,,139,139,139],[]],[[,,,139,,,,,139,139,,,,,,139,,,,,139,139,,,,,,139,,,,139,139,139],[]],[[139,,,,139,,139,,,139,,,139,,,,139,,139,,,139,,,139,,,,139,,139,,,139],[]],[[139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139],[]],[[139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139,139],[]]]],[[0,0,140,0,0,0,140,0,0,128,4,10,34,0,187,5,0,1,239,135,34,19,108,8,8,4],[,,1,,1,,3,,1,3,2,2,2,2,2,3,2,3,2,3,2,3,2,3,1],[[[,,,,,,,,,,127,,,,,,,,,,,,127,,,,,,,,,,,,127],[]],[[,,,139,,,,,,139,139,,,,,139,,,,,,139,139,,,,,139,,,,,139,,139],[]],[[,,127,,,,,,,,127,,,,127,,,,,,,,127,,,,127,,,,,,,,127],[]]]],[[1,192,128,0,3,201,128,0,0,93,5,6,58,3,195,6,1,3,35,63,14,17,11,10,61,6],[,,,,1,2,3,4,5,6,7,5,8,9,10,11,8,9,10,11,12,13,14,15,16],[[[,,,,,,,,147,146,145,,,,,,,,,,145,147,146,,,,,,,,,,149,148,147],[]],[[,,,,,,151,151,151,,,,,,,146,142,138,,,,,,,,,,,,,,,147,150,147],[]],[[,,146,,,146,,,,,,,,,147,146,145,,,,,,,,,,146,145,142,,,142,,,142],[]],[[,,141,,,,,,,,,,,,141,140,139,,,146,,,146,,,127],[]],[[,139,,151,,,,,,,,,,151,,139,,,,,,,,,,139,,151],[]],[[,139,,151,150,149,,,,,,,,139,,149,148,147,,,,,,,,139,,,146,,,145,,,144],[]],[[,139,,,139,142,,,142,144,146,,144,,,,146,147,,,147,146,141,,137,,,,142,141,,141,,137],[]],[[139,,127,,142,,,130,,,144,142,141,,129,,141,,,144,,,141,144,142,,,,149,,,146,,,151],[]],[[,149,,149,,146,144,142,,,141,,142,,,139,,,,151,147,,,,146,147,,144,146,,142,144,141,146],[]],[[,,,,,,,,147,146,145,,,,,141,144,147,146,,144,,137,,,144,146,142,144,,,142,144,141,146],[]],[[,146,,151,,146,,,,144,142,144,146,,,,142,,,,,139,,,,,151,146,139,144,139,142,141,142,151],[]],[[,,147,,,149,146,,,142,,142,141,,,144,,144,,,144,146,142,144,142,,,,151,150,149,,137,,149],[]],[[,151,,,147,151,,,146,151,,,,,144,151,,149,147,149,151,,146,,,144,143,142,,,139,,151,139],[]],[[,,134,,,134,,,134,,,146,144,,,141,144,,,146,147,146,,,144,,139,140,141,,,153,,,141],[]],[[,142,,151,,,142,143,144,,,,151,,,139,,,137,,149,,137,,,,125,,,141,142,141,,,146],[]],[[139,,127,139,,127,139,,127,139,127],[]]]],[[2,160,128,1,0,160,128,0,1,60,4,7,41,0,60,4,1,3,14,0,35,32,31,12,89,1],[,,,,,,,,,,,,1,2,1,2,1,2,1,2,1,2,1,2,1,3],[[[,,139,,,,,,,,,,,,139,,,,,,,,,,,,139,,,,,139,139,,,139],[]],[[,,139,,,151,,,139,,,151,,,139,,,151,,,139,,,151,,,139,,,151,,,146,146,146,146],[]],[[,,139,,,151,,,139,,,151,,,139,,139,139,139,139,127],[]]]],[[2,100,128,0,3,201,128,0,0,0,0,6,29,0,195,6,1,3,28,229,119,77,147,6,61,2],[,,,,,,,,,6,1,2,3,4,5,2,3,4,1,2,3,4,1,2,3,7],[[[115,115,115,115,115,115,115,115,115,115,115,115,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],[]],[[115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110],[]],[[115,115,115,115,115,115,115,115,115,115,115,115,117,117,117,117,117,117,117,117,117,117,117,117,118,118,118,118,118,118,118,118,118,118,118,118],[]],[[110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115],[]],[[118,118,118,118,118,118,118,118,118,118,118,118,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],[]],[[,,,,,,,,,,,,,,,,,,130,,130,,130,,130,,130,,130,118,130,118,130,118,130,118],[,,,,,,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2]],[[110,122,,122,134,,110,122,,122,134,,110,122,,111,123,,111,123,115,127,139,127,115],[,,,,,,,,,,,,,,,,,,,,26,25,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,147]]]],[[2,100,128,0,3,201,128,0,0,0,5,6,58,0,195,6,1,2,135,0,0,32,147,6,121,6],[],[]],[[2,100,128,0,3,201,128,0,0,0,5,6,58,0,195,6,1,2,135,0,0,32,147,6,121,6],[],[]]][mCurrentCol],o=[],g=h=m=p=0;p<=26;p++)for(b=f[1][p],a=0;a<36;a++){((e=b?f[2][b-1][1][a]:0)?((f[0][e-1]=f[2][b-1][1][a+36]||0),e<14?(o=[]):0):0),c=(p*36+a)*5513;for(j=0;j<4;j++)if(n=b?f[2][b-1][0][a+j*36]:0){if(!o[n])for(q=f[0][10],r=f[0][11],s=f[0][12],t=getnotefreq(n+f[0][2]-128),l=getnotefreq(n+f[0][6]-128)*(1+.0008*f[0][7]),u=v=0,q*=q*4,r*=r*4,s*=s*4,o[n]=new Int32Array(q+r+s),k=0;k<q+r+s;k++)e=k<q?(k/q):(1-(k<q+r?0:((k-q-r)/s))),o[n][k]=(80*(mOscillators[f[0][0]](u+=t*(f[0][3]?(e*e):1))*f[0][1]+mOscillators[f[0][4]](v+=l*(f[0][8]?(e*e):1))*f[0][5]+R(0,1)*f[0][9])*e)|0;for(k=0,i=c*2;k<o[n].length;k++,i+=2)d[i]+=o[n][k]}q=f[0][20]*1e-5,r=f[0][24]/255,s=f[0][25]*5513;for(j=0;j<5513;j++)(((n=e=d[k=(c+j)*2])||m)?(t=1.5*S(f[0][18]*.00307999186353015873*(f[0][16]?(mOscillators[f[0][13]](P(2,f[0][15]-9)*k/5513)*f[0][14]/512+.5):1)),g+=t*h,l=(1-f[0][19]/255)*(e-h)-g,h+=t*l,e=f[0][17]==3?h:f[0][17]==1?l:g,q?(e*=q,e=(e<1?e>-1?mOscillators[0](e*.25):-1:1)/q):0,e*=f[0][21]/32,m=e*e>1e-5,t=S(6.283184*P(2,f[0][23]-9)*k/5513)*f[0][22]/512+.5,n=e*(1-t),e*=t):0),(k>=s?(n+=d[k-s+1]*r,e+=d[k-s]*r):0),mMixBuf[k]+=(d[k]=n|0),mMixBuf[k+1]+=(d[k+1]=e|0)}
+		if(++mCurrentCol==8)for(clearInterval(synthGen),s=(f=String.fromCharCode).apply(String,[82,73,70,70,168,16,71,1,87,65,86,69,102,109,116,32,16,0,0,0,1,0,2,0,68,172,0,0,16,177,2,0,4,0,16,0,100,97,116,97,132,16,71,1]),i=0;i<mNumWords||(((A=document.createElement('audio')).src='data:audio/wav;base64,'+btoa(s),A.oncanplaythrough=mainfunc)&&0);i++)e=mMixBuf[i],e=e<-32767?-32767:(e>32767?32767:e),s+=f(e&255,(e>>8)&255)
+	}, 0);
+} else {
+	A = document.createElement("audio");
+	A.oncanplaythrough=mainfunc;
+	A.src= 'music.ogg';
+}
diff --git a/201410_-_Sine_City/sine-city-packing-6-gl.html b/201410_-_Sine_City/sine-city-packing-6-gl.html
new file mode 100644
index 0000000..4a22369
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-6-gl.html
@@ -0,0 +1,3 @@
+<body>
+<script language="javascript" src="sine-city-packing-6-gl.js"></script>
+
diff --git a/201410_-_Sine_City/sine-city-packing-6-gl.js b/201410_-_Sine_City/sine-city-packing-6-gl.js
new file mode 100644
index 0000000..244c1b1
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-6-gl.js
@@ -0,0 +1,455 @@
+var USE_SYNTH = 0;
+
+with(Math)S=sin,C=cos,M=max,N=min,P=pow;
+
+
+f = function(a,b,c){return eval('(function('+a+'){'+b+(b?';':'')+(c?('return '+c):'')+'})')},
+
+getnotefreq=f('a','','.003959503758*P(2,(a-128)/12)'),
+mOscillators=[
+	f('a','','S(a*6.283184)'),
+	f('a','','(a%1)<.5?1:-1'),
+	f('a','','2*(a%1)-1'),
+	f('a,b','b=(a%1)*4','(b<2)?(b-1):(3-b)')
+],
+
+// Vector stuff
+vecOp=f('a','','f(\'a,b,c\',\'for(var i=a.length;--i>=0;)\'+a,\'a\')'),
+vomNew=f('a','','new Float32Array(a)'),
+vecNorm=f('a,b,c','c=Math.sqrt(b[0]*b[0]+b[1]*b[1]+b[2]*b[2])','c?vecScale(a,b,1/c):vecCopy(a,b)'),
+vecCross=f('a,b,c','','vecSet(a,b[1]*c[2]-b[2]*c[1],b[2]*c[0]-b[0]*c[2],b[0]*c[1]-b[1]*c[0])'),
+vecSet=vecOp('a[i]=arguments[i+1]'),
+vecCopy=vecOp('a[i]=b[i]'),
+vecSub=vecOp('a[i]=b[i]-c[i]'),
+vecScale=vecOp('a[i]=b[i]*c'),
+
+
+// Shaders
+shaderHeader='precision highp %;varying !2 zx;',
+shaderFloat=f('a','','a+(a==(a|0)?\'.\':\'\')'),
+shaderVec=f('a','','a.map(shaderFloat).join(\',\')');
+
+
+// Raymarchers
+
+materials = [[[.05],.7,.02,.01],[[.2],.7,.9,.01,5,[.1]],[[1],.5,.4,.02],[[3,0,0],.3,.1,.6,6,[.6,0,0]],[[0,2,0],.9,.5,.4,15,[0,.2,0]],[[3,1.5,0],.95,.6,.9,.3,[.3,.6,0]],[[.1],0,.04,.002,3,[3]],[[0,1.5,2],.9,.3,.4]];
+raymarchers = [[100,.025,1,.7,64,.0005,.5,.3,.4,.015,4,2,.75,[0,1,2,3],'y=x+.1*(sin(x.zxy*.17+u4[0]*.5)+sin(x.yzx*.7+u4[0]*1.5))*8.5*(1.+cos(sin(x.z*.1)+x.z*.3)),z=14.-length(y.xy),w=x.x==.0?1.570795*(x.y>.0?1.:-1.):atan(x.y,x.x),q=8.35-u4[8]*1.35,y=!3(9.*(mod(w+x.z*.02,.628)-.314),length(x.xy)-9.,mod(x.z,12.56)-6.28),u=min(length(y.xy)-.25+.1*cos(x.z*8.+u4[0]*.1),length(y.yz)-.5),y=!3(q*(mod(w+x.z*.02,1.256636)-.628318),y.y+9.-q,mod(x.z,62.8318)-31.4159),o=step(u,z)+1.,z=min(u,z),u=length(y)-1.3;if(u<z)z=u,o=3.;y.y+=q-9.,u=yyx(y.yz,8.)-2.;if(u<z)z=u,o=.0;return !2(z,o);',[[.25,0],[.5,.5]]],[6,.00025,1.08,.7,100,.000008,10,.03,2.1,.2,6,.4,5.1,[0,2,5],'z=1.,y=x;for(int i=0;i<7;i++)x=2.*clamp(x,-!3(.58,.9,1.1),!3(.58,.9,1.1))-x,w=max((1.3+u4[9]*.1*cos(u4[0]*.5))/dot(x,x),1.),x*=w,z*=w;w=length(x.xy),e=!2(w-3.,-w*x.z/length(x)-2.*log(1.+.01*a))/abs(z),w=max(e.x,e.y),o=step(e.y,e.x),y+=!3(.1,.3,-.4)*u0-u2+.25*sin(x*1.),e.x=length(y)-.1*u4[8];if(e.x<w)w=e.x,o=2.;return !2(w,o);',[[.05]]],[100,.000025,1,.75,80,.00005,.5,.3,3,.01,4,.75,4.75,[6,0,4],'x.xy*=t(a*.009),w=min(min(yz(x.xzy),yz(x)),yz(x.yzx)),y=mod(x,!3(15.))-!3(7.5),o=step(z=max(length(max(abs(y)-!3(2.5),!3(.0)))-.25,3.5-length(y)),w),w=min(w,z),z=length(y+.1*sin(y*5.5+u4[0]))-2.;if(z<w)w=z,o=2.;return !2(w,o);',[[.05]]],[20,.0005,1,.6,128,.0001,.5,.002,.01,.08,4,.5,1.75,[2,7],'y=x,y.xz=mod(x.xz,8.)-4.,y.yz*=t(u4[8]+.1*a),y.xy*=t(u4[8]*.5+.2*a),y.y*=.9+.1*sin(u4[8]*5.),w=max(length(y)-3.,-min(length(y)-2.8,max(mod(y.y,.8)-.4,-mod(y.y+.4,.8)+.4))),z=x.y+1.+sin(x.x*4.+u4[8]*2.)*sin(x.z+u4[8])*.1,o=clamp(.5+.5*(z-w)/1.,.0,1.),w=mix(z,w,o)-1.*o*(1.-o),y=x,y.xz=mod(y.xz,8.)-4.,y/=1.25+.25*sin(u4[8]*5.),y.xy*=t(u4[8]*5.),y.yz*=t(u4[8]*2.5),z=max(length(y)-1.,.04-length(max(abs(mod(y,.5)-.25)-!3(.15),!3(.0))));return !2(min(w,z),step(z,w));',[[.02],[.05,.5],[.05,.5]]]];
+
+tunMul=1,
+R=f('a,b','','a-b+Math.random()*b*2'),
+lightFunc=f('a,b','','f(\'a\',\'vecCopy(a[0],camPos),a[1]=\'+a+\',a[2]=\'+b)'),
+
+tun1CamCommon=f('a','vecSet(camPos,-6,0,a=demoTime*6),vecSet(lookAt,misc[1]=1,misc[8]=0,a),vecSet(camUp,0,1,0)'),
+desyncFunc=f('a','','f(\'\',\'misc[4]=(\'+(a>0?a:\'\')+\'-stepTime*\'+a+\'/direction[t][6])*R(.875,.125)\')'),
+balls1CamFunc=f('a,b,c,d','c=desyncFunc(c),d=f(\'a,b,c,d\',\'vecSet(camPos,misc[2]=misc[8]=0,4,d=demoTime*3),vecSet(lookAt,a,0,d+b),vecSet(camUp,0,0,1),c()\')','function(){d(a,b,c)}'),
+balls2CamCommon=f('a','a=demoTime*5,vecSet(camPos,C(demoTime)*12,8,S(demoTime)*12+a),vecSet(lookAt,1,0,a),vecSet(camUp,0,1,0),toNearPlane=2.5,misc[8]=demoTime-direction[43][5]'),
+balls2LightFunc=f('a','','f(\'a\',\'vecSet(a[0],\'+a+\'*C(demoTime*2)*5,3,\'+a+\'*S(demoTime*2)*5+demoTime*30),a[1]=1,a[2]=4\')'),
+fract1CamCommon=f('','vecSet(camPos,4,2.5+.025*demoTime,6.7),vecSet(lookAt,misc[8]=misc[9]=0,2.5-.05*demoTime,6.7),vecSet(camUp,0,0,1),toNearPlane=3'),
+fract1CamFunc=f('a','a=desyncFunc(a)','function(){fract1CamCommon(),a()}'),
+fract2CamCommon=f('a,b','vecSet(camPos,5*S(b=demoTime*.2),9*C(demoTime*.41),7.8),vecSet(lookAt,C(b),S(demoTime*.33),camPos[2]-2),vecSet(camUp,0,0,misc[9]=1),misc[8]=a,toNearPlane=3'),
+
+drawText=f('a,b,c','with(twoDCtx)shadowBlur=c2height/5,fillText(a,b,c=c2height/2),shadowBlur=0,strokeText(a,b,c)'),
+titleParts=['TheT(ourist)','presents','Sine City'],
+titleText=f('a,b,c,d,e,f','drawText(titleParts[a],canvasWidth/15),misc[5]=1-c2rHeight+R(0,b),misc[6]=c,vecSet(textColour,d,e,f)'),
+greetingsText=f('','drawText(\'Greetings to ... Mog, Sycop, Tim & Wullon ... Adinpsz ... Alcatraz ... ASD ... Bits\\\'n\\\'Bites ... Brain Control ... Cocoon ... Conspiracy ... Ctrl+Alt+Test ... Fairlight ... Farbrausch ... Kewlers ... LNX ... Loonies ... Mercury ... Popsy Team ... Razor 1911 ... RGBA ... 7th Cube ... Still ... TPOLM ... TRBL ... Umlaut Design ... X-Men ... Youth Uprising ... Everyone here at DemoJS 2014!\',canvasWidth*(1-(demoTime-direction[34][5])/2)),misc[5]=1-c2rHeight+R(.01,.01),vecSet(textColour,misc[6]=1,1,1)'),
+squaresCam=f('a,b','a=demoTime-direction[25][5],vecSet(camPos,b=a*10-80,0,0),vecSet(lookAt,b+C(a*.5)*80,S(a*.25)*40,100),vecSet(camUp,0,toNearPlane=2.5,0)'),
+squaresCam2=f('a,b','a=demoTime-direction[a][5],vecSet(camPos,0,0,b=a*20-80),vecSet(lookAt,C(a*.5)*80,S(a*.25)*40,100+b),vecSet(camUp,0,1,0),misc[4]=R(a=.0125,a)'),
+tunnelLight=f('a','vecSub(a[0],camPos,vecNorm(a[0],lookAt)),a[0][1]-=.5,a[1]=3,a[2]=30'),
+tunnelCam=f('a','a=(demoTime-direction[a][5])*30*tunMul,vecSet(camPos,1.1*C(a*.1),S(a*.02),a),a+=5,vecSet(lookAt,-S(a*.05),-.7*C(a*.033),a),vecSet(camUp,0,toNearPlane=2,0)'),
+tunnelLightBall=f('a','','f(\'a,b\',\'b=demoTime-direction[\'+a+\'][5],vecSet(a[0],4*S(b*.5)*C(b*.7),3*C(b*1.5),b*30*tunMul+14+16*S(b*3.3)*C(b*.77)),a[1]=1,a[2]=2\')'),
+
+// direction    0<->rows / 1<->rm / 2<->setGlobals / 3<->lights / 4<->updateText / 5<->startTime / 6<->time / 7<->endTime
+direction = [
+	[
+		36 ,
+		0 ,
+		f('','tun1CamCommon(misc[2]=1-rStepTime*rStepTime*rStepTime,toNearPlane=5)') ,
+		a=[lightFunc(3,20)]
+	] , [
+		18 ,
+		0 ,
+		f('','tun1CamCommon(misc[2]=0,toNearPlane=5-2.25*rStepTime)') ,
+		a
+	] , [
+		36 ,
+		0 ,
+		f('','tun1CamCommon(misc[2]=rStepTime,toNearPlane=2.75-2.25*rStepTime)') ,
+		a
+	] , [
+		18 ,
+		3 ,
+		f('a','vecSet(camPos,0,4,a=demoTime*3),vecSet(lookAt,4,0,a),vecSet(camUp,0,0,1),misc[2]=1-rStepTime*rStepTime*rStepTime,toNearPlane=2.5') ,
+		[ lightFunc(.75,8) ]
+	] , [
+		22 ,
+		3 ,
+		balls1CamFunc(4,0,0) ,
+		a=[lightFunc(1,8)]
+	] , [
+		22 ,
+		3 ,
+		balls1CamFunc(2,-2,0) ,
+		a
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 6 , 0 , -.5 ) ,
+		b=[lightFunc(.5,4)]
+	] , [
+		9 ,
+		3 ,
+		balls1CamFunc( 6 , 0 , .5 ) ,
+		b
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , -.2 ) ,
+		a
+	] , [
+		9 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , .2 ) ,
+		a
+	] , [
+		3 ,
+		3 ,
+		balls1CamFunc( 2 , 5 , -.7 ) ,
+		a=[ lightFunc(1,2) ]
+	] , [
+		7 ,
+		3 ,
+		balls1CamFunc( 2 , 2 , .7 ) ,
+		a
+	] , [
+		9 ,
+		3 ,
+		f('a','vecSet(camPos,0,4+rStepTime*2,a=demoTime*3),vecSet(lookAt,2,0,a+2),vecSet(camUp,0,0,misc[3]=1),misc[2]=rStepTime') ,
+		a
+	] , [
+		21 ,
+		1 ,
+		f('','fract1CamCommon(misc[2]=1-rStepTime*rStepTime*rStepTime,misc[3]=1)'),
+		a=[f('a','vecCopy(a[0],camPos),a[0][2]+=2,a[1]=1,a[2]=3')]
+	] , [
+		14 ,
+		1 ,
+		fract1CamFunc(0) ,
+		a
+	] , [
+		3 ,
+		1 ,
+		fract1CamFunc(-.4) ,
+		a
+	] , [
+		9 ,
+		1 ,
+		fract1CamFunc(.4) ,
+		a
+	] , [
+		3 ,
+		1 ,
+		fract1CamFunc(-.2) ,
+		a
+	] , [
+		9 ,
+		1 ,
+		fract1CamFunc(.2) ,
+		a
+	] , [
+		12 ,
+		1 ,
+		f('','fract1CamCommon(misc[4]=(-(6*rStepTime)%1)*R(.875,.125))'),
+		a
+	] , [
+		22 ,
+		1 ,
+		f('','fract1CamCommon(misc[4]=((30*rStepTime)%1)*R(.925,.075),misc[2]=rStepTime,misc[3]=.4),toNearPlane=3-2.5*M(1,2*rStepTime)'),
+		a
+	] , [
+		3 ,
+		1 ,
+		b=f('','fract1CamCommon(misc[4]=0,misc[2]=1)'),
+		a
+	] , [
+		12 ,
+		1 ,
+		b ,
+		a,
+		f('','titleText(0,.08,1,1,1,1)')
+	] , [
+		12 ,
+		1 ,
+		b ,
+		a,
+		f('','titleText(0,.08,1-rStepTime,1,1,1)')
+	] , [
+		12 ,
+		1 ,
+		b ,
+		a,
+		f('','titleText(1,.08,1-rStepTime,1,1,1)')
+	] , [
+		20 ,
+		2 ,
+		f('','squaresCam(misc[2]=1-rStepTime)') ,
+		b=[lightFunc(1,30)],
+		f('','titleText(2,.04,rStepTime,1,1,1)')
+	] , [
+		52 ,
+		2 ,
+		f('','squaresCam(misc[2]=0)'),
+		b,
+		f('','titleText(2,.04,1,1,1,1)')
+	] , [
+		12 ,
+		2 ,
+		f('','squaresCam(misc[2]=1-M(0,rStepTime*2),misc[3]=1)'),
+		b,
+		f('','titleText(2,.04,1,1-rStepTime,1-rStepTime/2,1-rStepTime)')
+	] , [
+		12 ,
+		2 ,
+		f('a','squaresCam(misc[1]=1-rStepTime/2,misc[4]=(1-rStepTime)*.7+R(a=.0125,a))') ,
+		b,
+		f('','titleText(2,.04,1,0,.5,0)')
+	] , [
+		9 ,
+		2 ,
+		f('','squaresCam2(29,misc[1]=(1-rStepTime)/2,misc[2]=1-M(0,rStepTime*1.5),misc[4]+=misc[1]*.6)'),
+		b,
+		f('','titleText(2,.04,1-rStepTime,0,.5,0)')
+	] , [
+		69 ,
+		2 ,
+		f('','squaresCam2(29,misc[1]=0)') ,
+		b
+	] , [
+		11 ,
+		2 ,
+		f('','squaresCam2(29,misc[2]=rStepTime,misc[3]=.2)'),
+		b
+	] , [
+		11 ,
+		0 ,
+		f('','tunnelCam(32,misc[2]=1-rStepTime)'),
+		b=[ tunnelLight ]
+	] , [
+		17 ,
+		0 ,
+		f('','tunnelCam(32,misc[2]=0,misc[4]=(1-rStepTime)*1.2*R(1,.02))') ,
+		b
+	] , [
+		18 ,
+		0 ,
+		f('','tunnelCam(32,misc[4]=0,misc[8]=rStepTime)') ,
+		b ,
+		greetingsText
+	] , [
+		36 ,
+		0 ,
+		f('','tunnelCam(32,misc[2]=1-N(misc[8]=1,4*rStepTime))'),
+		b = [ tunnelLight , tunnelLightBall(32) ],
+		greetingsText
+	] , [
+		33 ,
+		0 ,
+		f('','tunnelCam(32,misc[2]=rStepTime,misc[3]=.7,misc[4]=-((4*rStepTime)%1)*R(1,.05))'),
+		b ,
+		greetingsText
+	] , [
+		9 ,
+		1 ,
+		f('','fract2CamCommon(misc[4]=0,misc[2]=rStepTime,misc[3]=1)'),
+		a,
+		greetingsText
+	] , [
+		20 ,
+		1 ,
+		f('','fract2CamCommon(rStepTime,misc[2]=0)'),
+		a,
+		greetingsText
+	] , [
+		31 ,
+		1 ,
+		f('','fract2CamCommon(1,misc[2]=1-N(1,5*rStepTime))'),
+		a,
+		greetingsText
+	] , [
+		5 ,
+		1 ,
+		f('','fract2CamCommon(1,misc[2]=1-rStepTime)'),
+		a,
+		greetingsText
+	] , [
+		18 ,
+		1 ,
+		f('','fract2CamCommon(1,misc[2]=1-N(1,5*rStepTime),misc[4]=M(0,1.6*rStepTime-.8)*R(1,.05))'),
+		a,
+		greetingsText
+	] , [
+		12 ,
+		1 ,
+		f('','fract2CamCommon(1,misc[2]=rStepTime,misc[4]=(1-rStepTime)*.8*R(1,.05),misc[3]=.1)'),
+		a,
+		greetingsText
+	] , [
+		22 ,
+		3 ,
+		f('','balls2CamCommon(misc[2]=1-rStepTime,misc[4]=0)'),
+		a = [ lightFunc(.6,30) , balls2LightFunc(1),balls2LightFunc(-1) ],
+		greetingsText
+	] , [
+		59 ,
+		3 ,
+		f('','balls2CamCommon(misc[2]=1-N(1,(12*rStepTime)%4),misc[3]=.8)'),
+		a,
+		greetingsText
+	] , [
+		8 ,
+		3 ,
+		f('','balls2CamCommon(misc[2]=rStepTime,misc[4]=R(0,misc[3]=.1))'),
+		a
+	] , [
+		7 ,
+		0 ,
+		f('','misc[tunMul=2]=1-rStepTime,tunnelCam(46,misc[4]=R(0,.1),misc[8]=1)'),
+		a = [ tunnelLight , tunnelLightBall(46) ]
+	] , [
+		22 ,
+		0 ,
+		f('','tunnelCam(46,misc[4]=R(0,.1))'),
+		a
+	] , [
+		10 ,
+		0 ,
+		f('','tunnelCam(46,misc[4]=R(0,.1+rStepTime*.4)+stepTime*4,misc[2]=rStepTime,misc[3]=1)'),
+		a
+	] , [
+		10 ,
+		2 ,
+		f('','squaresCam2(49,misc[2]=1-rStepTime),misc[4]=R(0,.5)+(demoTime-direction[48][5])*4'),
+		a=[ lightFunc(1,30) ]
+	] , [
+		40 ,
+		2 ,
+		f('','squaresCam2(49),misc[4]=R(0,.5)-(demoTime-direction[48][5])*6'),
+		a
+	] , [
+		40 ,
+		2 ,
+		f('','squaresCam2(49),misc[4]=R(misc[3]=0,.5)+(demoTime-direction[48][5])*8,misc[2]=rStepTime'),
+		a
+	] , [
+		68 ,
+		2 ,
+		f('','squaresCam2(49,misc[2]=1)'),
+		a
+	]
+];
+
+cmU=vomNew(3),
+    cmV=vomNew(3),
+    cmW=vomNew(3),
+    cd=vomNew(3),
+    cu=vomNew(3),
+    cm=vomNew(9);
+
+
+// Main
+
+with(document.body)style.background='black',innerHTML='<canvas id=C1 style=position:fixed;cursor:none></canvas><canvas id=C2 style=display:none>';
+twoDCtx = C2.getContext('2d');
+for(i in glCtx=C1.getContext('webgl'))glCtx[i.match(/^..|[A-Z]|\d[fi]v?$/g).join('')]=glCtx[i];
+(window.onresize=f('a,b,c,d,e','with(twoDCtx)a=innerWidth,b=innerHeight,c=(b*1.6)|0,d=(a*.625)|0,glCtx.vi(0,0,C2.style.width=C2.width=C1.width=canvasWidth=c>a?a:c,C1.height=e=c>a?d:b),c2height=C2.style.height=C2.height=M(e/8,100),c2rHeight=c2height/e,C1.style.left=((a-canvasWidth)/2)|0,C1.style.top=((b-e)/2)|0,shadowColor=\'#ccc\',font=\'normal small-caps bold \'+((c2height/2)|0)+\'px monospace\',fillStyle=\'#111\',strokeStyle=\'#ddd\''))();
+
+
+for(shaders=[[35633,shaderHeader+'attribute !2 i;void main(){gl_Position=!4(i,.0,1.),zx=i;}']],programs=[],i=0;i<4;i++)shaders[i+1]=[35632,f('a,b,c,d,e','b=\'uniform \',d=5,c=shaderHeader+b+\'mat3 u0;\'+b+\'sampler2D u1;\'+b+\'!3 u2,u3;\'+b+\'% u4[10];\';for(e in a[15])c+=b+\'!3 u\'+d+++\';\'+b+\'% u\'+d+++\', u\'+d+++\';\';c+=\'const !2 c=!2(1.,-1.)*\'+a[5]+\';% p,z,w,u,o,zy,q,x,a,zz;!2 e,h;!3 l=!3(zx,1.),m,r,s=u2,yx=!3(1.),n=!3(.0),b,v,xxx,xy,d,xx,xz,y;!4 f;% g(% x){return fract(sin(x)*43758.5453);}% yy(!3 x){m=floor(x),y=fract(x),y*=y*(3.-2.*y),z=m.x+m.y*57.+m.z*113.;return mix(mix(mix(g(z),g(z+1.),y.x),mix(g(z+57.),g(z+58.),y.x),y.y),mix(mix(g(z+113.),g(z+114.),y.x),mix(g(z+170.),g(z+171.),y.x),y.y),y.z);}% yyx(!2 x,% a){e=pow(abs(x),!2(a));return pow(e.x+e.y,1./a);}mat2 t(% x){e=!2(cos(x),sin(x));return mat2(-e.x,e.y,e.y,e.x);}% yz(!3 x){return length(mod(x.xy,!2(15.))-!2(7.5))-.5+.05*sin(x.z*9.42477);}!2 k(!3 x,% a){\'+a[14]+\'}void main(){l.y+=mod(u4[4],1.)*2.2;if(l.y>1.){if(l.y<1.2)discard;l.y-=2.2;}l.x*=1.6,r=normalize(l*u0);for(int j=0;j<2;j++){v=r,xxx=s,xy=!3(.0),x=.0,a=\'+a[1]+\';for(int i=0;i<\'+a[4]+\';i++){h=k(s+r*x,x);if(h.x<a||i>\'+a[4]+\'/(j+1)||x>\'+a[0]+\'.)break;x+=h.x*\'+a[3]+\',a*=\'+shaderFloat(a[2])+\';}h.x=x;if(x<\'+a[0]+\'.){d=s+r*x,f=!4(k(d+c.xyy,x).x,k(d+c.yyx,x).x,k(d+c.yxy,x).x,k(d+c.xxx,x).x),xx=normalize(f.x*c.xyy+f.y*c.yyx+f.z*c.yxy+f.w*c.xxx),a=.0,p=\'+a[12]+\';for(int i=1;i<=\'+a[10]+\';i++)x=(%(i)/\'+a[10]+\'.)*\'+shaderFloat(a[11])+\',m=d+xx*x,q=max(.1,1.-clamp(pow(a+=p*(x-k(m,distance(m,s)).x),1.),.0,1.)),p*=.5;\';for(e in d=a[13])b=materials[d[e]],c+=(e>0?\'else \':\'\')+\'if(h.y==\'+e+\'.)xz=\'+(b[4]?(\'mix(!3(\'+shaderVec(b[0])+\'),!3(\'+shaderVec(b[5])+\'),yy(d*\'+shaderFloat(a[6]*b[4])+\'))\'):(\'!3(\'+shaderVec(b[0])+\')\'))+\',w=\'+shaderFloat(b[1])+\',u=\'+b[2]+\',o=\'+b[3]+\';\';d=5,c+=\'v=reflect(r,xx),z=\'+a[9]+\'*h.x,z=clamp(exp(-z*z*z*1.442695),.0,1.),x=clamp((1.+dot(normalize(v+r),r)),.0,1.),a=x*x,zz=o+(1.-o)*x*a*a*(u*.9+.1),y=mix(!3(1.),xz/dot(!3(.299,.587,.114),xz),w),m=!3(.0),zy=exp2(4.+6.*u),\';for(e in b=a[15])c+=\'p=length(b=u\'+d+\'-d),b/=p,p=max(1.,p-u\'+(d+2)+\')*\'+b[e][0]+\',p=1./max(1.,p*p),m+=mix((1.-w)*xz*q,y*pow(max(dot(reflect(r,xx),b),.0),zy)*(zy+2.)/8.,zz)*p*max(dot(b,xx),.0)*!3(u\'+(d+1)+\'),\',d+=3;d=5,c+=\'xy=yx*z*normalize(y)*o*(u*.9+.1)*zz,m=mix(!3(\'+shaderFloat(a[8])+\'),m,z),xxx+=normalize(v)*\'+a[7]+\';}else m=!3(\'+shaderFloat(a[8])+\');\';for(e in b=a[15])(a=b[e][1])?c+=\'b=s-u\'+d+\',p=dot(r,r),a=2.*dot(b,r),x=a*a-4.*p*(dot(b,b)-\'+(a*a)+\'),e=x<.0?!2(-1.):(x=sqrt(x),-.5*!2(a+x,a-x)/p),e=!2(min(e.x,e.y),max(e.x,e.y));if(e.x>.0&&e.y<h.x)m+=u\'+(d+2)+\'*!3(u\'+(d+1)+\')*pow((e.y-e.x)/\'+shaderFloat(a*2)+\',64.);\':0,d+=3','c+=\'n+=m*yx;if(all(lessThan(xy,!3(.01))))break;yx=xy,s=xxx,r=normalize(v);}h=!2(zx.x,l.y)*.5+.5,h.y=(1.-h.y-u4[5])/u4[7],f=texture2D(u1,h),n=max(!3(.0),mix(mix(mix(n,(n.x==n.y&&n.x==n.z)?n:!3(dot(n,!3(.299,.587,.114))),u4[1]),!3(u4[3]),smoothstep(.05,.95,u4[2])),f.rgb*u3,f.a*u4[6])-!3(.004)),x=(l.x+1.)*(l.y+1.)*(u4[0]*10.),gl_FragColor=!4((1.-(smoothstep(.98,1.,yy(l*8.+u4[0]*20.))+smoothstep(.95,1.,yy(l*1.5+u4[0]*10.))))*smoothstep(1.042+.008*cos(u4[0]*40.),.8,yyx(zx,8.))*(1.-(mod((mod(x,13.)+1.)*(mod(x,47.)+1.),.01))*8.)*((.95+.05*cos(u4[0]*41.))*(n*(6.2*n+.5))/(n*(6.2*n+!3(1.7))+!3(.06))+!3(smoothstep(.98,1.,yy(l*8.-u4[0]*40.)))),1.);}\';')(misc=raymarchers[i])],programs[i]=[5+misc[15].length*3,0,i+1];
+
+misc = vomNew(10) , camPos = vomNew(3),lookAt=vomNew(3),camUp=vomNew(3),toNearPlane=0,textColour=vomNew(3) , lights= [[vomNew(3),0,0],[vomNew(3),0,0],[vomNew(3),0,0]];
+with(glCtx) {
+	for(i in shaders)
+		j=shaders[i],
+		shS(i=shaders[i]=crS(j[0]),j[1].replace(/!/g,'vec').replace(/%/g,'float')),
+		coS(i),
+		geSP(i,35713);
+	for(i in programs){
+		var p=crP(),d=programs[i],ul=d.shift();
+		for(j in d)atS(p,shaders[d[j]]);
+		liP(p),d=[];
+		for(;ul--;)d[ul]=geUL(p,'u'+ul);
+		programs[i]=[p,d]
+	}
+	biB(i=34962,crB()),buD(i,vomNew([1,4,1,-1,-4,-1]),35044),biT(i=3553,crT())
+	teP(i,j=10240,k=9728),teP(i,++j,k),teP(i,++j,k=33071),teP(i,++j,k),
+	teID(i,0,j=6408,j,5121,C2)
+}
+
+mCurrentCol=timeStart = 0,mNumWords=10717272,mMixBuf=new Int32Array(mNumWords);
+
+mainfunc = function(){setTimeout(function(){
+requestAnimationFrame(draw=function(time){
+	requestAnimationFrame(draw);
+	if ( timeStart == 0 ) {
+		A.currentTime = 0;
+		A.play( );
+		timeStart = time;
+		previousFrame = timeStart - 33;
+	}
+	var delta = time - previousFrame;
+	demoTime = .001*(time - timeStart);
+	if ( delta < 33 ) {
+		return;
+	}
+	previousFrame = time - ( delta % 33 );
+
+	var ds = direction[t];
+	while ( ds && ds[7] < demoTime ) {
+		ds=direction[++t];
+	}
+	if ( ! ds ) {
+		A.pause( );
+		return;
+	}
+	misc[0] = demoTime;
+	misc[7] = c2rHeight;
+	stepTime = demoTime - ds[5];
+	rStepTime = stepTime / ds[6];
+	with (glCtx) {
+		if ( ds[4] ) {
+			twoDCtx.clearRect( 0 , 0 , canvasWidth , 100 );
+			teID( 3553 , ds[4]() , j=6408 , j , 5121 , C2 );
+		}
+
+		ds[2]();
+		vecNorm(cmW,vecSub(cmW,lookAt,camPos));
+		vecNorm(cmU,vecCross(cmU,camUp,cmW));
+		vecNorm(cmV,vecCross(cmV,cmW,cmU));
+		vecScale(cmW,cmW,toNearPlane);
+		for(i=0;i<3;i++)cm[i*3]=cmU[i],cm[i*3+1]=cmV[i],cm[i*3+2]=cmW[i];
+
+		for (i in ds[3])ds[3][i](lights[i]);
+
+		var p = programs[ds[1]];
+		var u = 0;
+		usP( p[ 0 ] );
+		p = p[1];
+		veAP(enVAA(unM3fv(p[u++],un1i(p[u++],un3fv(p[u++],camPos)),cm)),2,5126,un3fv(p[u++],textColour),8,un1fv(p[u++],misc));
+		for(i in ds[3])un3fv(p[u++],lights[i][0]),un1f(p[u++],lights[i][1]),un1f(p[u++],lights[i][2]);
+		drA(4,0,3)
+	}
+})
+},500)};
+
+for(t=i=0;i<53;i++)direction[i][5]=t,t+=(direction[i][6]=direction[i][0]/8),direction[i][7]=t;
+t=0;
+
+if ( USE_SYNTH ) {
+	synthGen = setInterval(function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v){
+		for(d=new Int32Array(mNumWords),f=[[[0,198,128,0,3,192,128,1,0,0,96,128,28,0,0,0,0,2,63,61,13,16,44,8,0,0],[1,2,3,4,5,2,3,4,6,7,1,2,3,4,5,2,3,4,5,2,3,4,1,2,3,8,9],[[[115,,,,,,,,,,,,117,,,,,,,,,,,,113],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[115,,,,,,,,,,,,,,,110],[12,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,148]],[[115,,,,,,,,,,,,117,,,,,,,,,,,,118],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[122,,,,,,,,,,,,,,,123,,,,,115],[12,,,,,,,,,,,,,,,12,,,,,12,,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,8,,,,,128]],[[118,,,,,,,,,,,,117,,,,,,,,,,,,113],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[115],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,255]],[[,,,,,,,,,,,,,,,,118,118,118],[,,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,128]],[[122,,,,,,,,,,,,,,,123,,,,,115],[12,,,,,,,,,,,,,,,12,,,,,13,12,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,8,,,,,95,61]],[[],[]]]],[[0,255,116,1,0,255,101,0,0,15,1,4,45,0,13,6,1,2,62,27,60,48,0,0,44,2],[,1,,2,,1,,2,,3,4,4,5,4,5,4,5,4,5,4,5,4,5,4,3,6],[[[,,,,,139,,,139,139,,,,,,139,,,,,,,,139,,,139,139,,,,,139,139,139],[]],[[,,139,139,,,,,139,139,,,,,139,139,,,,,,,,,,139,139,139,,,,,139,139,139],[]],[[,,,139,,,,,139,139,,,,,,139,,,,,139,139,,,,,,139,,,,139,139,139],[]],[[139,,,,139,,139,,,139,,,139,,,,139,,139,,,139,,,139,,,,139,,139,,,139],[]],[[139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139],[]],[[139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139,139],[]]]],[[0,0,140,0,0,0,140,0,0,128,4,10,34,0,187,5,0,1,239,135,34,19,108,8,8,4],[,,1,,1,,3,,1,3,2,2,2,2,2,3,2,3,2,3,2,3,2,3,1],[[[,,,,,,,,,,127,,,,,,,,,,,,127,,,,,,,,,,,,127],[]],[[,,,139,,,,,,139,139,,,,,139,,,,,,139,139,,,,,139,,,,,139,,139],[]],[[,,127,,,,,,,,127,,,,127,,,,,,,,127,,,,127,,,,,,,,127],[]]]],[[1,192,128,0,3,201,128,0,0,93,5,6,58,3,195,6,1,3,35,63,14,17,11,10,61,6],[,,,,1,2,3,4,5,6,7,5,8,9,10,11,8,9,10,11,12,13,14,15,16],[[[,,,,,,,,147,146,145,,,,,,,,,,145,147,146,,,,,,,,,,149,148,147],[]],[[,,,,,,151,151,151,,,,,,,146,142,138,,,,,,,,,,,,,,,147,150,147],[]],[[,,146,,,146,,,,,,,,,147,146,145,,,,,,,,,,146,145,142,,,142,,,142],[]],[[,,141,,,,,,,,,,,,141,140,139,,,146,,,146,,,127],[]],[[,139,,151,,,,,,,,,,151,,139,,,,,,,,,,139,,151],[]],[[,139,,151,150,149,,,,,,,,139,,149,148,147,,,,,,,,139,,,146,,,145,,,144],[]],[[,139,,,139,142,,,142,144,146,,144,,,,146,147,,,147,146,141,,137,,,,142,141,,141,,137],[]],[[139,,127,,142,,,130,,,144,142,141,,129,,141,,,144,,,141,144,142,,,,149,,,146,,,151],[]],[[,149,,149,,146,144,142,,,141,,142,,,139,,,,151,147,,,,146,147,,144,146,,142,144,141,146],[]],[[,,,,,,,,147,146,145,,,,,141,144,147,146,,144,,137,,,144,146,142,144,,,142,144,141,146],[]],[[,146,,151,,146,,,,144,142,144,146,,,,142,,,,,139,,,,,151,146,139,144,139,142,141,142,151],[]],[[,,147,,,149,146,,,142,,142,141,,,144,,144,,,144,146,142,144,142,,,,151,150,149,,137,,149],[]],[[,151,,,147,151,,,146,151,,,,,144,151,,149,147,149,151,,146,,,144,143,142,,,139,,151,139],[]],[[,,134,,,134,,,134,,,146,144,,,141,144,,,146,147,146,,,144,,139,140,141,,,153,,,141],[]],[[,142,,151,,,142,143,144,,,,151,,,139,,,137,,149,,137,,,,125,,,141,142,141,,,146],[]],[[139,,127,139,,127,139,,127,139,127],[]]]],[[2,160,128,1,0,160,128,0,1,60,4,7,41,0,60,4,1,3,14,0,35,32,31,12,89,1],[,,,,,,,,,,,,1,2,1,2,1,2,1,2,1,2,1,2,1,3],[[[,,139,,,,,,,,,,,,139,,,,,,,,,,,,139,,,,,139,139,,,139],[]],[[,,139,,,151,,,139,,,151,,,139,,,151,,,139,,,151,,,139,,,151,,,146,146,146,146],[]],[[,,139,,,151,,,139,,,151,,,139,,139,139,139,139,127],[]]]],[[2,100,128,0,3,201,128,0,0,0,0,6,29,0,195,6,1,3,28,229,119,77,147,6,61,2],[,,,,,,,,,6,1,2,3,4,5,2,3,4,1,2,3,4,1,2,3,7],[[[115,115,115,115,115,115,115,115,115,115,115,115,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],[]],[[115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110],[]],[[115,115,115,115,115,115,115,115,115,115,115,115,117,117,117,117,117,117,117,117,117,117,117,117,118,118,118,118,118,118,118,118,118,118,118,118],[]],[[110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115],[]],[[118,118,118,118,118,118,118,118,118,118,118,118,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],[]],[[,,,,,,,,,,,,,,,,,,130,,130,,130,,130,,130,,130,118,130,118,130,118,130,118],[,,,,,,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2]],[[110,122,,122,134,,110,122,,122,134,,110,122,,111,123,,111,123,115,127,139,127,115],[,,,,,,,,,,,,,,,,,,,,26,25,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,147]]]],[[2,100,128,0,3,201,128,0,0,0,5,6,58,0,195,6,1,2,135,0,0,32,147,6,121,6],[],[]],[[2,100,128,0,3,201,128,0,0,0,5,6,58,0,195,6,1,2,135,0,0,32,147,6,121,6],[],[]]][mCurrentCol],o=[],g=h=m=p=0;p<=26;p++)for(b=f[1][p],a=0;a<36;a++){((e=b?f[2][b-1][1][a]:0)?((f[0][e-1]=f[2][b-1][1][a+36]||0),e<14?(o=[]):0):0),c=(p*36+a)*5513;for(j=0;j<4;j++)if(n=b?f[2][b-1][0][a+j*36]:0){if(!o[n])for(q=f[0][10],r=f[0][11],s=f[0][12],t=getnotefreq(n+f[0][2]-128),l=getnotefreq(n+f[0][6]-128)*(1+.0008*f[0][7]),u=v=0,q*=q*4,r*=r*4,s*=s*4,o[n]=new Int32Array(q+r+s),k=0;k<q+r+s;k++)e=k<q?(k/q):(1-(k<q+r?0:((k-q-r)/s))),o[n][k]=(80*(mOscillators[f[0][0]](u+=t*(f[0][3]?(e*e):1))*f[0][1]+mOscillators[f[0][4]](v+=l*(f[0][8]?(e*e):1))*f[0][5]+R(0,1)*f[0][9])*e)|0;for(k=0,i=c*2;k<o[n].length;k++,i+=2)d[i]+=o[n][k]}q=f[0][20]*1e-5,r=f[0][24]/255,s=f[0][25]*5513;for(j=0;j<5513;j++)(((n=e=d[k=(c+j)*2])||m)?(t=1.5*S(f[0][18]*.00307999186353015873*(f[0][16]?(mOscillators[f[0][13]](P(2,f[0][15]-9)*k/5513)*f[0][14]/512+.5):1)),g+=t*h,l=(1-f[0][19]/255)*(e-h)-g,h+=t*l,e=f[0][17]==3?h:f[0][17]==1?l:g,q?(e*=q,e=(e<1?e>-1?mOscillators[0](e*.25):-1:1)/q):0,e*=f[0][21]/32,m=e*e>1e-5,t=S(6.283184*P(2,f[0][23]-9)*k/5513)*f[0][22]/512+.5,n=e*(1-t),e*=t):0),(k>=s?(n+=d[k-s+1]*r,e+=d[k-s]*r):0),mMixBuf[k]+=(d[k]=n|0),mMixBuf[k+1]+=(d[k+1]=e|0)}
+		if(++mCurrentCol==8)for(clearInterval(synthGen),s=(f=String.fromCharCode).apply(String,[82,73,70,70,168,16,71,1,87,65,86,69,102,109,116,32,16,0,0,0,1,0,2,0,68,172,0,0,16,177,2,0,4,0,16,0,100,97,116,97,132,16,71,1]),i=0;i<mNumWords||(((A=document.createElement('audio')).src='data:audio/wav;base64,'+btoa(s),A.oncanplaythrough=mainfunc)&&0);i++)e=mMixBuf[i],e=e<-32767?-32767:(e>32767?32767:e),s+=f(e&255,(e>>8)&255)
+	}, 0);
+} else {
+	A = document.createElement("audio");
+	A.oncanplaythrough=mainfunc;
+	A.src= 'music.ogg';
+}
diff --git a/201410_-_Sine_City/sine-city-packing-7-variables.html b/201410_-_Sine_City/sine-city-packing-7-variables.html
new file mode 100644
index 0000000..33ea5c4
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-7-variables.html
@@ -0,0 +1,3 @@
+<body>
+<script language="javascript" src="sine-city-packing-7-variables.js"></script>
+
diff --git a/201410_-_Sine_City/sine-city-packing-7-variables.js b/201410_-_Sine_City/sine-city-packing-7-variables.js
new file mode 100644
index 0000000..55b4466
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-7-variables.js
@@ -0,0 +1,418 @@
+var USE_SYNTH = 1;
+
+with(Math)S=sin,C=cos,M=max,N=min,P=pow;
+
+
+f = function(a,b,c){return eval('(function('+a+'){'+b+(b?';':'')+(c?('return '+c):'')+'})')},
+
+yz=f('a','','.003959503758*P(2,(a-128)/12)'),
+$=[
+	f('a','','S(a*6.283184)'),
+	f('a','','(a%1)<.5?1:-1'),
+	f('a','','2*(a%1)-1'),
+	f('a,b','b=(a%1)*4','(b<2)?(b-1):(3-b)')
+],
+
+e=f('a','','f(\'a,b,c\',\'for(var i=a.length;--i>=0;)\'+a,\'a\')'),
+zw=f('a,b,c','c=Math.sqrt(b[0]*b[0]+b[1]*b[1]+b[2]*b[2])','c?$f(a,b,1/c):yf(a,b)'),
+fw=f('a,b,c','','y(a,b[1]*c[2]-b[2]*c[1],b[2]*c[0]-b[0]*c[2],b[0]*c[1]-b[1]*c[0])'),
+y=e('a[i]=arguments[i+1]'),
+yf=e('a[i]=b[i]'),
+_f=e('a[i]=b[i]-c[i]'),
+$f=e('a[i]=b[i]*c'),
+e=f('a','','new Float32Array(a)'),
+
+
+R=f('a,b','','a-b+Math.random()*b*2');
+
+
+
+with(document.body)style.background='black',innerHTML='<canvas id=C1 style=position:fixed;cursor:none></canvas><canvas id=C2 style=display:none>';
+for(i in zx=C1.getContext('webgl'))zx[i.match(/^..|[A-Z]|\d[fi]v?$/g).join('')]=zx[i];
+
+yx='precision highp %;varying !2 zx;',
+w=f('a','','a+(a==(a|0)?\'.\':\'\')'),
+v=f('a','','a.map(w).join(\',\')');
+
+for(h=[[35633,yx+'attribute !2 i;void main(){gl_Position=!4(i,.0,1.),zx=i;}']],zy=[],i=0;i<4;i++)h[i+1]=[35632,f('a,b,c,d,e','b=\'uniform \',d=5,c=yx+b+\'mat3 u0;\'+b+\'sampler2D u1;\'+b+\'!3 u2,u3;\'+b+\'% u4[10];\';for(e in a[15])c+=b+\'!3 u\'+d+++\';\'+b+\'% u\'+d+++\', u\'+d+++\';\';c+=\'const !2 c=!2(1.,-1.)*\'+a[5]+\';% p,z,w,u,o,zy,q,x,a,zz;!2 e,h;!3 l=!3(zx,1.),m,r,s=u2,yx=!3(1.),n=!3(.0),b,v,xxx,xy,d,xx,xz,y;!4 f;% g(% x){return fract(sin(x)*43758.5453);}% yy(!3 x){m=floor(x),y=fract(x),y*=y*(3.-2.*y),z=m.x+m.y*57.+m.z*113.;return mix(mix(mix(g(z),g(z+1.),y.x),mix(g(z+57.),g(z+58.),y.x),y.y),mix(mix(g(z+113.),g(z+114.),y.x),mix(g(z+170.),g(z+171.),y.x),y.y),y.z);}% yyx(!2 x,% a){e=pow(abs(x),!2(a));return pow(e.x+e.y,1./a);}mat2 t(% x){e=!2(cos(x),sin(x));return mat2(-e.x,e.y,e.y,e.x);}% yz(!3 x){return length(mod(x.xy,!2(15.))-!2(7.5))-.5+.05*sin(x.z*9.42477);}!2 k(!3 x,% a){\'+a[14]+\'}void main(){l.y+=mod(u4[4],1.)*2.2;if(l.y>1.){if(l.y<1.2)discard;l.y-=2.2;}l.x*=1.6,r=normalize(l*u0);for(int j=0;j<2;j++){v=r,xxx=s,xy=!3(.0),x=.0,a=\'+a[1]+\';for(int i=0;i<\'+a[4]+\';i++){h=k(s+r*x,x);if(h.x<a||i>\'+a[4]+\'/(j+1)||x>\'+a[0]+\'.)break;x+=h.x*\'+a[3]+\',a*=\'+w(a[2])+\';}h.x=x;if(x<\'+a[0]+\'.){d=s+r*x,f=!4(k(d+c.xyy,x).x,k(d+c.yyx,x).x,k(d+c.yxy,x).x,k(d+c.xxx,x).x),xx=normalize(f.x*c.xyy+f.y*c.yyx+f.z*c.yxy+f.w*c.xxx),a=.0,p=\'+a[12]+\';for(int i=1;i<=\'+a[10]+\';i++)x=(%(i)/\'+a[10]+\'.)*\'+w(a[11])+\',m=d+xx*x,q=max(.1,1.-clamp(pow(a+=p*(x-k(m,distance(m,s)).x),1.),.0,1.)),p*=.5;\';for(e in d=a[13])b=[[[.05],.7,.02,.01],[[.2],.7,.9,.01,5,[.1]],[[1],.5,.4,.02],[[3,0,0],.3,.1,.6,6,[.6,0,0]],[[0,2,0],.9,.5,.4,15,[0,.2,0]],[[3,1.5,0],.95,.6,.9,.3,[.3,.6,0]],[[.1],0,.04,.002,3,[3]],[[0,1.5,2],.9,.3,.4]][d[e]],c+=(e>0?\'else \':\'\')+\'if(h.y==\'+e+\'.)xz=\'+(b[4]?(\'mix(!3(\'+v(b[0])+\'),!3(\'+v(b[5])+\'),yy(d*\'+w(a[6]*b[4])+\'))\'):(\'!3(\'+v(b[0])+\')\'))+\',w=\'+w(b[1])+\',u=\'+b[2]+\',o=\'+b[3]+\';\';d=5,c+=\'v=reflect(r,xx),z=\'+a[9]+\'*h.x,z=clamp(exp(-z*z*z*1.442695),.0,1.),x=clamp((1.+dot(normalize(v+r),r)),.0,1.),a=x*x,zz=o+(1.-o)*x*a*a*(u*.9+.1),y=mix(!3(1.),xz/dot(!3(.299,.587,.114),xz),w),m=!3(.0),zy=exp2(4.+6.*u),\';for(e in b=a[15])c+=\'p=length(b=u\'+d+\'-d),b/=p,p=max(1.,p-u\'+(d+2)+\')*\'+b[e][0]+\',p=1./max(1.,p*p),m+=mix((1.-w)*xz*q,y*pow(max(dot(reflect(r,xx),b),.0),zy)*(zy+2.)/8.,zz)*p*max(dot(b,xx),.0)*!3(u\'+(d+1)+\'),\',d+=3;d=5,c+=\'xy=yx*z*normalize(y)*o*(u*.9+.1)*zz,m=mix(!3(\'+w(a[8])+\'),m,z),xxx+=normalize(v)*\'+a[7]+\';}else m=!3(\'+w(a[8])+\');\';for(e in b=a[15])(a=b[e][1])?c+=\'b=s-u\'+d+\',p=dot(r,r),a=2.*dot(b,r),x=a*a-4.*p*(dot(b,b)-\'+(a*a)+\'),e=x<.0?!2(-1.):(x=sqrt(x),-.5*!2(a+x,a-x)/p),e=!2(min(e.x,e.y),max(e.x,e.y));if(e.x>.0&&e.y<h.x)m+=u\'+(d+2)+\'*!3(u\'+(d+1)+\')*pow((e.y-e.x)/\'+w(a*2)+\',64.);\':0,d+=3','c+=\'n+=m*yx;if(all(lessThan(xy,!3(.01))))break;yx=xy,s=xxx,r=normalize(v);}h=!2(zx.x,l.y)*.5+.5,h.y=(1.-h.y-u4[5])/u4[7],f=texture2D(u1,h),n=max(!3(.0),mix(mix(mix(n,(n.x==n.y&&n.x==n.z)?n:!3(dot(n,!3(.299,.587,.114))),u4[1]),!3(u4[3]),smoothstep(.05,.95,u4[2])),f.rgb*u3,f.a*u4[6])-!3(.004)),x=(l.x+1.)*(l.y+1.)*(u4[0]*10.),gl_FragColor=!4((1.-(smoothstep(.98,1.,yy(l*8.+u4[0]*20.))+smoothstep(.95,1.,yy(l*1.5+u4[0]*10.))))*smoothstep(1.042+.008*cos(u4[0]*40.),.8,yyx(zx,8.))*(1.-(mod((mod(x,13.)+1.)*(mod(x,47.)+1.),.01))*8.)*((.95+.05*cos(u4[0]*41.))*(n*(6.2*n+.5))/(n*(6.2*n+!3(1.7))+!3(.06))+!3(smoothstep(.98,1.,yy(l*8.-u4[0]*40.)))),1.);}\';')(x=[[100,.025,1,.7,64,.0005,.5,.3,.4,.015,4,2,.75,[0,1,2,3],'y=x+.1*(sin(x.zxy*.17+u4[0]*.5)+sin(x.yzx*.7+u4[0]*1.5))*8.5*(1.+cos(sin(x.z*.1)+x.z*.3)),z=14.-length(y.xy),w=x.x==.0?1.570795*(x.y>.0?1.:-1.):atan(x.y,x.x),q=8.35-u4[8]*1.35,y=!3(9.*(mod(w+x.z*.02,.628)-.314),length(x.xy)-9.,mod(x.z,12.56)-6.28),u=min(length(y.xy)-.25+.1*cos(x.z*8.+u4[0]*.1),length(y.yz)-.5),y=!3(q*(mod(w+x.z*.02,1.256636)-.628318),y.y+9.-q,mod(x.z,62.8318)-31.4159),o=step(u,z)+1.,z=min(u,z),u=length(y)-1.3;if(u<z)z=u,o=3.;y.y+=q-9.,u=yyx(y.yz,8.)-2.;if(u<z)z=u,o=.0;return !2(z,o);',[[.25,0],[.5,.5]]],[6,.00025,1.08,.7,100,.000008,10,.03,2.1,.2,6,.4,5.1,[0,2,5],'z=1.,y=x;for(int i=0;i<7;i++)x=2.*clamp(x,-!3(.58,.9,1.1),!3(.58,.9,1.1))-x,w=max((1.3+u4[9]*.1*cos(u4[0]*.5))/dot(x,x),1.),x*=w,z*=w;w=length(x.xy),e=!2(w-3.,-w*x.z/length(x)-2.*log(1.+.01*a))/abs(z),w=max(e.x,e.y),o=step(e.y,e.x),y+=!3(.1,.3,-.4)*u0-u2+.25*sin(x*1.),e.x=length(y)-.1*u4[8];if(e.x<w)w=e.x,o=2.;return !2(w,o);',[[.05]]],[100,.000025,1,.75,80,.00005,.5,.3,3,.01,4,.75,4.75,[6,0,4],'x.xy*=t(a*.009),w=min(min(yz(x.xzy),yz(x)),yz(x.yzx)),y=mod(x,!3(15.))-!3(7.5),o=step(z=max(length(max(abs(y)-!3(2.5),!3(.0)))-.25,3.5-length(y)),w),w=min(w,z),z=length(y+.1*sin(y*5.5+u4[0]))-2.;if(z<w)w=z,o=2.;return !2(w,o);',[[.05]]],[20,.0005,1,.6,128,.0001,.5,.002,.01,.08,4,.5,1.75,[2,7],'y=x,y.xz=mod(x.xz,8.)-4.,y.yz*=t(u4[8]+.1*a),y.xy*=t(u4[8]*.5+.2*a),y.y*=.9+.1*sin(u4[8]*5.),w=max(length(y)-3.,-min(length(y)-2.8,max(mod(y.y,.8)-.4,-mod(y.y+.4,.8)+.4))),z=x.y+1.+sin(x.x*4.+u4[8]*2.)*sin(x.z+u4[8])*.1,o=clamp(.5+.5*(z-w)/1.,.0,1.),w=mix(z,w,o)-1.*o*(1.-o),y=x,y.xz=mod(y.xz,8.)-4.,y/=1.25+.25*sin(u4[8]*5.),y.xy*=t(u4[8]*5.),y.yz*=t(u4[8]*2.5),z=max(length(y)-1.,.04-length(max(abs(mod(y,.5)-.25)-!3(.15),!3(.0))));return !2(min(w,z),step(z,w));',[[.02],[.05,.5],[.05,.5]]]][i])],zy[i]=[5+x[15].length*3,0,i+1];
+
+with(zx) {
+	for(i in h)
+		j=h[i],
+		shS(i=h[i]=crS(j[0]),j[1].replace(/!/g,'vec').replace(/%/g,'float')),
+		coS(i),
+		geSP(i,35713);
+	for(i in zy){
+		w=crP(),m=zy[i],x=m.shift();
+		for(j in m)atS(w,h[m[j]]);
+		liP(w),m=[];
+		for(;x--;)m[x]=geUL(w,'u'+x);
+		zy[i]=[w,m]
+	}
+	biB(i=34962,crB()),buD(i,e([1,4,1,-1,-4,-1]),35044),biT(i=3553,crT())
+	teP(i,j=10240,k=9728),teP(i,++j,k),teP(i,++j,k=33071),teP(i,++j,k),
+	teID(i,0,j=6408,j,5121,C2)
+}
+
+w=f('a,b','','f(\'a\',\'yf(a[0],p),a[1]=\'+a+\',a[2]=\'+b)'),
+v=f('a','','f(\'\',\'x[4]=(\'+(a>0?a:\'\')+\'-xz*\'+a+\'/h[t][6])*R(.875,.125)\')'),
+q=f('a,b,c,d','c=v(c),d=f(\'a,b,c,d\',\'y(p,x[2]=x[8]=0,4,d=f*3),y(s,a,0,d+b),y(n,0,0,1),c()\')','function(){d(a,b,c)}'),
+u=f('a','','f(\'a\',\'y(a[0],\'+a+\'*C(f*2)*5,3,\'+a+\'*S(f*2)*5+f*30),a[1]=1,a[2]=4\')'),
+r=f('a','a=v(a)','function(){r(),a()}'),
+o=f('a','_f(a[0],p,zw(a[0],s)),a[0][1]-=.5,a[1]=3,a[2]=30'),
+m=f('','v(\'Greetings to ... Mog, Sycop, Tim & Wullon ... Adinpsz ... Alcatraz ... ASD ... Bits\\\'n\\\'Bites ... Brain Control ... Cocoon ... Conspiracy ... Ctrl+Alt+Test ... Fairlight ... Farbrausch ... Kewlers ... LNX ... Loonies ... Mercury ... Popsy Team ... Razor 1911 ... RGBA ... 7th Cube ... Still ... TPOLM ... TRBL ... Umlaut Design ... X-Men ... Youth Uprising ... Everyone here at DemoJS 2014!\',yw*(1-(f-h[34][5])/2)),x[5]=1-zf+R(.01,.01),y(fz,x[6]=1,1,1)'),
+g=f('a','','f(\'a,b\',\'b=f-h[\'+a+\'][5],y(a[0],4*S(b*.5)*C(b*.7),3*C(b*1.5),b*30*fx+14+16*S(b*3.3)*C(b*.77)),a[1]=1,a[2]=2\')'),
+
+h = [
+	[
+		36 ,
+		0 ,
+		f('','w(x[2]=1-z*z*z,_=5)') ,
+		a=[w(3,20)]
+	] , [
+		18 ,
+		0 ,
+		f('','w(x[2]=0,_=5-2.25*z)') ,
+		a
+	] , [
+		36 ,
+		0 ,
+		f('','w(x[2]=z,_=2.75-2.25*z)') ,
+		a
+	] , [
+		18 ,
+		3 ,
+		f('a','y(p,0,4,a=f*3),y(s,4,0,a),y(n,0,0,1),x[2]=1-z*z*z,_=2.5') ,
+		[ w(.75,8) ]
+	] , [
+		22 ,
+		3 ,
+		q(4,0,0) ,
+		a=[w(1,8)]
+	] , [
+		22 ,
+		3 ,
+		q(2,-2,0) ,
+		a
+	] , [
+		3 ,
+		3 ,
+		q( 6 , 0 , -.5 ) ,
+		b=[w(.5,4)]
+	] , [
+		9 ,
+		3 ,
+		q( 6 , 0 , .5 ) ,
+		b
+	] , [
+		3 ,
+		3 ,
+		q( 2 , 2 , -.2 ) ,
+		a
+	] , [
+		9 ,
+		3 ,
+		q( 2 , 2 , .2 ) ,
+		a
+	] , [
+		3 ,
+		3 ,
+		q( 2 , 5 , -.7 ) ,
+		a=[ w(1,2) ]
+	] , [
+		7 ,
+		3 ,
+		q( 2 , 2 , .7 ) ,
+		a
+	] , [
+		9 ,
+		3 ,
+		f('a','y(p,0,4+z*2,a=f*3),y(s,2,0,a+2),y(n,0,0,x[3]=1),x[2]=z') ,
+		a
+	] , [
+		21 ,
+		1 ,
+		f('','r(x[2]=1-z*z*z,x[3]=1)'),
+		a=[f('a','yf(a[0],p),a[0][2]+=2,a[1]=1,a[2]=3')]
+	] , [
+		14 ,
+		1 ,
+		r(0) ,
+		a
+	] , [
+		3 ,
+		1 ,
+		r(-.4) ,
+		a
+	] , [
+		9 ,
+		1 ,
+		r(.4) ,
+		a
+	] , [
+		3 ,
+		1 ,
+		r(-.2) ,
+		a
+	] , [
+		9 ,
+		1 ,
+		r(.2) ,
+		a
+	] , [
+		12 ,
+		1 ,
+		f('','r(x[4]=(-(6*z)%1)*R(.875,.125))'),
+		a
+	] , [
+		22 ,
+		1 ,
+		f('','r(x[4]=((30*z)%1)*R(.925,.075),x[2]=z,x[3]=.4),_=3-2.5*M(1,2*z)'),
+		a
+	] , [
+		3 ,
+		1 ,
+		b=f('','r(x[4]=0,x[2]=1)'),
+		a
+	] , [
+		12 ,
+		1 ,
+		b ,
+		a,
+		f('','m(0,.08,1,1,1,1)')
+	] , [
+		12 ,
+		1 ,
+		b ,
+		a,
+		f('','m(0,.08,1-z,1,1,1)')
+	] , [
+		12 ,
+		1 ,
+		b ,
+		a,
+		f('','m(1,.08,1-z,1,1,1)')
+	] , [
+		20 ,
+		2 ,
+		f('','o(x[2]=1-z)') ,
+		b=[w(1,30)],
+		f('','m(2,.04,z,1,1,1)')
+	] , [
+		52 ,
+		2 ,
+		f('','o(x[2]=0)'),
+		b,
+		f('','m(2,.04,1,1,1,1)')
+	] , [
+		12 ,
+		2 ,
+		f('','o(x[2]=1-M(0,z*2),x[3]=1)'),
+		b,
+		f('','m(2,.04,1,1-z,1-z/2,1-z)')
+	] , [
+		12 ,
+		2 ,
+		f('a','o(x[1]=1-z/2,x[4]=(1-z)*.7+R(a=.0125,a))') ,
+		b,
+		f('','m(2,.04,1,0,.5,0)')
+	] , [
+		9 ,
+		2 ,
+		f('','g(29,x[1]=(1-z)/2,x[2]=1-M(0,z*1.5),x[4]+=x[1]*.6)'),
+		b,
+		f('','m(2,.04,1-z,0,.5,0)')
+	] , [
+		69 ,
+		2 ,
+		f('','g(29,x[1]=0)') ,
+		b
+	] , [
+		11 ,
+		2 ,
+		f('','g(29,x[2]=z,x[3]=.2)'),
+		b
+	] , [
+		11 ,
+		0 ,
+		f('','e(32,x[2]=1-z)'),
+		b=[ o ]
+	] , [
+		17 ,
+		0 ,
+		f('','e(32,x[2]=0,x[4]=(1-z)*1.2*R(1,.02))') ,
+		b
+	] , [
+		18 ,
+		0 ,
+		f('','e(32,x[4]=0,x[8]=z)') ,
+		b ,
+		m
+	] , [
+		36 ,
+		0 ,
+		f('','e(32,x[2]=1-N(x[8]=1,4*z))'),
+		b = [ o , g(32) ],
+		m
+	] , [
+		33 ,
+		0 ,
+		f('','e(32,x[2]=z,x[3]=.7,x[4]=-((4*z)%1)*R(1,.05))'),
+		b ,
+		m
+	] , [
+		9 ,
+		1 ,
+		f('','u(x[4]=0,x[2]=z,x[3]=1)'),
+		a,
+		m
+	] , [
+		20 ,
+		1 ,
+		f('','u(z,x[2]=0)'),
+		a,
+		m
+	] , [
+		31 ,
+		1 ,
+		f('','u(1,x[2]=1-N(1,5*z))'),
+		a,
+		m
+	] , [
+		5 ,
+		1 ,
+		f('','u(1,x[2]=1-z)'),
+		a,
+		m
+	] , [
+		18 ,
+		1 ,
+		f('','u(1,x[2]=1-N(1,5*z),x[4]=M(0,1.6*z-.8)*R(1,.05))'),
+		a,
+		m
+	] , [
+		12 ,
+		1 ,
+		f('','u(1,x[2]=z,x[4]=(1-z)*.8*R(1,.05),x[3]=.1)'),
+		a,
+		m
+	] , [
+		22 ,
+		3 ,
+		f('','q(x[2]=1-z,x[4]=0)'),
+		a = [ w(.6,30) , u(1),u(-1) ],
+		m
+	] , [
+		59 ,
+		3 ,
+		f('','q(x[2]=1-N(1,(12*z)%4),x[3]=.8)'),
+		a,
+		m
+	] , [
+		8 ,
+		3 ,
+		f('','q(x[2]=z,x[4]=R(0,x[3]=.1))'),
+		a
+	] , [
+		7 ,
+		0 ,
+		f('','x[fx=2]=1-z,e(46,x[4]=R(0,.1),x[8]=1)'),
+		a = [ o , g(46) ]
+	] , [
+		22 ,
+		0 ,
+		f('','e(46,x[4]=R(0,.1))'),
+		a
+	] , [
+		10 ,
+		0 ,
+		f('','e(46,x[4]=R(0,.1+z*.4)+xz*4,x[2]=z,x[3]=1)'),
+		a
+	] , [
+		10 ,
+		2 ,
+		f('','g(49,x[2]=1-z),x[4]=R(0,.5)+(f-h[48][5])*4'),
+		a=[ w(1,30) ]
+	] , [
+		40 ,
+		2 ,
+		f('','g(49),x[4]=R(0,.5)-(f-h[48][5])*6'),
+		a
+	] , [
+		40 ,
+		2 ,
+		f('','g(49),x[4]=R(x[3]=0,.5)+(f-h[48][5])*8,x[2]=z'),
+		a
+	] , [
+		68 ,
+		2 ,
+		f('','g(49,x[2]=1)'),
+		a
+	]
+],
+
+fx=1,
+x = e(10) , p = e(3),s=e(3),n=e(3),fz=e(3),xw= [[e(3),0,0],[e(3),0,0],[e(3),0,0]],
+ff=e(3),fy=e(3),yy=e(3),xf=e(9),
+mCurrentCol=zz=0,_=new Int32Array(xz=10717272);
+
+w=f('a','y(p,-6,0,a=f*6),y(s,x[1]=1,x[8]=0,a),y(n,0,1,0)'),
+q=f('a','a=f*5,y(p,C(f)*12,8,S(f)*12+a),y(s,1,0,a),y(n,0,1,0),_=2.5,x[8]=f-h[43][5]'),
+r=f('','y(p,4,2.5+.025*f,6.7),y(s,x[8]=x[9]=0,2.5-.05*f,6.7),y(n,0,0,1),_=3'),
+u=f('a,b','y(p,5*S(b=f*.2),9*C(f*.41),7.8),y(s,C(b),S(f*.33),p[2]-2),y(n,0,0,x[9]=1),x[8]=a,_=3'),
+v=f('a,b,c','with(yx)shadowBlur=ww/5,fillText(a,b,c=ww/2),shadowBlur=0,strokeText(a,b,c)'),
+m=f('a,b,c,d,e,f','v([\'TheT(ourist)\',\'presents\',\'Sine City\'][a],yw/15),x[5]=1-zf+R(0,b),x[6]=c,y(fz,d,e,f)'),
+o=f('a,b','a=f-h[25][5],y(p,b=a*10-80,0,0),y(s,b+C(a*.5)*80,S(a*.25)*40,100),y(n,0,_=2.5,0)'),
+g=f('a,b','a=f-h[a][5],y(p,0,0,b=a*20-80),y(s,C(a*.5)*80,S(a*.25)*40,100+b),y(n,0,1,0),x[4]=R(a=.0125,a)'),
+e=f('a','a=(f-h[a][5])*30*fx,y(p,1.1*C(a*.1),S(a*.02),a),a+=5,y(s,-S(a*.05),-.7*C(a*.033),a),y(n,0,_=2,0)'),
+
+mainfunc = function(){setTimeout(function(){
+requestAnimationFrame(draw=function(a){
+	requestAnimationFrame(draw);
+	zz?0:(A.currentTime=0,A.play(),zz=a,$=zz-33);
+	yz = a - $;
+	f = .001*(a - zz);
+	if ( yz < 33 ) {
+		return;
+	}
+	$ = a - ( yz % 33 );
+
+	j = h[t];
+	while ( j && j[7] < f ) {
+		j=h[++t];
+	}
+	if ( ! j ) {
+		A.pause( );
+		return;
+	}
+	x[0] = f;
+	x[7] = zf;
+	xz = f - j[5];
+	z = xz / j[6];
+	with (zx) {
+		j[4]?(yx.clearRect(0,0,yw,100),teID(3553,j[4](),k=6408,k,5121,C2)):0,j[2](),zw(yy,_f(yy,s,p)),zw(ff,fw(ff,n,yy)),zw(fy,fw(fy,yy,ff)),$f(yy,yy,_);
+		for(i=0;i<3;i++)xf[i*3]=ff[i],xf[i*3+1]=fy[i],xf[i*3+2]=yy[i];
+		for(i in j[3])j[3][i](xw[i]);
+
+		f=zy[j[1]],usP(f[k=0]),f=f[1],veAP(enVAA(unM3fv(f[k++],un1i(f[k++],un3fv(f[k++],p)),xf)),2,5126,un3fv(f[k++],fz),8,un1fv(f[k++],x));
+		for(i in j[3])un3fv(f[k++],xw[i][0]),un1f(f[k++],xw[i][1]),un1f(f[k++],xw[i][2]);
+		drA(4,0,3)
+	}
+})
+},500)};
+
+for(t=i=0;i<53;i++)h[i][5]=t,t+=(h[i][6]=h[i][0]/8),h[i][7]=t;
+t=0,
+yx = C2.getContext('2d');
+(onresize=f('a,b,c,d,e','with(yx)a=innerWidth,b=innerHeight,c=(b*1.6)|0,d=(a*.625)|0,zx.vi(0,0,C2.style.width=C2.width=C1.width=yw=c>a?a:c,C1.height=e=c>a?d:b),ww=C2.style.height=C2.height=M(e/8,100),zf=ww/e,C1.style.left=((a-yw)/2)|0,C1.style.top=((b-e)/2)|0,shadowColor=\'#ccc\',font=\'normal small-caps bold \'+((ww/2)|0)+\'px monospace\',fillStyle=\'#111\',strokeStyle=\'#ddd\''))();
+
+if ( USE_SYNTH ) {
+	synthGen = setInterval(function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,u,v,w){
+		for(d=new Int32Array(xz),f=[[[0,198,128,0,3,192,128,1,0,0,96,128,28,0,0,0,0,2,63,61,13,16,44,8,0,0],[1,2,3,4,5,2,3,4,6,7,1,2,3,4,5,2,3,4,5,2,3,4,1,2,3,8,9],[[[115,,,,,,,,,,,,117,,,,,,,,,,,,113],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[115,,,,,,,,,,,,,,,110],[12,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,148]],[[115,,,,,,,,,,,,117,,,,,,,,,,,,118],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[122,,,,,,,,,,,,,,,123,,,,,115],[12,,,,,,,,,,,,,,,12,,,,,12,,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,8,,,,,128]],[[118,,,,,,,,,,,,117,,,,,,,,,,,,113],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[115],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,255]],[[,,,,,,,,,,,,,,,,118,118,118],[,,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,128]],[[122,,,,,,,,,,,,,,,123,,,,,115],[12,,,,,,,,,,,,,,,12,,,,,13,12,,,,,,,,,,,,,,,115,,,,,,,,,,,,,,,8,,,,,95,61]],[[],[]]]],[[0,255,116,1,0,255,101,0,0,15,1,4,45,0,13,6,1,2,62,27,60,48,0,0,44,2],[,1,,2,,1,,2,,3,4,4,5,4,5,4,5,4,5,4,5,4,5,4,3,6],[[[,,,,,139,,,139,139,,,,,,139,,,,,,,,139,,,139,139,,,,,139,139,139],[]],[[,,139,139,,,,,139,139,,,,,139,139,,,,,,,,,,139,139,139,,,,,139,139,139],[]],[[,,,139,,,,,139,139,,,,,,139,,,,,139,139,,,,,,139,,,,139,139,139],[]],[[139,,,,139,,139,,,139,,,139,,,,139,,139,,,139,,,139,,,,139,,139,,,139],[]],[[139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139],[]],[[139,,,139,139,,139,,,139,,,139,,,139,139,,139,,,139,139],[]]]],[[0,0,140,0,0,0,140,0,0,128,4,10,34,0,187,5,0,1,239,135,34,19,108,8,8,4],[,,1,,1,,3,,1,3,2,2,2,2,2,3,2,3,2,3,2,3,2,3,1],[[[,,,,,,,,,,127,,,,,,,,,,,,127,,,,,,,,,,,,127],[]],[[,,,139,,,,,,139,139,,,,,139,,,,,,139,139,,,,,139,,,,,139,,139],[]],[[,,127,,,,,,,,127,,,,127,,,,,,,,127,,,,127,,,,,,,,127],[]]]],[[1,192,128,0,3,201,128,0,0,93,5,6,58,3,195,6,1,3,35,63,14,17,11,10,61,6],[,,,,1,2,3,4,5,6,7,5,8,9,10,11,8,9,10,11,12,13,14,15,16],[[[,,,,,,,,147,146,145,,,,,,,,,,145,147,146,,,,,,,,,,149,148,147],[]],[[,,,,,,151,151,151,,,,,,,146,142,138,,,,,,,,,,,,,,,147,150,147],[]],[[,,146,,,146,,,,,,,,,147,146,145,,,,,,,,,,146,145,142,,,142,,,142],[]],[[,,141,,,,,,,,,,,,141,140,139,,,146,,,146,,,127],[]],[[,139,,151,,,,,,,,,,151,,139,,,,,,,,,,139,,151],[]],[[,139,,151,150,149,,,,,,,,139,,149,148,147,,,,,,,,139,,,146,,,145,,,144],[]],[[,139,,,139,142,,,142,144,146,,144,,,,146,147,,,147,146,141,,137,,,,142,141,,141,,137],[]],[[139,,127,,142,,,130,,,144,142,141,,129,,141,,,144,,,141,144,142,,,,149,,,146,,,151],[]],[[,149,,149,,146,144,142,,,141,,142,,,139,,,,151,147,,,,146,147,,144,146,,142,144,141,146],[]],[[,,,,,,,,147,146,145,,,,,141,144,147,146,,144,,137,,,144,146,142,144,,,142,144,141,146],[]],[[,146,,151,,146,,,,144,142,144,146,,,,142,,,,,139,,,,,151,146,139,144,139,142,141,142,151],[]],[[,,147,,,149,146,,,142,,142,141,,,144,,144,,,144,146,142,144,142,,,,151,150,149,,137,,149],[]],[[,151,,,147,151,,,146,151,,,,,144,151,,149,147,149,151,,146,,,144,143,142,,,139,,151,139],[]],[[,,134,,,134,,,134,,,146,144,,,141,144,,,146,147,146,,,144,,139,140,141,,,153,,,141],[]],[[,142,,151,,,142,143,144,,,,151,,,139,,,137,,149,,137,,,,125,,,141,142,141,,,146],[]],[[139,,127,139,,127,139,,127,139,127],[]]]],[[2,160,128,1,0,160,128,0,1,60,4,7,41,0,60,4,1,3,14,0,35,32,31,12,89,1],[,,,,,,,,,,,,1,2,1,2,1,2,1,2,1,2,1,2,1,3],[[[,,139,,,,,,,,,,,,139,,,,,,,,,,,,139,,,,,139,139,,,139],[]],[[,,139,,,151,,,139,,,151,,,139,,,151,,,139,,,151,,,139,,,151,,,146,146,146,146],[]],[[,,139,,,151,,,139,,,151,,,139,,139,139,139,139,127],[]]]],[[2,100,128,0,3,201,128,0,0,0,0,6,29,0,195,6,1,3,28,229,119,77,147,6,61,2],[,,,,,,,,,6,1,2,3,4,5,2,3,4,1,2,3,4,1,2,3,7],[[[115,115,115,115,115,115,115,115,115,115,115,115,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],[]],[[115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110],[]],[[115,115,115,115,115,115,115,115,115,115,115,115,117,117,117,117,117,117,117,117,117,117,117,117,118,118,118,118,118,118,118,118,118,118,118,118],[]],[[110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115],[]],[[118,118,118,118,118,118,118,118,118,118,118,118,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],[]],[[,,,,,,,,,,,,,,,,,,130,,130,,130,,130,,130,,130,118,130,118,130,118,130,118],[,,,,,,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2]],[[110,122,,122,134,,110,122,,122,134,,110,122,,111,123,,111,123,115,127,139,127,115],[,,,,,,,,,,,,,,,,,,,,26,25,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,147]]]],[[2,100,128,0,3,201,128,0,0,0,5,6,58,0,195,6,1,2,135,0,0,32,147,6,121,6],[],[]],[[2,100,128,0,3,201,128,0,0,0,5,6,58,0,195,6,1,2,135,0,0,32,147,6,121,6],[],[]]][t],o=[],g=h=m=p=0;p<=26;p++)for(b=f[1][p],a=0;a<36;a++){((e=b?f[2][b-1][1][a]:0)?((f[0][e-1]=f[2][b-1][1][a+36]||0),e<14?(o=[]):0):0),c=(p*36+a)*5513;for(j=0;j<4;j++)if(n=b?f[2][b-1][0][a+j*36]:0){if(!o[n])for(q=f[0][10],r=f[0][11],s=f[0][12],w=yz(n+f[0][2]-128),l=yz(n+f[0][6]-128)*(1+.0008*f[0][7]),u=v=0,q*=q*4,r*=r*4,s*=s*4,o[n]=new Int32Array(q+r+s),k=0;k<q+r+s;k++)e=k<q?(k/q):(1-(k<q+r?0:((k-q-r)/s))),o[n][k]=(80*($[f[0][0]](u+=w*(f[0][3]?(e*e):1))*f[0][1]+$[f[0][4]](v+=l*(f[0][8]?(e*e):1))*f[0][5]+R(0,1)*f[0][9])*e)|0;for(k=0,i=c*2;k<o[n].length;k++,i+=2)d[i]+=o[n][k]}q=f[0][20]*1e-5,r=f[0][24]/255,s=f[0][25]*5513;for(j=0;j<5513;j++)(((n=e=d[k=(c+j)*2])||m)?(w=1.5*S(f[0][18]*.00307999186353015873*(f[0][16]?($[f[0][13]](P(2,f[0][15]-9)*k/5513)*f[0][14]/512+.5):1)),g+=w*h,l=(1-f[0][19]/255)*(e-h)-g,h+=w*l,e=f[0][17]==3?h:f[0][17]==1?l:g,q?(e*=q,e=(e<1?e>-1?$[0](e*.25):-1:1)/q):0,e*=f[0][21]/32,m=e*e>1e-5,w=S(6.283184*P(2,f[0][23]-9)*k/5513)*f[0][22]/512+.5,n=e*(1-w),e*=w):0),(k>=s?(n+=d[k-s+1]*r,e+=d[k-s]*r):0),_[k]+=(d[k]=n|0),_[k+1]+=(d[k+1]=e|0)}
+		if(++t==8)for(clearInterval(synthGen),s=(f=String.fromCharCode).apply(String,[82,73,70,70,168,16,71,1,87,65,86,69,102,109,116,32,16,0,0,0,1,0,2,0,68,172,0,0,16,177,2,0,4,0,16,0,100,97,116,97,132,16,71,1]),t=i=0;i<xz||(((A=document.createElement('audio')).src='data:audio/wav;base64,'+btoa(s),A.oncanplaythrough=mainfunc)&&0);i++)e=_[i],e=e<-32767?-32767:(e>32767?32767:e),s+=f(e&255,(e>>8)&255)
+	}, 0);
+} else {
+	A = document.createElement("audio");
+	A.oncanplaythrough=mainfunc;
+	A.src= 'music.ogg';
+}
diff --git a/201410_-_Sine_City/sine-city-packing-8-finalize.html b/201410_-_Sine_City/sine-city-packing-8-finalize.html
new file mode 100644
index 0000000..1f232fd
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-8-finalize.html
@@ -0,0 +1,3 @@
+<body>
+<script language="javascript" src="sine-city-packing-8-finalize.js"></script>
+
diff --git a/201410_-_Sine_City/sine-city-packing-8-finalize.js b/201410_-_Sine_City/sine-city-packing-8-finalize.js
new file mode 100644
index 0000000..e0326c4
--- /dev/null
+++ b/201410_-_Sine_City/sine-city-packing-8-finalize.js
@@ -0,0 +1,80 @@
+f=function(a,b,c){return eval('(function('+a+'){'+b+(b?';':'')+(c?('return '+c):'')+'})')},
+
+yz=f('a','','.003959503758*P(2,(a-128)/12)'),$=[f('a','','S(a*6.283184)'),f('a','','(a%1)<.5?1:-1'),f('a','','2*(a%1)-1'),f('a,b','b=(a%1)*4','(b<2)?(b-1):(3-b)')],e=f('a','','f(\'a,b,c\',\'for(var i=a.length;--i>=0;)\'+a,\'a\')'),zw=f('a,b,c','c=Math.sqrt(b[0]*b[0]+b[1]*b[1]+b[2]*b[2])','c?$f(a,b,1/c):yf(a,b)'),fw=f('a,b,c','','y(a,b[1]*c[2]-b[2]*c[1],b[2]*c[0]-b[0]*c[2],b[0]*c[1]-b[1]*c[0])'),y=e('a[i]=arguments[i+1]'),yf=e('a[i]=b[i]'),_f=e('a[i]=b[i]-c[i]'),$f=e('a[i]=b[i]*c'),e=f('a','','new Float32Array(a)'),R=f('a,b','','a-b+Math.random()*b*2');
+
+with(Math)S=sin,C=cos,M=max,N=min,P=pow;with(document.body)style.background='black',innerHTML='<canvas id=C1 style=position:fixed;cursor:none></canvas><canvas id=C2 style=display:none>';for(i in zx=C1.getContext('webgl'))zx[i.match(/^..|[A-Z]|\d[fi]v?$/g).join('')]=zx[i];yx='precision highp float;varying vec2 zx;',w=f('a','','a+(a==(a|0)?\'.\':\'\')'),v=f('a','','a.map(w).join(\',\')');
+
+for(h=[[35633,yx+'attribute vec2 i;void main(){gl_Position=vec4(i,.0,1.),zx=i;}']],zy=[],i=0;i<4;i++)h[i+1]=[35632,f('a,b,c,d,e','b=\'uniform \',d=5,c=yx+b+\'mat3 u0;\'+b+\'sampler2D u1;\'+b+\'vec3 u2,u3;\'+b+\'float u4[10];\';for(e in a[15])c+=b+\'vec3 u\'+d+++\';\'+b+\'float u\'+d+++\', u\'+d+++\';\';c+=\'const vec2 c=vec2(1.,-1.)*\'+a[5]+\';float p,z,w,u,o,zy,q,x,a,zz;vec2 e,h;vec3 l=vec3(zx,1.),m,r,s=u2,yx=vec3(1.),n=vec3(.0),b,v,xxx,xy,d,xx,xz,y;vec4 f;float g(float x){return fract(sin(x)*43758.5453);}float yy(vec3 x){vec3 m=floor(x),y=fract(x);y*=y*(3.-2.*y);float z=m.x+m.y*57.+m.z*113.;return mix(mix(mix(g(z),g(z+1.),y.x),mix(g(z+57.),g(z+58.),y.x),y.y),mix(mix(g(z+113.),g(z+114.),y.x),mix(g(z+170.),g(z+171.),y.x),y.y),y.z);}float yyx(vec2 x,float a){e=pow(abs(x),vec2(a));return pow(e.x+e.y,1./a);}mat2 t(float x){e=vec2(cos(x),sin(x));return mat2(-e.x,e.y,e.y,e.x);}float yz(vec3 x){return length(mod(x.xy,vec2(15.))-vec2(7.5))-.5+.05*sin(x.z*9.42477);}vec2 k(vec3 x,float a){\'+a[14]+\'}void main(){l.y+=mod(u4[4],1.)*2.2;if(l.y>1.){if(l.y<1.2)discard;l.y-=2.2;}l.x*=1.6,r=normalize(l*u0);for(int j=0;j<2;j++){v=r,xxx=s,xy=vec3(.0),x=.0,a=\'+a[1]+\';for(int i=0;i<\'+a[4]+\';i++){h=k(s+r*x,x);if(h.x<a||i>\'+a[4]+\'/(j+1)||x>\'+a[0]+\'.)break;x+=h.x*\'+a[3]+\',a*=\'+w(a[2])+\';}h.x=x;if(x<\'+a[0]+\'.){d=s+r*x,f=vec4(k(d+c.xyy,x).x,k(d+c.yyx,x).x,k(d+c.yxy,x).x,k(d+c.xxx,x).x),xx=normalize(f.x*c.xyy+f.y*c.yyx+f.z*c.yxy+f.w*c.xxx),a=.0,p=\'+a[12]+\';for(int i=1;i<=\'+a[10]+\';i++)x=(float(i)/\'+a[10]+\'.)*\'+w(a[11])+\',m=d+xx*x,q=max(.1,1.-clamp(pow(a+=p*(x-k(m,distance(m,s)).x),1.),.0,1.)),p*=.5;\';for(e in d=a[13])b=[[[.05],.7,.02,.01],[[.2],.7,.9,.01,5,[.1]],[[1],.5,.4,.02],[[2,0,0],.3,.1,.6,5,[.1,0,0]],[[0,2,0],.7,.9,.8,15,[0,.2,0]],[[3,1.5,0],.95,.6,.9,.3,[.3,.6,0]],[[.1],0,.04,.002,3,[3]],[[0,1.5,2],.5,.5,.7]][d[e]],c+=(e>0?\'else \':\'\')+\'if(h.y==\'+e+\'.)xz=\'+(b[4]?(\'mix(vec3(\'+v(b[0])+\'),vec3(\'+v(b[5])+\'),yy(d*\'+w(a[6]*b[4])+\'))\'):(\'vec3(\'+v(b[0])+\')\'))+\',w=\'+w(b[1])+\',u=\'+b[2]+\',o=\'+b[3]+\';\';d=5,c+=\'v=reflect(r,xx),z=\'+a[9]+\'*h.x,z=clamp(exp(-z*z*z*1.442695),.0,1.),x=clamp((1.+dot(normalize(v+r),r)),.0,1.),a=x*x,zz=o+(1.-o)*x*a*a*(u*.9+.1),y=mix(vec3(1.),xz/dot(vec3(.299,.587,.114),xz),w),m=vec3(.0),zy=exp2(4.+6.*u),\';for(e in b=a[15])c+=\'p=length(b=u\'+d+\'-d),b/=p,p=max(1.,p-u\'+(d+2)+\')*\'+b[e][0]+\',p=1./max(1.,p*p),m+=mix((1.-w)*xz*q,y*pow(max(dot(reflect(r,xx),b),.0),zy)*(zy+2.)/8.,zz)*p*max(dot(b,xx),.0)*vec3(u\'+(d+1)+\'),\',d+=3;d=5,c+=\'xy=yx*z*normalize(y)*o*(u*.9+.1)*zz,m=mix(vec3(\'+w(a[8])+\'),m,z),xxx+=normalize(v)*\'+a[7]+\';}else m=vec3(\'+w(a[8])+\');\';for(e in b=a[15])(j=b[e][1])?c+=\'b=s-u\'+d+\',p=dot(r,r),a=2.*dot(b,r),x=a*a-4.*p*(dot(b,b)-\'+(j*j)+\'),e=x>.0?(x=sqrt(x),-.5*vec2(a+x,a-x)/p):vec2(-1.),e=vec2(min(e.x,e.y),max(e.x,e.y));if(e.x>.0&&e.y<h.x)z=\'+a[9]+\'*e.x,m+=clamp(exp(-z*z*z*1.442695),.0,1.)*u\'+(d+2)+\'*vec3(u\'+(d+1)+\')*pow((e.y-e.x)/\'+w(j*2)+\',64.)*yy((u2+r*e.x)*3.);\':0,d+=3','c+=\'n+=m*yx;if(all(lessThan(xy,vec3(.01))))break;yx=xy,s=xxx,r=normalize(v);}h=vec2(zx.x,l.y)*.5+.5,h.y=(1.-h.y-u4[5])/u4[7],f=texture2D(u1,h),n=max(vec3(.0),mix(mix(mix(n,(n.x==n.y&&n.x==n.z)?n:vec3(dot(n,vec3(.299,.587,.114))),u4[1]),vec3(u4[3]),smoothstep(.05,.95,u4[2])),f.rgb*u3,f.a*u4[6])-vec3(.004)),x=(l.x+1.)*(l.y+1.)*(u4[0]*10.),gl_FragColor=vec4((1.-(smoothstep(.98,1.,yy(l*8.+u4[0]*20.))+smoothstep(.95,1.,yy(l*1.5+u4[0]*10.))))*smoothstep(1.042+.008*cos(u4[0]*40.),.8,yyx(zx,8.))*(1.-(mod((mod(x,13.)+1.)*(mod(x,47.)+1.),.01))*8.)*((.95+.05*cos(u4[0]*41.))*(n*(6.2*n+.5))/(n*(6.2*n+vec3(1.7))+vec3(.06))+vec3(smoothstep(.98,1.,yy(l*8.-u4[0]*40.)))),1.);}\';')(x=[[100,.025,1,.7,64,.0005,.5,.3,.4,.015,4,2,.75,[0,1,2,3],'y=x+.1*(sin(x.zxy*.17+u4[0]*.5)+sin(x.yzx*.7+u4[0]*1.5))*8.5*(1.+cos(sin(x.z*.1)+x.z*.3)),z=14.-length(y.xy),w=x.x==.0?1.570795*(x.y>.0?1.:-1.):atan(x.y,x.x),q=8.35-u4[8]*1.35,y=vec3(9.*(mod(w+x.z*.02,.628)-.314),length(x.xy)-9.,mod(x.z,12.56)-6.28),u=min(length(y.xy)-.25+.1*cos(x.z*8.+u4[0]*.1),length(y.yz)-.5),y=vec3(q*(mod(w+x.z*.02,1.256636)-.628318),y.y+9.-q,mod(x.z,62.8318)-31.4159),o=step(u,z)+1.,z=min(u,z),u=length(y)-1.3;if(u<z)z=u,o=3.;y.y+=q-9.,u=yyx(y.yz,8.)-2.;if(u<z)z=u,o=.0;return vec2(z,o);',[[.25,0],[.1,2.1]]],[6,.000125,1.08,.7,100,.000008,10,.03,2.1,.2,6,.4,5.1,[0,2,5],'z=1.,y=x;for(int i=0;i<7;i++)x=2.*clamp(x,-vec3(.58,.9,1.1),vec3(.58,.9,1.1))-x,w=max((1.3+u4[9]*.1*cos(u4[0]*.5))/dot(x,x),1.),x*=w,z*=w;w=length(x.xy),e=vec2(w-3.,-w*x.z/length(x)-2.*log(1.+.01*a))/abs(z),w=max(e.x,e.y),o=step(e.y,e.x),y+=vec3(.1,.3,-.4)*u0-u2+.25*sin(x*1.),e.x=length(y)-.1*u4[8];if(e.x<w)w=e.x,o=2.;return vec2(w,o);',[[.05]]],[100,.000025,1,.75,80,.0005,.5,.3,3,.01,4,.75,4.75,[6,0,4],'x.xy*=t(a*.009),w=min(min(yz(x.xzy),yz(x)),yz(x.yzx)),y=mod(x,vec3(15.))-vec3(7.5),o=step(z=max(length(max(abs(y)-vec3(2.5),vec3(.0)))-.25,3.5-length(y)),w),w=min(w,z),z=length(y+.1*sin(y*5.5+u4[0]))-2.;if(z<w)w=z,o=2.;return vec2(w,o);',[[.05]]],[20,.0005,1,.6,128,.0001,.5,.002,.01,.08,4,.5,1.75,[2,7],'y=x,y.xz=mod(x.xz,8.)-4.,y.yz*=t(u4[8]+.1*a),y.xy*=t(u4[8]*.5+.2*a),y.y*=.9+.1*sin(u4[8]*5.),w=max(length(y)-3.,-min(length(y)-2.8,max(mod(y.y,.8)-.4,-mod(y.y+.4,.8)+.4))),z=x.y+1.+sin(x.x*4.+u4[8]*2.)*sin(x.z+u4[8])*.1,o=clamp(.5+.5*(z-w)/1.,.0,1.),w=mix(z,w,o)-1.*o*(1.-o),y=x,y.xz=mod(y.xz,8.)-4.,y/=1.25+.25*sin(u4[8]*5.),y.xy*=t(u4[8]*5.),y.yz*=t(u4[8]*2.5),z=max(length(y)-1.,.04-length(max(abs(mod(y,.5)-.25)-vec3(.15),vec3(.0))));return vec2(min(w,z),step(z,w));',[[.02],[.05,1.5],[.05,1.5]]]][i])],zy[i]=[5+x[15].length*3,0,i+1];
+
+with(zx){for(i in h)j=h[i],shS(i=h[i]=crS(j[0]),j[1]),coS(i),geSP(i,35713);for(i in zy){w=crP(),m=zy[i],x=m.shift();for(j in m)atS(w,h[m[j]]);liP(w),m=[];for(;x--;)m[x]=geUL(w,'u'+x);zy[i]=[w,m]}biB(i=34962,crB()),buD(i,e([1,4,1,-1,-4,-1]),35044),biT(i=3553,crT()),teP(i,j=10240,k=9728),teP(i,++j,k),teP(i,++j,k=33071),teP(i,++j,k),teID(i,0,j=6408,j,5121,C2)}
+
+w=f('a,b','','f(\'a\',\'yf(a[0],p),a[1]=\'+a+\',a[2]=\'+b)'),v=f('a','','f(\'\',\'x[4]=(\'+(a>0?a:\'\')+\'-xz*\'+a+\'/h[t][6])*R(.875,.125)\')'),q=f('a,b,c,d','c=v(c),d=f(\'a,b,c,d\',\'y(p,x[2]=x[8]=0,4,d=f*3),y(s,a,0,d+b),y(n,0,0,1),c()\')','function(){d(a,b,c)}'),u=f('a','','f(\'a\',\'y(a[0],\'+a+\'*C(\'+a+\'*f*2)*5,4.25,\'+a+\'*S(\'+a+\'*f*2.5)*5+D(44)*10),a[1]=1.5+S(f+\'+a+\'),a[2]=8+2*S(f+\'+a+\')\')'),r=f('a','a=v(a)','function(){r(),a()}'),o=f('a','_f(a[0],p,zw(a[0],s)),a[0][1]-=.5,a[1]=3,a[2]=30'),m=f('','v(\'Greetings to ... Mog, Sycop, Tim & Wullon ... Adinpsz ... Alcatraz ... ASD ... Bits\\\'n\\\'Bites ... Brain Control ... Cocoon ... Conspiracy ... Ctrl+Alt+Test ... Fairlight ... Farbrausch ... Kewlers ... LNX ... Loonies ... Mercury ... Popsy Team ... Razor 1911 ... RGBA ... 7th Cube ... Still ... TPOLM ... TRBL ... Umlaut Design ... X-Men ... Youth Uprising ... Everyone here at DemoJS 2014!\',yw*(1-D(35)/3)),x[5]=1-zf+R(.01,.01),y(fz,x[6]=1,1,1)'),g=f('a','','f(\'a,b\',\'b=D(\'+a+\'),y(a[0],4*S(b*.5)*C(b*.7),3*C(b*1.5),b*30*fx+14+16*S(b*3.3)*C(b*.77)),a[1]=3+3*(f%1),a[2]=16\')'),
+
+h = [
+	[ 36 , 0 , f('','w(x[2]=1-z*z*z,_=5)') , a=[w(3,20)] ],
+	[ 18 , 0 , f('','w(x[2]=0,_=5-2.25*z)') , a ],
+	[ 36 , 0 , f('','w(x[2]=z,_=2.75-2.25*z)') , a ],
+	[ 18 , 3 , f('a','y(p,0,4,a=f*3),y(s,4,0,a),y(n,0,0,1),x[2]=1-z*z*z,_=2.5') , [ w(.75,8) ] ],
+	[ 22 , 3 , q(4,0,0) , a=[w(1,8)] ],
+	[ 22 , 3 , q(2,-2,0) , a ],
+	[ 3 , 3 , q( 6 , 0 , -.5 ) , b=[w(.5,4)] ],
+	[ 9 , 3 , q( 6 , 0 , .5 ) , b ],
+	[ 3 , 3 , q( 2 , 2 , -.2 ) , a ],
+	[ 9 , 3 , q( 2 , 2 , .2 ) , a ],
+	[ 3 , 3 , q( 2 , 5 , -.7 ) , a=[ w(1,2) ] ],
+	[ 7 , 3 , q( 2 , 5 , .7 ) , a ],
+	[ 9 , 3 , f('a','y(p,0,4+z*8,a=f*3),y(s,2,0,a+5),y(n,0,0,x[3]=1),x[2]=z') , a ],
+	[ 23 , 1 , f('','r(x[2]=1-z*z*z,x[3]=1)'), a=[f('a','yf(a[0],p),a[0][2]+=2,a[1]=1,a[2]=3')] ],
+	[ 3 , 1 , r(-.9) , a ],
+	[ 9 , 1 , r(.9) , a ],
+	[ 3 , 1 , r(-.3) , a ],
+	[ 9 , 1 , r(.3) , a ],
+	[ 3 , 1 , r(-.6) , a ],
+	[ 9 , 1 , r(.6) , a ],
+	[ 12 , 1 , f('','r(x[4]=(-(6*z)%1)*R(.875,.125))'), a ],
+	[ 22 , 1 , f('','r(x[4]=((30*z)%1)*R(.925,.075),x[2]=z,x[3]=.4),_=3-2.5*M(1,2*z)'), a ],
+	[ 3 , 1 , b=f('','r(x[4]=0,x[2]=1)'), a ],
+	[ 12 , 1 , b , a, f('','m(0,.08,1,1,1,1)') ],
+	[ 12 , 1 , b , a, f('','m(0,.08,1-z,1,1,1)') ],
+	[ 12 , 1 , b , a, f('','m(1,.08,1-z,1,1,1)') ],
+	[ 20 , 2 , f('','o(x[2]=1-z)') , b=[w(1,30)], f('','m(2,.04,z,1,1,1)') ],
+	[ 52 , 2 , f('','o(x[2]=0)'), b, f('','m(2,.04,1,1,1,1)') ],
+	[ 12 , 2 , f('','o(x[2]=1-M(0,z*2),x[3]=1)'), b, f('','m(2,.04,1,1-z,1-z/2,1-z)') ],
+	[ 12 , 2 , f('a','o(x[1]=1-z/2,x[4]=(1-z)*.7+R(a=.0125,a))') , b, f('','m(2,.04,1,0,.5,0)') ],
+	[ 9 , 2 , f('','g(30,x[1]=(1-z)/2,x[2]=1-M(0,z*1.5),x[4]+=x[1]*.6)'), b, f('','m(2,.04,1-z,0,.5,0)') ],
+	[ 69 , 2 , f('','g(30,x[1]=0)') , b ],
+	[ 11 , 2 , f('','g(30,x[2]=z,x[3]=.2)'), b ],
+	[ 11 , 0 , f('','e(33,x[2]=1-z)'), b=[ o ] ],
+	[ 17 , 0 , f('','e(33,x[2]=0,x[4]=(1-z)*1.2*R(1,.02))') , b ],
+	[ 18 , 0 , f('','e(33,x[4]=0,x[8]=z)') , b , m ],
+	[ 36 , 0 , f('','e(33,x[2]=1-N(x[8]=1,4*z))'), b = [ o , g(33) ], m ],
+	[ 33 , 0 , f('','e(33,x[2]=z,x[3]=.7,x[4]=-((4*z)%1)*R(1,.05))'), b , m ],
+	[ 9 , 1 , f('','u(x[4]=0,x[2]=1-z,x[3]=1)'), a, m ],
+	[ 20 , 1 , f('','u(z,x[2]=0)'), a, m ],
+	[ 31 , 1 , f('','u(1,x[2]=1-N(1,5*z))'), a, m ],
+	[ 5 , 1 , f('','u(1,x[2]=1-z)'), a, m ],
+	[ 18 , 1 , f('','u(1,x[2]=1-N(1,5*z),x[4]=M(0,1.6*z-.8)*R(1,.05))'), a, m ],
+	[ 12 , 1 , f('','u(1,x[2]=z,x[4]=(1-z)*.8*R(1,.05),x[3]=.1)'), a, m ],
+	[ 22 , 3 , f('','q(x[2]=1-z,x[4]=0)'), b = [ w(.6,30) , u(1),u(-1.5) ], m ],
+	[ 59 , 3 , f('','q(x[2]=1-N(1,(12*z)%4),x[3]=.8)'), b, m ],
+	[ 8 , 3 , f('','q(x[2]=z,x[4]=R(0,x[3]=.1))'), b ],
+	[ 7 , 0 , f('','x[fx=2]=1-z,e(46,x[4]=R(0,.1),x[8]=1)'), c = [ o , g(47) ] ],
+	[ 22 , 0 , f('','e(47,x[4]=R(0,.1))'), c ],
+	[ 10 , 0 , f('','e(47,x[4]=R(0,.1),x[2]=z,x[3]=1)'), c ],
+	[ 10 , 1 , f('','u(1,x[2]=1-z,x[4]=R(0,.1))'), a ] ,
+	[ 4 , 1 , f('','u(1,x[2]=1-((z*4)%1),x[4]=R(0,.1))'), a ] ,
+	[ 2 , 1 , f('','u(1,x[4]=R(x[2]=0,.1))'), a ] ,
+	[ 36 , 1 , f('','u(1,x[2]=1-N(1,2*((z*3)%1)),x[4]=R(0,.1+.1*z)),_=3+2*z'), a ] ,
+	[ 12 , 2 , f('','g(54,x[2]=1-((z*4)%1))'+(b=',x[4]=R(0,.2)+D(54)*2')), a=[ w(1,30) ] ],
+	[ 6 , 2 , f('','g(54,x[2]=1-((z*6)%1))'+b), a ],
+	[ 30 , 2 , f('','g(54,x[1]=N(1,z*2),x[2]=z,x[3]=0)'+b), a ],
+	[ 21 , 2 , f('','g(54,x[2]=1)'), a ]
+];
+
+fx=1,x=e(10),p=e(3),s=e(3),n=e(3),fz=e(3),ff=e(3),fy=e(3),yy=e(3),xf=e(9),xw=[[e(3),0,0],[e(3),0,0],[e(3),0,zz=0]],_=new Int32Array(xz=10717272),w=f('a','y(p,-6,0,a=f*6),y(s,x[1]=1,x[8]=0,a),y(n,0,1,0)'),q=f('a','a=D(44)*10,y(p,C(f)*12,9.5,S(f)*12+a),y(s,1,1,a),y(n,0,_=2.5,0),x[8]=D(44)'),r=f('','y(p,4,2.5+.025*f,6.7),y(s,x[8]=x[9]=0,2.5-.05*f,6.7),y(n,0,0,1),_=3'),u=f('a,b','b=fx*f,y(p,5*S(b*.2),9*C(b*.41),7.8),y(s,C(b*.2),S(b*.33),p[2]-2),y(n,0,0,x[9]=1),x[8]=a,_=3'),v=f('a,b,c','with(yx)shadowBlur=ww/5,fillText(a,b,c=ww/2),shadowBlur=0,strokeText(a,b,c)'),m=f('a,b,c,d,e,f','v([\'TheT(ourist)\',\'presents\',\'Sine City\'][a],yw/15),x[5]=1-zf+R(0,b),x[6]=c,y(fz,d,e,f)'),o=f('a,b','a=D(26),y(p,b=a*10-80,0,0),y(s,b+C(a*.5)*80,S(a*.25)*40,100),y(n,0,_=2.5,0)'),g=f('a,b','a=D(a)*fx,y(p,0,0,b=a*20-80),y(s,C(a*.5)*80,S(a*.25)*40,100+b),y(n,0,_=2,0),x[4]=R(a=.0125,a)'),e=f('a','a=D(a)*fx*30,y(p,1.1*C(a*.1),S(a*.02)-2,a),a+=5,y(s,-S(a*.05),-.7*C(a*.033)-2,a),y(n,0,_=2/fx,0)'),K=f('a,b','b=100/3,J(K),zz?0:(A.play(),zz=a,$=zz-b),yz=a-$,f=.001*(a-zz);if(yz>b){$=a-(yz%b),j=h[t];while(j&&j[7]<f)j=h[++t];if(j){x[0]=f,x[7]=zf,xz=f-j[5],z=xz/j[6];with(zx){j[4]?(yx.clearRect(0,0,yw,100),teID(3553,j[4](),k=6408,k,5121,C2)):0,j[2](),zw(yy,_f(yy,s,p)),zw(ff,fw(ff,n,yy)),zw(fy,fw(fy,yy,ff)),$f(yy,yy,_);for(i=0;i<3;i++)xf[i*3]=ff[i],xf[i*3+1]=fy[i],xf[i*3+2]=yy[i];for(i in j[3])j[3][i](xw[i]);f=zy[j[1]],usP(f[k=0]),f=f[1],veAP(enVAA(unM3fv(f[k++],un1i(f[k++],un3fv(f[k++],p)),xf)),2,5126,un3fv(f[k++],fz),8,un1fv(f[k++],x));for(i in j[3])un3fv(f[k++],xw[i][0]),un1f(f[k++],xw[i][1]),un1f(f[k++],xw[i][2]);drA(4,0,3)}}}'),L=f('','setTimeout(function(){(J=requestAnimationFrame)(K)},1500)'),D=f('a','','f-h[a][5]');
+
+for(t=i=0;i<58;i++)h[i][5]=t,t+=(h[i][6]=h[i][0]/8),h[i][7]=t;
+
+t=0,yx=C2.getContext('2d'),(onresize=f('a,b,c,d,e','with(yx)a=innerWidth,b=innerHeight,c=(b*1.6)|0,d=(a*.625)|0,zx.vi(0,0,C2.style.width=C2.width=C1.width=yw=c>a?a:c,C1.height=e=c>a?d:b),ww=C2.style.height=C2.height=M(e/8,100),zf=ww/e,C1.style.left=((a-yw)/2)|0,C1.style.top=((b-e)/2)|0,shadowColor=\'#ccc\',font=\'normal small-caps bold \'+((ww/2)|0)+\'px monospace\',fillStyle=\'#111\',strokeStyle=\'#ddd\''))(),
+
+I=setInterval(f('a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,u,v,w','for(d=new Int32Array(xz),f=[[[0,198,128,0,3,192,128,1,0,0,96,128,28,0,0,0,0,2,63,61,13,16,44,8,0,0],[1,2,3,4,5,2,3,4,6,7,1,2,3,4,5,2,3,4,5,2,3,4,1,2,3,8,9],[[[b=115,,,,,,,,,,,,117,,,,,,,,,,,,113],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[b,,,,,,,,,,,,,,,110],[12,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,b,,,,,,,,,,,,,,,148]],[[b,,,,,,,,,,,,117,,,,,,,,,,,,118],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[122,,,,,,,,,,,,,,,123,,,,,b],[12,,,,,,,,,,,,,,,12,,,,,12,,,,,,,,,,,,,,,,b,,,,,,,,,,,,,,,8,,,,,128]],[[118,,,,,,,,,,,,117,,,,,,,,,,,,113],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,96]],[[b],[12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,255]],[[,,,,,,,,,,,,,,,,118,118,118],[,,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,128]],[[122,,,,,,,,,,,,,,,123,,,,,b],[12,,,,,,,,,,,,,,,12,,,,,13,12,,,,,,,,,,,,,,,b,,,,,,,,,,,,,,,8,,,,,95,61]],[[],[]]]],[[0,255,116,1,0,255,101,0,0,15,1,4,45,0,13,6,1,2,62,27,60,48,0,0,44,2],[,1,,2,,1,,2,,3,4,4,5,4,5,4,5,4,5,4,5,4,5,4,3,6],[[[,,,,,a=139,,,a,a,,,,,,a,,,,,,,,a,,,a,a,,,,,a,a,a],[]],[[,,a,a,,,,,a,a,,,,,a,a,,,,,,,,,,a,a,a,,,,,a,a,a],[]],[[,,,a,,,,,a,a,,,,,,a,,,,,a,a,,,,,,a,,,,a,a,a],[]],[[a,,,,a,,a,,,a,,,a,,,,a,,a,,,a,,,a,,,,a,,a,,,a],[]],[[a,,,a,a,,a,,,a,,,a,,,a,a,,a,,,a,,,a,,,a,a,,a,,,a],[]],[[a,,,a,a,,a,,,a,,,a,,,a,a,,a,,,a,a],[]]]],[[0,0,140,0,0,0,140,0,0,128,4,10,34,0,187,5,0,1,239,135,34,19,108,8,8,4],[,,1,,1,,3,,1,3,2,2,2,2,2,3,2,3,2,3,2,3,2,3,1],[[[,,,,,,,,,,127,,,,,,,,,,,,127,,,,,,,,,,,,127],[]],[[,,,a,,,,,,a,a,,,,,a,,,,,,a,a,,,,,a,,,,,a,,a],[]],[[,,127,,,,,,,,127,,,,127,,,,,,,,127,,,,127,,,,,,,,127],[]]]],[[1,192,128,0,3,201,128,0,0,93,5,6,58,3,195,6,1,3,35,63,14,17,11,10,61,6],[,,,,1,2,3,4,5,6,7,5,8,9,10,11,8,9,10,11,12,13,14,15,16],[[[,,,,,,,,147,146,145,,,,,,,,,,145,147,146,,,,,,,,,,149,148,147],[]],[[,,,,,,151,151,151,,,,,,,146,142,138,,,,,,,,,,,,,,,147,150,147],[]],[[,,146,,,146,,,,,,,,,147,146,145,,,,,,,,,,146,145,142,,,142,,,142],[]],[[,,141,,,,,,,,,,,,141,140,a,,,146,,,146,,,127],[]],[[,a,,151,,,,,,,,,,151,,a,,,,,,,,,,a,,151],[]],[[,a,,151,150,149,,,,,,,,a,,149,148,147,,,,,,,,a,,,146,,,145,,,144],[]],[[,a,,,a,142,,,142,144,146,,144,,,,146,147,,,147,146,141,,137,,,,142,141,,141,,137],[]],[[a,,127,,142,,,130,,,144,142,141,,129,,141,,,144,,,141,144,142,,,,149,,,146,,,151],[]],[[,149,,149,,146,144,142,,,141,,142,,,a,,,,151,147,,,,146,147,,144,146,,142,144,141,146],[]],[[,,,,,,,,147,146,145,,,,,141,144,147,146,,144,,137,,,144,146,142,144,,,142,144,141,146],[]],[[,146,,151,,146,,,,144,142,144,146,,,,142,,,,,a,,,,,151,146,a,144,a,142,141,142,151],[]],[[,,147,,,149,146,,,142,,142,141,,,144,,144,,,144,146,142,144,142,,,,151,150,149,,137,,149],[]],[[,151,,,147,151,,,146,151,,,,,144,151,,149,147,149,151,,146,,,144,143,142,,,a,,151,a],[]],[[,,134,,,134,,,134,,,146,144,,,141,144,,,146,147,146,,,144,,a,140,141,,,153,,,141],[]],[[,142,,151,,,142,143,144,,,,151,,,a,,,137,,149,,137,,,,125,,,141,142,141,,,146],[]],[[a,,127,a,,127,a,,127,a,127],[]]]],[[2,160,128,1,0,160,128,0,1,60,4,7,41,0,60,4,1,3,14,0,35,32,31,12,89,1],[,,,,,,,,,,,,1,2,1,2,1,2,1,2,1,2,1,2,1,3],[[[,,a,,,,,,,,,,,,a,,,,,,,,,,,,a,,,,,a,a,,,a],[]],[[,,a,,,151,,,a,,,151,,,a,,,151,,,a,,,151,,,a,,,151,,,146,146,146,146],[]],[[,,a,,,151,,,a,,,151,,,a,,a,a,a,a,127],[]]]],[[2,100,128,0,3,201,128,0,0,0,0,6,29,0,195,6,1,3,28,229,119,77,147,6,61,2],[,,,,,,,,,6,1,2,3,4,5,2,3,4,1,2,3,4,1,2,3,7],[[[b,b,b,b,b,b,b,b,b,b,b,b,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],[]],[[b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110],[]],[[b,b,b,b,b,b,b,b,b,b,b,b,117,117,117,117,117,117,117,117,117,117,117,117,118,118,118,118,118,118,118,118,118,118,118,118],[]],[[110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b],[]],[[118,118,118,118,118,118,118,118,118,118,118,118,117,117,117,117,117,117,117,117,117,117,117,117,113,113,113,113,113,113,113,113,113,113,113,113],[]],[[,,,,,,,,,,,,,,,,,,130,,130,,130,,130,,130,,130,118,130,118,130,118,130,118],[,,,,,,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2]],[[110,122,,122,134,,110,122,,122,134,,110,122,,111,123,,111,123,b,127,a,127,b],[,,,,,,,,,,,,,,,,,,,,26,25,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,147]]]],[[2,100,128,0,3,201,128,0,0,0,5,6,58,0,195,6,1,2,135,0,0,32,147,6,121,6],[],[]],[[2,100,128,0,3,201,128,0,0,0,5,6,58,0,195,6,1,2,135,0,0,32,147,6,121,6],[],[]]][t],o=[],g=h=m=p=0;p<=26;p++)for(b=f[1][p],a=0;a<36;a++){((e=b?f[2][b-1][1][a]:0)?((f[0][e-1]=f[2][b-1][1][a+36]||0),e<14?(o=[]):0):0),c=(p*36+a)*5513;for(j=0;j<4;j++)if(n=b?f[2][b-1][0][a+j*36]:0){if(!o[n])for(q=f[0][10],r=f[0][11],s=f[0][12],w=yz(n+f[0][2]-128),l=yz(n+f[0][6]-128)*(1+.0008*f[0][7]),u=v=0,q*=q*4,r*=r*4,s*=s*4,o[n]=new Int32Array(q+r+s),k=0;k<q+r+s;k++)e=k<q?(k/q):(1-(k<q+r?0:((k-q-r)/s))),o[n][k]=(80*($[f[0][0]](u+=w*(f[0][3]?(e*e):1))*f[0][1]+$[f[0][4]](v+=l*(f[0][8]?(e*e):1))*f[0][5]+R(0,1)*f[0][9])*e)|0;for(k=0,i=c*2;k<o[n].length;k++,i+=2)d[i]+=o[n][k]}q=f[0][20]*1e-5,r=f[0][24]/255,s=f[0][25]*5513;for(j=0;j<5513;j++)(((n=e=d[k=(c+j)*2])||m)?(w=1.5*S(f[0][18]*.00307999186353015873*(f[0][16]?($[f[0][13]](P(2,f[0][15]-9)*k/5513)*f[0][14]/512+.5):1)),g+=w*h,l=(1-f[0][19]/255)*(e-h)-g,h+=w*l,e=f[0][17]==3?h:f[0][17]==1?l:g,q?(e*=q,e=(e<1?e>-1?$[0](e*.25):-1:1)/q):0,e*=f[0][21]/32,m=e*e>1e-5,w=S(6.283184*P(2,f[0][23]-9)*k/5513)*f[0][22]/512+.5,n=e*(1-w),e*=w):0),(k>=s?(n+=d[k-s+1]*r,e+=d[k-s]*r):0),_[k]+=(d[k]=n|0),_[k+1]+=(d[k+1]=e|0)}if(++t==8)for(clearInterval(I),s=(f=String.fromCharCode).apply(String,[82,73,70,70,168,16,71,1,87,65,86,69,102,109,116,32,16,0,0,0,1,0,2,0,68,172,0,0,16,177,2,0,4,0,16,0,100,97,116,97,132,16,71,1]),t=i=0;i<xz||(((A=document.createElement(\'audio\')).src=\'data:audio/wav;base64,\'+btoa(s),A.oncanplaythrough=L)&&0);i++)e=_[i],e=e<-32767?-32767:(e>32767?32767:e),s+=f(e&255,(e>>8)&255)'),0);