混沌粒子
上图是使用粒子来对下面这张图进行描述的结果。
获取图片对应位置的像素值,然后通过鼠标位置与图片中心位置的旋转方式来获得粒子的变化。如果粒子足够小,那么粒子的旋转就变成了图片的旋转。
p5.js代码如下
var img,
particles = [],
bg;
function preload(){
img = loadImage("asset/1.jpg");
}
function setup(){
createCanvas(img.width, img.height);
for (let i = 1; i > 0; i -= 0.0003) {
const x = random(width),
y = random(height),
size = 80 * Math.pow(random(i), 2) + 8;
if (!particles.some(p => Math.pow(p.x - x, 2) + Math.pow(p.y - y, 2) < Math.pow(size / 2 + p.size / 2 - 2, 2)))
particles.push(new Particle(x, y, size));
}
bg = img.get(0, 0);
noStroke();
}
function draw(){
image(img, 0, 0);
for (const particle of particles) {
fill(particle.col);
const t = 1 - 5e-4 * (Math.pow(particle.pos.x - mouseX, 2) + Math.pow(particle.pos.y - mouseY, 2)),
p = p5.Vector.mult(particle.pos, 1 - t).add(p5.Vector.mult(particle.tgt, t));
circle(p.x, p.y, particle.size);
}
}
class Particle {
constructor(x, y, size){
this.pos = new p5.Vector(x, y);
this.tgt = p5.Vector.random2D().add(this.pos);
this.size = size;
this.col = img.get(x, y);
}
}
混沌粒子绘图
使用随机的三角函数去绘制看似随机却有关联的粒子图。
var color1 = ["#996F8D", "#083d77", "#DFB521", "#f4d35e", "#3CC43C", "#ee964b"];
var color2 = ["#f24", "#991633", "#00CCC7", "#02CA5C", "#c7f9cc", "#f01"];
var particles = []
m = 0
span = 0
function setup() {
createCanvas(1000, 700);
background(255);
fill("#111021");
pixelDensity(2);
rect(0, 0, width, height)
for (var i = 0; i < width; i += 4) {
particles.push(new Particle({
p: createVector(0, (i - height / 2) + height / 2),
v: createVector(1, -(i - height / 2) / 50),
a: createVector(0.03, 0),
color: color1[int(i / 50) % color1.length],
r: max(1, random(13) * random() * random())
}))
}
}
function draw() {
noStroke()
particles.forEach(p=> {
p.update()
p.draw()
})
}
class Particle {
constructor(args) {
let def = {
lastP: createVector(0, 0),
p: createVector(0, 0),
v: createVector(0, 0),
a: createVector(0, 0),
color: color(35),
rSpan: random([10, 20, 50, 100]),
dashSpan: random([1, 10, 10000000]),
r: 1
}
Object.assign(def, args)
Object.assign(this, def)
}
update() {
this.lastP.x = this.p.x
this.lastP.y = this.p.y
this.p.add(this.v)
this.v.add(this.a)
this.p.y += 1/tan(this.p.y*this.p.y / this.rSpan) * 4
this.p.x += tan(this.p.x*this.p.x / this.rSpan) * 4
if (int(this.p.x) % 10 == 0) {
this.v.x += (noise(this.p.x * 100, 100000) - 0.5) / 100
this.v.y += (noise(this.p.y * 100, 5) - 0.5) / 100
this.p.y += tan(this.p.x / 5) * 4
this.p.x += cos(this.p.y / 5) * 10
if (random() < 0.4) {
this.color = random(random([color1, color2]))
}
}
let delta = createVector(width / 2, height / 2).sub(this.p)
this.p.add(delta.mult(0.1).limit(4))
this.v.mult(0.999)
this.r *= 0.997
}
draw() {
push()
noStroke()
strokeWeight(this.r)
if(random(100)<1)
{
stroke(this.p.y/width*255)
}
else
{
stroke(100+random(-20,155),this.p.x/width*255,this.p.y/width*255)
}
translate(this.p.x, this.p.y)
ellipse(0, 0, this.r)
if ((frameCount % this.dashSpan) < this.dashSpan * 0.7) {
line(this.lastP.x, this.lastP.y, this.p.x, this.p.y)
}
if (random() < 0.1) {
noStroke()
fill(0, 100)
for (var i = 0; i < 5; i++) {
ellipse(this.p.x + random(-5, 5), this.p.y + random(-5, 5), random(3))
}
}
let c = color(this.color)
c.setAlpha(3)
stroke(c)
blendMode(SCREEN);
circleline0423(this.lastP.x, this.lastP.y, this.p.x, this.p.y, this.r);
pop()
m += .1
}
}
function circleline0423(s_x, s_y, e_x, e_y, num) {
for (var i = 0 ; i < num; ++i) {
c_x = lerp(s_x, e_x, i / num);
c_y = lerp(s_y, e_y, i / num);
ecolor = 255 - 155 * i / num;
fill(e_x/width*200,e_y/height*200,100+random(-100,155))
ellipse(c_x, c_y, i, i);
}
}
分形正方形
分形正方形,按照六个方向进行分形,然后得到一个拼接成六边形分形结构。然后通过鼠标拖动来移动视角得到不同距离下的分形结果。
ArrayList<Fractal> pieces;
int maxLevel = 8;
int count = 0;
int nsides = 6;
void setup() {
size(800, 800);
frameRate(100);
}
void draw() {
background(0);
pieces = new ArrayList<Fractal>();
int l = 1;
float multiplier = map(mouseX, 0, width, 0.1, 2.0);
float initialsize = map(mouseY, height, 0, 1, 400);
initialsize = map(count,0,100,400,88);
initialsize = 88;
float theta;
pieces.add(new Fractal(width/2, height/2, initialsize, 0, 0, -1));
while (l < maxLevel) {
for (int i = pieces.size()-1; i >= 0; i-- ) {
Fractal f = pieces.get(i);
if (f.level == 0 && f.level == l-1) {
for (int j = 0; j < nsides; j++) {
theta = j*TWO_PI/nsides;
float x = f.x + f.size*cos(theta);
float y = f.y + f.size*sin(theta);
pieces.add(new Fractal(x+f.size/2*cos(theta+PI/2), y+f.size/2*sin(theta+PI/2), f.size*multiplier, theta, f.level+1, j));
pieces.add(new Fractal(x+f.size/2*cos(theta-PI/2), y+f.size/2*sin(theta-PI/2), f.size*multiplier, theta, f.level+1, j));
}
} else if (f.level == l-1 && f.level > 0) {
theta = f.direction*TWO_PI/nsides;
float x = f.x + f.size*cos(theta);
float y = f.y + f.size*sin(theta);
pieces.add(new Fractal(x+f.size/2*cos(theta+PI/2), y+f.size/2*sin(theta+PI/2), f.size*multiplier, theta, f.level+1, f.direction));
pieces.add(new Fractal(x+f.size/2*cos(theta-PI/2), y+f.size/2*sin(theta-PI/2), f.size*multiplier, theta, f.level+1, f.direction));
}
}
l += 1;
}
for (Fractal f : pieces) {
f.display();
}
}
void keyPressed() {
if (keyCode == UP) {
nsides += 1;
} else if (keyCode == DOWN) {
if (nsides > 2) {
nsides -= 1;
}
} else {
saveFrame("d####.png");
}
}
class Fractal {
float x, y, size, theta;
int level, direction;
ArrayList<Float> xpoints;
ArrayList<Float> ypoints;
Fractal(float xt, float yt, float sizet, float thetat, int levelt, int directiont) {
x = xt;
y = yt;
size = sizet;
theta = thetat;
direction = directiont;
level = levelt;
xpoints = new ArrayList<Float>();
ypoints = new ArrayList<Float>();
float t = 0;
for (int i = 0; i < nsides; i++) {
float vertex_x = x + size * cos(t + PI/2 + theta);
float vertex_y = y + size * sin(t + PI/2 + theta);
//h.vertex(vertex_x, vertex_y);
xpoints.add(vertex_x);
ypoints.add(vertex_y);
t += TWO_PI/nsides* TWO_PI/nsides;
}
}
void display() {
stroke(100, 500);
//draw exterior
float xt = 0;
float yt = 0;
if (xpoints.size()>0) {
xt = xpoints.get(0);
yt = ypoints.get(0);
}
line(xt, yt, xpoints.get(xpoints.size()-1), ypoints.get(ypoints.size()-1));
for (int i = 1; i < xpoints.size(); i++) {
line(xt, yt, xpoints.get(i), ypoints.get(i));
xt = xpoints.get(i);
yt = ypoints.get(i);
}
noStroke();
fill(255, 30);
if (xpoints.size()>0) {
xt = xpoints.get(0);
yt = ypoints.get(0);
}
for (int i = 1; i < xpoints.size()-1; i++) {
triangle(xt, yt, xpoints.get(i), ypoints.get(i), xpoints.get(i+1), ypoints.get(i+1));
}
}
}
分形球
使用订单着色器进行顶点颜色编码,利用分形的思想来产生镜像的面,然后通过将不规则多个面组合成多面体就生成上图中所示的分形球,分形的次数越多,多面体月接近于球。
通过鼠标进行交互,鼠标移动时会产生一根根的对称轴,这些对称轴作为镜面来对球面上的多面体生成镜像。
let theShader;
let webGlGraphics
let frontGraphics
let colors = "43ffc7-384ded-c70039-f37121-c0e218-ffee91-fff".split("-").map(a=>"#"+a)
const vert = `
precision highp float;
// attributes, in
attribute vec3 aPosition;
attribute vec3 aNormal;
attribute vec2 aTexCoord;
// attributes, out
varying vec3 var_vertPos;
varying vec3 var_vertNormal;
varying vec2 var_vertTexCoord;
varying vec4 var_centerGlPosition;//原点
// matrices
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
uniform mat3 uNormalMatrix;
uniform float u_time;
void main() {
vec3 pos = aPosition;
vec4 posOut = uProjectionMatrix * uModelViewMatrix * vec4(pos, 1.0);
posOut.x+=sin(pos.x*5. + pos.y*7.)*20.;
posOut.y+=sin(pos.y*3.+pos.x*5.)*20.;
posOut.z+=sin(u_time/50.+posOut.y)*5.;
gl_Position = posOut;
// set out value
var_vertPos = pos;
var_vertNormal = aNormal;
var_vertTexCoord = aTexCoord;
var_centerGlPosition = uProjectionMatrix * uModelViewMatrix * vec4(0., 0., 0.,1.0);
}`;
const frag_functions_default = `
float rand(vec2 c){
return fract(sin(dot(c.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
mat2 rotate2d(float _angle){
return mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle));
}
mat2 scale2d(vec2 _scale){
return mat2(_scale.x,0.0,
0.0,_scale.y);
}
vec2 tile (vec2 _st, float _zoom) {
_st *= _zoom;
return fract(_st);
}
// Classic Perlin 3D Noise
// by Stefan Gustavson
vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}
vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}
vec3 fade(vec3 t) {return t*t*t*(t*(t*6.0-15.0)+10.0);}
float cnoise(vec3 P){
vec3 Pi0 = floor(P); // Integer part for indexing
vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1
Pi0 = mod(Pi0, 289.0);
Pi1 = mod(Pi1, 289.0);
vec3 Pf0 = fract(P); // Fractional part for interpolation
vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
vec4 iy = vec4(Pi0.yy, Pi1.yy);
vec4 iz0 = Pi0.zzzz;
vec4 iz1 = Pi1.zzzz;
vec4 ixy = permute(permute(ix) + iy);
vec4 ixy0 = permute(ixy + iz0);
vec4 ixy1 = permute(ixy + iz1);
vec4 gx0 = ixy0 / 7.0;
vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5;
gx0 = fract(gx0);
vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
vec4 sz0 = step(gz0, vec4(0.0));
gx0 -= sz0 * (step(0.0, gx0) - 0.5);
gy0 -= sz0 * (step(0.0, gy0) - 0.5);
vec4 gx1 = ixy1 / 7.0;
vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5;
gx1 = fract(gx1);
vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
vec4 sz1 = step(gz1, vec4(0.0));
gx1 -= sz1 * (step(0.0, gx1) - 0.5);
gy1 -= sz1 * (step(0.0, gy1) - 0.5);
vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);
vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
g000 *= norm0.x;
g010 *= norm0.y;
g100 *= norm0.z;
g110 *= norm0.w;
vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
g001 *= norm1.x;
g011 *= norm1.y;
g101 *= norm1.z;
g111 *= norm1.w;
float n000 = dot(g000, Pf0);
float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
float n111 = dot(g111, Pf1);
vec3 fade_xyz = fade(Pf0);
vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x);
return 2.2 * n_xyz;
}
vec2 random2( vec2 p ) {
return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}`;
const frag = `
precision highp float;
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
uniform vec3 u_lightDir;
uniform vec3 u_col;
uniform mat3 uNormalMatrix;
uniform float u_pixelDensity;
uniform sampler2D u_tex;
//attributes, in
varying vec4 var_centerGlPosition;
varying vec3 var_vertNormal;
varying vec2 var_vertTexCoord;
${frag_functions_default}
void main(){
vec2 st = var_vertTexCoord.xy /u_resolution.xy;
st = fract(st+u_time/20.);
vec2 originalSt = st;
// st.y = 1.0 - st.y;
// vec3 color = vec3(st.x,st.y,1.0);
//st.x+=rand(st+u_time/100.)/50.;
st.x+=texture2D(u_tex,st).r/10.;
st.y+=texture2D(u_tex,st).g/10.;
st.y+=texture2D(u_tex,st).b;
float ang = atan(st.y-0.5,st.x-0.5)*5.+u_mouse.x;
float dd = distance(st,vec2(0.5));
st = rotate2d(ang*3.14159*0.2)*(st-0.5)+0.5;
st-=0.;
float grid = 5.+sin(u_time/5.)*3.+ sin(st.y*(15.)+st.x*(15.)+u_time)*1.;
vec2 f_st = fract(st*grid);
float mask = 1.-step(0.4,distance(f_st,vec2(0.5)));
float grid2 = 200.+sin(u_time/5.)*100.+ sin(st.y*15.+st.x*15.+u_time)*1.;
vec2 f_st2 = fract(st*grid2);
float mask2 = 1.-step(0.8,distance(f_st2,vec2(0.5)));
vec2 i_st = floor(st*grid);
st.x+=rand(st+u_time/100.)/2.5;
// st.y+=cnoise(vec3(st*40.,u_time))/100.;
// st.x+=cnoise(vec3(st*40.,u_time))/100.;
// st.y+=cnoise(vec3(st*200.,u_time))/100.;
// st.x+=cnoise(vec3(st*200.,u_time))/100.;
ang = atan(st.y-0.5,st.x-0.5);
// st.x+=sin(ang/10.);
// st.y+=cos(ang/10.);
st = floor(st*10.)/10.;
vec3 color = texture2D(u_tex,st).rgb;
// color+=color/2.;
// color*=color;
color*=mask*mask2;
color*=(1.-distance(originalSt,vec2(0.5)))*2.;
// color*=cnoise(vec3(originalSt*2.,u_time))+1.;
gl_FragColor= vec4(color,1.0);
}`;
function preload(){
theShader = new p5.Shader(this.renderer,vert,frag)
}
function setup() {
pixelDensity(2)
createCanvas(1000,1000);
frontGraphics = createGraphics(width,height);
webGlGraphics= createGraphics(width,height,WEBGL);
noStroke()
frontGraphics.background(0)
background(100);
mouseX=width/2
mouseY=height/2
}
function draw() {
theShader.setUniform('u_resolution',[width/1000,height/1000])
theShader.setUniform('u_time',millis()/1000)
theShader.setUniform('u_mouse',[mouseX/width,mouseY/height])
theShader.setUniform('u_tex',frontGraphics)
frontGraphics.push()
frontGraphics.translate(width/2,height/2)
for(var i=0;i<200;i++){
frontGraphics.push()
frontGraphics.noStroke()
frontGraphics.fill(colors[i%colors.length])
frontGraphics.rotate(i*PI/6+frameCount/500+mouseX/1000+mouseY/100)
frontGraphics.ellipse(0,0,width*map(mouseY,0,height,0,2),80+sin(frameCount/100)*width/i)
frontGraphics.pop()
}
frontGraphics.pop()
if (frameCount% 1000==0){
mouseX = random(width)
mousey = random(height)
}
clear(0,0,width,height)
webGlGraphics.push()
webGlGraphics.clear(0,0,width,height)
webGlGraphics.noStroke()
webGlGraphics.scale(0.1)
webGlGraphics.shader(theShader)
webGlGraphics.rotateY(0.1+frameCount/600+mouseX/200)
webGlGraphics.rotateX(0.1+frameCount/600+mouseX/200)
webGlGraphics.rotateY(0.01*frameCount)
webGlGraphics.sphere(width*4,width/4,200)
webGlGraphics.pop()
fill(0)
rect(0,0,width,height)
image(webGlGraphics,0,0)
}