Showing posts with label particles. Show all posts
Showing posts with label particles. Show all posts

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

09 May 2016

Tukey Window



This is a quick video demonstrating Tukey Windowing modulating the particle size using age as the input signal. Alpha (from the window function, not rgba) is set to .3 and it's been zoomed in to see the effect easier. Windowing the particle size will help ease transitions from particle birth and death so there's less noticeable pops. Here's some glsl code:

float tukeyWindow(float sig, float alpha) {
 if (alpha == 0.) // rectangular window
  return 1.;
 else if (sig < alpha / 2.)
  return 0.5 * (1. + cos(2.*3.1459265/alpha * (sig-alpha/2.)));
 else if (sig > 1.-alpha/2.)
  return 0.5 * (1. + cos(2.*3.1459265/alpha * (sig-1.+alpha/2.)));
 else
  return 1.;
}

24 April 2016

Particle trails



Messing around with feedback to get flow lines from the fluid sim. The color represents velocity direction and value is the magnitude of the velocity. Particles can bounce around obstacles and don't spawn inside them. 1 million particles @60 fps.

21 April 2016

GPU particles



Here's 250,000 particles being advected by the velocity field. This is being done using glsl shaders in TouchDesigner. The value of the particles is currently just the magnitude of the velocity, but I'll be adding a lot more color options later. I'm maintaining 60fps using a 512x512 fluid container.

I'm going to spend the next couple of weeks making big pushes in UI to prepare for a public demonstration at the end of year show. A lot to do still.