filters/sphere tracer

 
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { create: create, update: update });

var filter;
var sprite;

function create() {

    //  From http://glslsandbox.com/e#16061.2

    var fragmentSrc = [

        "#ifdef GL_ES",
        "precision mediump float;",
        "const vec3 df = vec3(0.05, 0.0, 0.0);",
        "#else",
        "const vec3 df = vec3(0.01, 0.0, 0.0);",
        "#endif",

        "uniform float     time;",
        "uniform vec2      resolution;",
        "uniform vec2      mouse;",

        "// Sphere tracer by mzeo",
        "// inspired by http://www.youtube.com/watch?v=kuesTvUYsSc#t=377",
        "// waves by @hintz",

        "#define AUTO_CAMERA",

        "// Constants",
        "// Camera",
        "const vec3 origin = vec3(0, 0, 0);",
        "const int steps = 128;",
        "const vec3 sun = vec3(1.0, .5, -1.0);",

        "const int miterations = 32;",

        "// Ball",
        "struct Ball",
        "{",
            "vec3 pos;",
            "float size;",
        "};",

        "const Ball ball = Ball(vec3(0, 0, 5), 0.5);",

        "struct Balls",
        "{",
            "vec3 dir;",
            "vec3 p;",
            "float dist;",
        "};",

        "const Balls balls = Balls(vec3(1, 0, 0), vec3(0, 0, 0), 1.0);",

        "// Floor",

        "struct Plane",
        "{",
            "vec3 n;",
            "float d;",
        "};",

        "const Plane plane = Plane(vec3(0, 1, 0), -1.0);",

        "// Distance",
        "struct Dist",
        "{",
            "float dist;",
            "int id;",
        "};",


        "Dist and(Dist a, Dist b)",
        "{",
            "if (a.dist < b.dist)",
            "{",
                "return a;",
            "}",

            "return b;",
        "}",

        "Dist fBall(Ball ball, vec3 p)",
        "{",
            "return Dist(length(ball.pos - p) - ball.size, 0);",
        "}",

        "Ball get(Balls balls, float t)",
        "{",
            "float a = abs(mod(t, 6.0) - 3.0);",
            "vec3 p = balls.p + balls.dir * t * balls.dist + a * a * vec3(0, -0.15, 0);",
            "return Ball(p, ball.size);",
        "}",

        "Dist fBalls(Balls balls, vec3 p)",
        "{",
            "float t = dot(p - balls.p, balls.dir) / balls.dist;",
            "float t0 = t - fract(t + fract(time) * 2.0);",
            "float t1 = t0 + 1.0;",

            "return and(",
            "fBall(get(balls, t0), p),",
            "fBall(get(balls, t1), p));",
        "}",

        "Dist fPlane(Plane plane, vec3 p)",
        "{",
            "return Dist(dot(plane.n, p) - plane.d - 0.4*cos(length(p.xz) - time), 1);",
        "}",

        "Dist f(vec3 p)",
        "{",
            "return and(",
            "fBalls(balls, p),",
            "fPlane(plane, p));",
        "}",

        "vec3 grad(vec3 p)",
        "{",
            "float f0 = f(p).dist;",

            "return normalize(vec3(",
            "f(p + df.xyz).dist,",
            "f(p + df.yxz).dist,",
            "f(p + df.yzx).dist) - f0);",
        "}",

        "float mandel(vec2 c)",
        "{",
            "vec2 z = c;",

            "for(int i = 0; i < miterations; ++i)",
            "{",
                "z = vec2(z.x*z.x - z.y*z.y, 2.0*z.x*z.y) + c;",
                "if (length(z) > 40.0) return float(i) / float(miterations);",
            "}",

            "return 0.0;",
        "}",

        "vec3 floorTexture(vec3 p)",
        "{",
            "mat2 rot = mat2(vec2(1, 1), vec2(1, -1));",
            "vec2 c = rot * (p.xz + vec2(-0.7, -1.0)) * 0.2;",
            "float i = mandel(c);",
            "return clamp(vec3(i * 10.0, i * i *10.0, i*i*i*5.0).zyx, vec3(0,0,0), vec3(2,2,2));",
        "}",


        "vec4 shade(vec3 p, vec3 ray, int id)",
        "{",
            "vec3 n = grad(p);",
            "float diffuse = clamp(dot(normalize(sun), n), 0.0, 1.0);",

            "vec3 color;",
            "float ref;",

            "if (id == 0)",
            "{",
                "color = vec3(0,1,0);",
                "ref = 0.1;",
            "}",
            "else",
            "{",
                "color = floorTexture(p);",
                "ref = 0.5;",
            "}",

            "return vec4(color * diffuse, 1) * ref;",
        "}",

        "vec4 combine(vec4 a, vec4 b)",
        "{",
            "return a + b * (1.0 - a.w);",
        "}",

        "vec4 sky(vec3 ray)",
        "{",
            "float sun = dot(ray, normalize(sun));",
            "sun = (sun > 0.0) ? pow(sun, 100.0) * 3.0 : 0.0;",
            "float horizon = 1.0 - abs(ray.y);",
            "vec3 blue = vec3(0.1, 0.3, 0.6);",
            "vec3 red = vec3(0.6, 0.3, 0.) * 2.0;",
            "return vec4(vec3(0.9, 0.8, 0.5) * sun + blue * horizon + red * pow(horizon, 8.0), 1);",
        "}",

        "vec4 trace(vec3 origin, vec3 ray)",
        "{",
            "vec3 p = origin;",
            "Dist dist = Dist(10000.0, 2);",
            "vec4 result = vec4(0, 0, 0, 0);",

            "for(int i = 0; i < steps; ++i)",
            "{",
                "dist = f(p);",
                "if (dist.dist > 0.01)",
                "{",
                    "p += ray * dist.dist;",
                    "float absorb = exp(-dist.dist * 0.05);",
                    "vec4 s = sky(ray) * (1.0 - absorb);",

                    "result = combine(result, s);",
                "}",
                "else if (result.w < 0.99)",
                "{",
                    "vec3 n = grad(p);",
                    "vec4 s = shade(p, ray, dist.id);",
                    "ray = reflect(ray, n);",
                    "p += n * 0.01;",

                    "result = combine(result, s);",
                "}",
                "else",
                "{",
                    "break;",
                "}",
            "}",

            "return combine(result, sky(ray));",
        "}",

        "void main(void)",
        "{",
            "float scale = 2.0 / max(resolution.x, resolution.y);",
            "vec3 ray = vec3((gl_FragCoord.xy - resolution.xy / 2.0) * scale, 1);",

            "#ifdef AUTO_CAMERA",
            "float yaw = cos(time) * -0.25 + 0.1;",
            "float angle = time * 0.5;",
            "#else",
            "float yaw = mouse.y - 0.15;",
            "float angle = mouse.x * 8.0;",
            "#endif",

            "vec3 from = (vec3(sin(angle), 0, cos(angle)) * cos(yaw) + vec3(0, sin(yaw) * 1.0, 0)) * 5.0;",
            "//vec3 from = origin + vec3((mouse.xy - vec2(0.5,0.0)) * vec2(15.0, 3.0), -5);",
            "vec3 to = vec3(0, -1, 0);",
            "vec3 up = vec3(0, 1, 0);",
            "vec3 dir = normalize(to - from);",
            "vec3 left = normalize(cross(up, dir));",
            "mat3 rot = mat3(left, cross(dir, left), dir);",

            "gl_FragColor = trace(from, rot * normalize(ray));",
        "}"
    ];


    filter = new Phaser.Filter(game, null, fragmentSrc);
    filter.setResolution(800, 600);

    sprite = game.add.sprite();
    sprite.width = 800;
    sprite.height = 600;

    sprite.filters = [ filter ];

}

function update() {

    filter.update(game.input.activePointer);

}