xxxxxxxxxx
208
let pg;
let pg2; //背景模様用
let blur;
const r = 200; //半径
function setup() {
createCanvas(500, 500,WEBGL);
pg = createGraphics(width, height);
pg.noStroke();
pg.fill('#ffffff');
pg2 = createGraphics(width, height);
pg2.noStroke();
background('#000000');
noStroke();
blur = createShader(shader1.vs, shader1.fs);
}
function draw() {
translate(-width/2,-height/2);
pg.push();
pg.background('#000000');
for(let i = 0;i<20;i++){
lissajous(pg,i*10);
}
grid(6,pg);
pg.pop();
pg2.background('#000000');
// 真ん中
pg2.push();
base(pg2);
pg2.pop();
// 右隣
pg2.push();
pg2.translate(180, -100);
base(pg2);
pg2.pop();
// 左下
pg2.push();
pg2.translate(-180, 100);
base(pg2);
pg2.pop();
// 右上
pg2.push();
pg2.translate(440, -120);
base(pg2);
pg2.pop();
shader(blur);
blur.setUniform(`u_tex`, pg);
blur.setUniform(`u_back`, pg2);
blur.setUniform(`u_time`, frameCount / 35);
blur.setUniform('u_resolution', [pg.width, pg.height]);
image(pg,0,0);
}
/** num個で分割したグリッドを画面いっぱいに生成する
* @method grid
* @param {Number} num 画面の分割数
*/
const grid = (num,pg) => {
const n1 = num + 1;
const margin_left = width / n1 / n1;
const margin_bottom = height / n1 / n1;
const nw = width / n1;
const nh = height / n1;
for (let i = 0; i < num; i++) {
for (let j = 0; j < num; j++) {
const x = nw * i + margin_left * (i + 1);
const y = nh * j + margin_bottom * (j + 1);
pg.circle(x + nw / 2, y + nw / 2, nw);
}
}
};
// リサージュ曲線
// 参考:https://processing-fan.firebaseapp.com/galary/lissajous-curve/index.html
function lissajous(pg,iTime){
const a = 3;
const b = 2;
const d = 1;
const u = 0.003;
const t = frameCount * u+iTime;
const s = (frameCount - 1) * u;
const preX = r * sin(a * s + d)* sin(a * s + d)* cos(b * s + d) + frameCount*0.001;
const preY = r * sin(b * s) * sin(a * s);
const x = r * sin(a * t + d)* sin(a * t + d)* cos(b * t + d) + frameCount*0.001;
const y = r * sin(b * t) * sin(a * t);
pg.circle(x+pg.width/2,y+pg.height/2,50);
}
// 模様
function base(pg) {
const r = 40;
const x = 0;
const y = 0;
const xx = r;
const yy = 140;
const xxx = yy;
const yyy = r;
for (let i = 0; i < 10; i++) {
pg.push();
pg.translate(x + i * r, y + i * r);
if (i % 2 === 0) {
pg.fill('#FFF5E0');
} else {
pg.fill('#C70039');
}
pg.rect(x, y, xx, yy);
if (i % 2 === 0) {
pg.fill('#FF6969');
} else {
pg.fill('#141E46');
}
pg.rect(xx, y, xxx, yyy);
pg.pop();
}
}
keyPressed = () => {
if (key === 's') {
//saveCanvas(canvas, 'canvas', 'png');
saveGif('canvas', 4);
}
};
const shader1 = {
vs: `
precision highp float;
precision highp int;
attribute vec3 aPosition;
attribute vec2 aTexCoord;
varying vec2 vTexCoord;
uniform mat4 uProjectionMatrix;
uniform mat4 uModelViewMatrix;
void main() {
vec4 positionVec4 = vec4(aPosition, 1.0);
gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;
vTexCoord = aTexCoord;
}
`,
fs: `
precision highp float;
precision highp int;
varying vec2 vTexCoord;
uniform sampler2D u_tex;
uniform sampler2D u_back;
uniform float u_time;
uniform vec2 u_resolution;
void main() {
const float Pi = 6.28318530718;
const float Directions = 16.0; // BLUR DIRECTIONS
const float Quality = 20.0; // BLUR QUALITY
const float Size = 20.0; // BLUR SIZE
vec2 Radius = Size/u_resolution.xy;
vec2 uv = vTexCoord; // / u_resolution.xy;
vec4 Color = texture2D(u_tex, uv);
for( float d=0.0; d<Pi; d+=Pi/Directions){
for(float i=1.0/Quality; i<=1.0; i+=1.0/Quality){
Color += texture2D( u_tex, uv+vec2(cos(d),sin(d))*Radius*i);
}
}
Color /= Quality * Directions - 15.0;
float c = step(0.8, float(Color));
if(vec3(c, c, c) == vec3(1.0, 1.0, 1.0)){
vec4 tex2 = texture2D(u_back,vTexCoord);
// 走査線を描く
float scanLineInterval = 1500.0; // 大きいほど幅狭く
float scanLineSpeed = u_time * 5.0; // 走査線移動速度
float scanLine = max(1.0, sin(uv.y * scanLineInterval + scanLineSpeed) * 1.6);
tex2.rgb *= scanLine;
gl_FragColor = tex2;
}else{
gl_FragColor = vec4(c, c, c, 1.0);
}
}
`,
};