Cellular Voronoi Zoetrope Generator
PShader frag; | |
int frames = 33; | |
float frameTheta = 2. * PI / frames; | |
int h = 520; | |
int w = 520; | |
float base = 2 * tan(frameTheta / 2.)* h; | |
int renderSize = ceil(base); | |
float sliceAspect = sin(1. / frames * 0.5 * 2 * PI) * 2.; | |
int frameWidth = ceil(h * sliceAspect); | |
void settings() { | |
size(w, h, P2D); | |
} | |
PGraphics pg; | |
void setup() { | |
frag = loadShader("frag.glsl"); | |
frag.set("u_resolution", float(frameWidth), float(h)); | |
frag.set("u_cells", float(3), float(14)); | |
frag.set("u_miny", 0.1); | |
background(255); | |
} | |
String getFrameNumber(int frame) { | |
if (frame < 10) | |
return "0" + frame; | |
return "" + frame + ""; | |
} | |
int frame = 0; | |
int layer = 0; | |
int layers = 4; | |
PVector blue = new PVector(0., 0., 1.); | |
PVector purple = new PVector(1., 0., 1.); | |
PVector white = new PVector(1., 1., 1.); | |
float[] layerBorderSizes = { 1., 0.4, 0.2, 0.07 }; | |
float[] meatballSizes = { 1., 0.6, 0.45, 0.31 }; | |
PVector[] layerColors = { blue, purple, blue, white }; | |
void draw() { | |
if (frame > frames) { | |
frame = 0; | |
layer++; | |
if (layer >= layers) | |
noLoop(); | |
} | |
noStroke(); | |
frag.set("u_time", frame * 1.0 / frames); | |
frag.set("u_bordersize", layerBorderSizes[layer]); | |
frag.set("u_meatballsize", meatballSizes[layer]); | |
frag.set("u_color", layerColors[layer]); | |
//frag.set("u_frame", frame); | |
pg = createGraphics(frameWidth, h, P2D); | |
pg.beginDraw(); | |
//pg.translate(-w/2, 0); | |
pg.filter(frag); | |
//pg.arc(0, 0, h*2, h*2, PI/2 - frameTheta / 2, PI/2 + frameTheta / 2); | |
//pg.rect(0, 0, 200, 200); | |
pg.endDraw(); | |
translate(w/2, h/2); | |
scale(0.5); | |
rotate(lerp(0, -2. * PI, float(frame) / frames)); | |
translate(-frameWidth/2, 0); | |
image(pg, 0,0 ); | |
// saveFrame("frame-" + getFrameNumber(frame) + ".gif"); | |
frame++; | |
} |
// Created by Dan Oved | |
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. | |
// With code by by inigo quilez - iq/2013 | |
// http://www.iquilezles.org/www/articles/voronoilines/voronoilines.htm | |
// and code by @patriciogv - 2015 | |
// from: https://thebookofshaders.com/edit.php#12/metaballs.frag | |
#ifdef GL_ES | |
precision mediump float; | |
#endif | |
// uniform mat4 transform; | |
uniform vec2 u_resolution; | |
uniform float u_bordersize; | |
uniform float u_meatballsize; | |
uniform float u_time; | |
uniform vec2 u_cells; | |
uniform vec3 u_color; | |
uniform float u_miny; | |
#define PI 3.1415926535897932384626433832795 | |
vec2 hash2( vec2 p ) { | |
return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453); | |
} | |
int frames = 33; | |
float totalTheta = 2. * PI / float(frames); | |
float minTheta = -totalTheta / 2.; | |
vec2 origin = vec2(u_resolution.x / u_resolution.y / 2., 1.); | |
vec2 getRadialCoords(vec2 point) { | |
float y = length(point - origin); | |
float xMagnitude = point.x - origin.x; | |
float theta = sin(xMagnitude / y); | |
return vec2((theta - minTheta) / totalTheta, y); | |
} | |
vec2 getWrappedPoint(vec2 point, vec2 cells) { | |
int x; | |
int y; | |
//vec2 result = point; | |
int rows = int(cells.y); | |
int cols = int(cells.x); | |
if (point.x < 0.) { | |
x = cols - 1; | |
} | |
else if(point.x >= float(cols)) { | |
x = 0; | |
} | |
else { | |
x = int(point.x); | |
} | |
if (point.y < 0.) { | |
y = rows - 1; | |
} else if(point.y >= float(rows)) { | |
y = 0; | |
} else { | |
y = int(point.y); | |
} | |
return vec2(x, y); | |
} | |
float voronoi( in vec2 x, in vec2 cells) | |
{ | |
vec2 n = floor(x); | |
vec2 f = fract(x); | |
//---------------------------------- | |
// first pass: regular voronoi | |
//---------------------------------- | |
vec2 mg, mr; | |
float md = 8.0; | |
for( int j=-1; j<=1; j++ ) | |
for( int i=-1; i<=1; i++ ) | |
{ | |
vec2 g = vec2(float(i),float(j)); | |
vec2 o = hash2(getWrappedPoint(n+g, cells)); | |
o = 0.5 + 0.5*sin(u_time * 2. * PI + 6.2831*o ); | |
vec2 r = g + o - f; | |
float d = dot(r,r); | |
if( d<md ) | |
{ | |
md = d; | |
mr = r; | |
mg = g; | |
} | |
} | |
//---------------------------------- | |
// second pass: distance to borders | |
//---------------------------------- | |
md = 8.0; | |
for( int j=-2; j<=2; j++ ) | |
for( int i=-2; i<=2; i++ ) | |
{ | |
vec2 g = mg + vec2(float(i),float(j)); | |
vec2 o = hash2(getWrappedPoint(n+g, cells)); | |
o = 0.5 + 0.5*sin(u_time * 2. * PI + 6.2831*o ); | |
vec2 r = g + o - f; | |
if( dot(mr-r,mr-r)>0.00001 ) | |
md = min( md, dot( 0.5*(mr+r), normalize(r-mr) ) ); | |
} | |
return md; | |
} | |
vec2 random2( vec2 p ) { | |
return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453); | |
} | |
float meatballs(vec2 st, vec2 cells) { | |
vec2 i_st = floor(st); | |
vec2 f_st = fract(st); | |
float m_dist = 1.; // minimun distance | |
for (int j= -1; j <= 1; j++ ) { | |
for (int i= -1; i <= 1; i++ ) { | |
// Neighbor place in the grid | |
vec2 neighbor = vec2(float(i),float(j)); | |
// Random position from current + neighbor place in the grid | |
vec2 offset = random2(getWrappedPoint(i_st + neighbor, cells)); | |
// Animate the offset | |
offset = 0.5 + 0.5*sin(u_time * 2. * PI + 6.2831*offset); | |
// Position of the cell | |
vec2 pos = neighbor + offset - f_st; | |
// Cell distance | |
float dist = length(pos); | |
// Metaball it! | |
m_dist = min(m_dist, m_dist*dist); | |
} | |
} | |
// Draw cells | |
return m_dist; | |
} | |
float divider = 0.5; | |
float bordersize = 0.005; | |
void main() { | |
vec2 st = gl_FragCoord.xy/u_resolution.xy; | |
st.x *= u_resolution.x/u_resolution.y; | |
st = getRadialCoords(st); | |
float show = (1. - step(1. - bordersize, st.y)) * step(u_miny, st.y); | |
show *= step(0., st.x) * (1.-step(1., st.x)); | |
float color; | |
if(st.y < divider) { | |
vec2 cells = u_cells * vec2(1., 6.); | |
st *= cells; | |
float meatball = meatballs(st, cells); | |
show *= 1.-step(u_meatballsize, meatball); | |
} else { | |
st *= u_cells; | |
float c = voronoi(st, u_cells); | |
show *= (1.-step(u_bordersize, c)); | |
} | |
gl_FragColor = vec4(u_color, show); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment