Skip to content

Commit

Permalink
parameterize all the things, better neighbor selection
Browse files Browse the repository at this point in the history
  • Loading branch information
Will Greenberg committed May 14, 2016
1 parent 65af80b commit d9e135b
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 57 deletions.
117 changes: 86 additions & 31 deletions boids/computeFragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,48 @@ uniform vec2 u_resolution;
uniform sampler2D u_prevP;
uniform sampler2D u_prevV;

uniform float u_boxSize;
uniform float u_comfortZone;
uniform float u_alignmentC;
uniform float u_cohesionC;
uniform float u_randomC;
uniform float u_separationC;
uniform float u_maxV;

#define DIM 64
#define BOX_SIZE 10.0
#define MAX_V 0.085
#define COMFORT_ZONE 0.4
#define NEIGHBOR_ZONE 0.5
#define MAX_R 10.0
#define CNT_STR 0.002
#define MAX_R 30.0
#define CNT_STR 0.008
#define N_NEIGHBORS 8

vec3 bound (vec3 p) {
if (p.x > BOX_SIZE)
p.x = -BOX_SIZE;
if (p.x < -BOX_SIZE)
p.x = BOX_SIZE;
if (p.y > BOX_SIZE)
p.y = -BOX_SIZE;
if (p.y < -BOX_SIZE)
p.y = BOX_SIZE;
if (p.z > BOX_SIZE)
p.z = -BOX_SIZE;
if (p.z < -BOX_SIZE)
p.z = BOX_SIZE;
float half_box = u_boxSize / 2.0;
if (p.x > half_box)
p.x -= u_boxSize;
if (p.x < -half_box)
p.x += u_boxSize;
if (p.y > half_box)
p.y -= u_boxSize;
if (p.y < -half_box)
p.y += u_boxSize;
if (p.z > half_box)
p.z -= u_boxSize;
if (p.z < -half_box)
p.z += u_boxSize;
return p;
}

// one liner prng from http://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl
float rand(vec2 co){
return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453) - 0.5;
}

vec3 randvec3(int t, vec3 pos) {
float x = rand(vec2(float(t), pos.x));
float y = rand(vec2(float(t), pos.y));
float z = rand(vec2(float(t), pos.z));
return vec3(x, y, z);
}

void main() {
vec2 uv = gl_FragCoord.xy/u_resolution.xy;

Expand All @@ -41,9 +59,15 @@ void main() {
vec3 separation = vec3(0.0);
vec3 cohesion = vec3(0.0);
vec3 alignment = vec3(0.0);
vec3 centering = length(our_p) > MAX_R ? -CNT_STR * our_p : vec3(0.0);
vec3 centering = length(our_p) > MAX_R && false ? -CNT_STR * our_p : vec3(0.0);
vec3 random = randvec3(u_time, our_p);

// d, u, v
vec3 closest_neighbors[N_NEIGHBORS];

int n_neighbors = 0, n_separated = 0;
for (int i=0; i < N_NEIGHBORS; i++) {
closest_neighbors[i] = vec3(-1.0, 1.0, 0.0);
}

for (int i=0; i < DIM; i++) {
for (int j=0; j < DIM; j++) {
Expand All @@ -58,27 +82,58 @@ void main() {
continue;

float d = distance(their_p, our_p);
if (d < COMFORT_ZONE) {
if (d < u_comfortZone) {
separation -= (their_p - our_p);
}
if (d < NEIGHBOR_ZONE) {
alignment += their_v;
cohesion += their_p;
n_neighbors++;

vec3 furthest_neighbor = closest_neighbors[N_NEIGHBORS - 1];
if (furthest_neighbor.x == -1.0 || furthest_neighbor.x > d) {
bool inserted = false;
vec3 temp, last;
for (int k=0; k < N_NEIGHBORS; k++) {
vec3 neighbor = closest_neighbors[k];
// If we've already inserted this boid into the neighbors list,
// just bump the last neighbor down the line
if (inserted) {
temp = neighbor;
closest_neighbors[k] = last;
last = temp;
continue;
}
if (neighbor.x == -1.0 || neighbor.x > d) {
inserted = true;
last = neighbor;
closest_neighbors[k].x = d;
closest_neighbors[k].yz = coord;
}
}
}
}
}

cohesion /= float(n_neighbors);
for (int i=0; i < N_NEIGHBORS; i++) {
vec2 coord = closest_neighbors[i].yz;
vec3 their_v = vec3(texture2D(u_prevV, coord));
vec3 their_p = vec3(texture2D(u_prevP, coord));

alignment += their_v;
cohesion += their_p;
}

cohesion /= float(N_NEIGHBORS);
cohesion -= our_p;
cohesion /= 100.0;

alignment /= float(n_neighbors);
alignment *= 8.0;
alignment /= float(N_NEIGHBORS);

cohesion *= u_cohesionC;
alignment *= u_alignmentC;
separation *= u_separationC;
random *= u_randomC;

our_new_v = normalize(our_v + centering + separation + cohesion + alignment) * MAX_V;
our_new_v = normalize(our_v + centering + separation + cohesion + alignment + random) * u_maxV;
//our_new_v = normalize(our_v) * u_maxV;

vec3 our_new_p = our_p + our_new_v;
vec3 our_new_p = bound(our_p + our_new_v);

gl_FragData[0] = vec4(our_new_p, 1.0);
gl_FragData[1] = vec4(our_new_v, 1.0);
Expand Down
3 changes: 2 additions & 1 deletion boids/fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ uniform int u_time;
varying vec2 v_uv;

uniform sampler2D u_currP;
uniform sampler2D u_currV;

void main() {
gl_FragColor = vec4 (1.0, 0.0, 0.0, 1.0);
gl_FragColor = vec4 (vec3(0.0), 1.0);
}
70 changes: 48 additions & 22 deletions boids/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@ var time = 0;
var USE_DEBUG = false;
var USE_COMPUTE = true;

function update (gl, camera, render, compute, debug) {
var boxSize = 100.0;
var comfortZone = 2.0;
var alignmentC = 8.0;
var cohesionC = 0.1;
var randomC = 0.5;
var separationC = 1.0;
var cameraZ = 50.0;
var maxV = 0.3;

function update (gl, render, compute, debug) {
time += 1;

var curr, prev;
Expand Down Expand Up @@ -38,17 +47,26 @@ function update (gl, camera, render, compute, debug) {
gl.bindTexture(gl.TEXTURE_2D, prev.velocityTex);
gl.uniform1i(compute.prevVLocation, 1);

gl.uniform1i(compute.timeLocation, time % 1e9);
gl.uniform1f(compute.boxSizeLocation, boxSize);
gl.uniform1f(compute.maxVLocation, maxV);
gl.uniform1f(compute.comfortZoneLocation, comfortZone);
gl.uniform1f(compute.alignmentCLocation, alignmentC);
gl.uniform1f(compute.cohesionCLocation, cohesionC);
gl.uniform1f(compute.separationCLocation, separationC);
gl.uniform1f(compute.randomCLocation, randomC);

gl.bindBuffer(gl.ARRAY_BUFFER, quad.buffer);
gl.vertexAttribPointer(compute.positionLocation, 3, gl.FLOAT, false, step * quad.size, 0);
gl.drawArrays(gl.TRIANGLES, 0, quad.count);

// actually draw to screen
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.viewport(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.clearColor(1, 0, 0, 1);
}

// actually draw to screen
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.viewport(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.clearColor(0, 1, 1, 1);

if (USE_DEBUG) {
gl.useProgram(debug);

Expand All @@ -66,22 +84,25 @@ function update (gl, camera, render, compute, debug) {
gl.bindTexture(gl.TEXTURE_2D, curr.positionTex);
gl.uniform1i(render.currPLocation, 0);

gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, curr.velocityTex);
gl.uniform1i(render.currVLocation, 1);

var projection = mat4.create();
mat4.perspective(projection, 60 * Math.PI/180, CANVAS_WIDTH/CANVAS_HEIGHT, 0.1, 300); // random defaults
gl.uniformMatrix4fv(render.projLocation, false, projection);

var view = mat4.create();
mat4.lookAt(view, camera.pos, camera.look, [0, 1, 0]); // y axis is up
gl.uniformMatrix4fv(render.viewLocation, false, view);
gl.uniform1f(render.boxSizeLocation, boxSize);
gl.uniform3f(render.cameraPosLocation, 0, 0, cameraZ);

gl.bindBuffer(gl.ARRAY_BUFFER, particleUVs.buffer);
gl.vertexAttribPointer(render.uvLocation, 2, gl.FLOAT, false, step * particleUVs.size, 0);
gl.drawArrays(gl.POINTS, 0, NUM_BOIDS);
}
}

// make a grid of boids
function getBoidVerts () {
// make a grid of evenly spaced UV coordinates
function getUVGrid () {
var arr = [];
for (var x=0; x<SQRT_BOIDS; x++) {
for (var y=0; y<SQRT_BOIDS; y++) {
Expand Down Expand Up @@ -109,7 +130,7 @@ function setupModel (gl) {

particleUVs.buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, particleUVs.buffer);
verts = Float32Array.from(getBoidVerts());
verts = Float32Array.from(getUVGrid());
gl.bufferData(gl.ARRAY_BUFFER, verts, gl.STATIC_DRAW);
particleUVs.size = 2;
particleUVs.count = verts.length / particleUVs.size;
Expand Down Expand Up @@ -157,10 +178,10 @@ function createComputeFBO (gl, ext) {
var width = SQRT_BOIDS;
var height = SQRT_BOIDS;

var positionTex = createTex(gl, width, height, 10);
var positionTex = createTex(gl, width, height, boxSize);
gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT0_WEBGL, gl.TEXTURE_2D, positionTex, 0);

var velocityTex = createTex(gl, width, height, 0.005);
var velocityTex = createTex(gl, width, height, maxV);
gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT1_WEBGL, gl.TEXTURE_2D, velocityTex, 0);

ext.drawBuffersWEBGL([
Expand Down Expand Up @@ -190,6 +211,14 @@ function createComputeProgram () {
computeProg.prevPLocation = gl.getUniformLocation(computeProg, 'u_prevP');
computeProg.prevVLocation = gl.getUniformLocation(computeProg, 'u_prevV');
computeProg.resolutionLocation = gl.getUniformLocation(computeProg, 'u_resolution');
computeProg.boxSizeLocation = gl.getUniformLocation(computeProg, 'u_boxSize');
computeProg.comfortZoneLocation = gl.getUniformLocation(computeProg, 'u_comfortZone');
computeProg.alignmentCLocation = gl.getUniformLocation(computeProg, 'u_alignmentC');
computeProg.cohesionCLocation = gl.getUniformLocation(computeProg, 'u_cohesionC');
computeProg.separationCLocation = gl.getUniformLocation(computeProg, 'u_separationC');
computeProg.randomCLocation = gl.getUniformLocation(computeProg, 'u_randomC');
computeProg.maxVLocation = gl.getUniformLocation(computeProg, 'u_maxV');

return computeProg;
}

Expand Down Expand Up @@ -224,7 +253,10 @@ window.onload = function () {
gl.enableVertexAttribArray(render.uvLocation);

render.currPLocation = gl.getUniformLocation(render, 'u_currP');
render.currVLocation = gl.getUniformLocation(render, 'u_currV');
render.projLocation = gl.getUniformLocation(render, "u_proj");
render.boxSizeLocation = gl.getUniformLocation(render, 'u_boxSize');
render.cameraPosLocation = gl.getUniformLocation(render, 'u_cameraPos');

// setup the render pass
var debug = createProgram(gl, 'debugVertex.glsl', 'debugFragment.glsl');
Expand All @@ -242,14 +274,8 @@ window.onload = function () {

setupModel(gl);

var camera = setupCamera({
initialAngle: 90,
speed: 1,
turnRate: 5,
});

window.mainloop = function () {
update(gl, camera, render, compute, debug);
update(gl, render, compute, debug);
window.requestAnimationFrame(mainloop);
};

Expand Down
11 changes: 8 additions & 3 deletions boids/vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,24 @@ attribute vec2 a_uv;

uniform int u_time;
uniform sampler2D u_currP;
uniform sampler2D u_currV;
uniform mat4 u_proj;
uniform mat4 u_view;

varying vec2 v_uv;

uniform float u_boxSize;
uniform vec3 u_cameraPos;

float minPointScale = 0.1;
float maxPointScale = 1.0;
float maxDistance = 10.0;
float maxDistance = u_cameraPos.z + u_boxSize / 2.0;

void main () {
v_uv = a_uv;
vec3 pos = vec3(texture2D(u_currP, a_uv));
pos.z -= 20.0;
vec3 vel = vec3(texture2D(u_currV, v_uv));

pos.z -= u_cameraPos.z;

float cameraDist = length(pos);
float pointScale = 1.0 - (cameraDist / maxDistance);
Expand Down

0 comments on commit d9e135b

Please sign in to comment.