混沌与分形

混沌粒子

在这里插入图片描述
上图是使用粒子来对下面这张图进行描述的结果。
在这里插入图片描述
获取图片对应位置的像素值,然后通过鼠标位置与图片中心位置的旋转方式来获得粒子的变化。如果粒子足够小,那么粒子的旋转就变成了图片的旋转。
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)
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值