29 June 2017

Unity experiments

I started experimenting more in Unity. First, I worked on converting some point cloud stuff I was doing in TouchDesigner to Unity's compute shaders. The screen capture didn't come out too well, but it runs at about 100fps.

I also started building a whip weapon in the style of Dr. Strange-meets-vaporwave. It really needs to be in VR for the full effect.

12 April 2017

Melange dev

Some quick videos showing my Masters project, Melange. The strings are used as waveforms to sonify the fluid field.

Strings visible:

Turning up string velocity feedback:

10 April 2017

150 Media Stream

Last month I flew to Chicago to get my piece Cirrus running on 150 Media Stream. The LED wall is 150' x 22' and runs four 4k streams across five computers. Cirrus is a live real time fluid dynamics + reaction-diffusion simulation.

Videos are sped up 5x.

19 March 2017

Spring-mass GLSL

This spring-mass system was adapted to the GPU in GLSL from Paul Bourke's example. I'm using it to sonify the fluid in a way that allows for more structure and flexibility than directly sampling the velocity field. I'll post more about this technique in the future.

The system uses a 1024 x 4 texture map with simple one-dimensional spring connections that bind each pixel to its horizontal neighbor, forming 4 lines. I extended Paul's example to include an anchor force which pulls the particles back to a rest position (in this case concentric rings), and an impulse force that applies velocity from an outside source.

layout(location=0) out vec3 fragColorPosition;
layout(location=1) out vec3 fragColorVelocity;

uniform float dt;
uniform float springConstant;
uniform float restLength;
uniform float dampingConstant;
uniform float viscousDrag;
uniform float anchorForce;
uniform float impulseForce;
uniform float mass;
uniform float fluidLengthThreshold;

vec2 springs[2] = vec2[2](vec2(-1.,0.), vec2(1.,0.));

const int POSITION_OLD = 0;
const int VELOCITY_OLD = 1;
const int VELOCITY_NEW = 2;
const int ANCHOR = 3;

const float smallf = 0.000001;

void main() {

    // Calculate forces
    vec3 pos0 = texture(sTD2DInputs[POSITION_OLD], vUV.st).xyz;
    vec3 vel0 = texture(sTD2DInputs[VELOCITY_OLD], vUV.st).xyz;
    vec3 vel_new = texture(sTD2DInputs[VELOCITY_NEW], pos0.xy).xyz; 
    vec3 anchor = texture(sTD2DInputs[ANCHOR], vUV.st).xyz;
    vec3 force = vec3(0.);

    force -= viscousDrag * vel0;
    force += vel_new * dt * dt * impulseForce;
    force += (anchor-pos0) * anchorForce;

    // spring interaction
    // 1d horizontal connection
    float cellSize = uTD2DInfos[POSITION_OLD].res.x; // 1/width

    for (int i = 0; i < 2; i++) {
        vec2 offset = vec2(cellSize, 0.);
        offset *= springs[i];
        vec2 coord = vUV.st + offset;
        if (coord.x < 0.) coord.x = 1.-cellSize;
        if (coord.x > 1.) coord.x = 0.+cellSize;

        vec3 pos1 = texture(sTD2DInputs[POSITION_OLD], coord).xyz;
        vec3 vel1 = texture(sTD2DInputs[VELOCITY_OLD], coord).xyz;

        vec3 dx = pos0 - pos1;
        float len = length(dx) + smallf;

        vec3 f = vec3(springConstant * (len - restLength)); 
        f += dampingConstant * (vel0 - vel1) * dx/vec3(len); 
        f *= -dx/vec3(len);

        force += f;

    // Apply derivative
    vec3 dpdt = vel0;
    vec3 dvdt = force/vec3(mass);

    pos0 += dpdt * dt;
    vel0 += dvdt * dt;

    fragColorPosition = pos0;
    fragColorVelocity = vel0; 

} //main

12 February 2017

Playing with reaction diffusion anisotropy and scale

150 Media Stream

Pieces are coming together for the media wall installation in Chicago. It has a website now:


Here are some photos of a test shoot of my fluid work that I'm now calling Cirrus. They only had one half of the display working: