xxxxxxxxxx
280
const CYCLE = 100;
let sh;
const Pallete = ["#FF7F83","#FFFFFF","#D783FF"];
let col;
let geom;
let maxRadius,pipeR,maxY;
function setup() {
createCanvas(windowWidth, windowHeight,WEBGL);
//ortho
let dep = max(width,height);
ortho(-width / 2, width / 2, -height / 2, height / 2,-dep*3 , dep*3);
//shader
sh = createShader(vert,frag);
this.shader(sh);
sh.setUniform("u_resolution", [width,height]);
sh.setUniform("u_pixelDensity", pixelDensity());
sh.setUniform("u_lightDir", [0.7,0.5,-1]);
noStroke();
//setup
const segNum = 400;
const rotres =20;
pipeR = height*0.03;
const minY = -height/2 - pipeR*2;
maxY = height*0.1;
const midY = -height*0.5;
const minRadius = height*0.05;
maxRadius = height*0.1;
col = Pallete[int(random(Pallete.length))];
//ジオメトリ
let segPos = getSegPos(0,0,minY,midY,maxY,segNum,minRadius,maxRadius);
geom = new p5.Geometry();
let allpoints = [];
for(let i=0; i<segPos.length-1; i++){
let pos1 = segPos[i];
let pos2 = segPos[i+1];
let dir = p5.Vector.sub(pos2, pos1);
dir.normalize();
//点のxz座標 曲線のxz平面法線ってこと。。?
let tup = p5.Vector.sub(pos1, createVector(pos1.x, 0, 0));
tup.normalize();
//パイプの垂直ベクトルを規定する
let pdir = p5.Vector.cross(dir, tup);
//crossベクトルがないと0ベクトルになるのでスキップ?(原因がわからん、、)
if(pdir.magSq() == 0)continue;
let rpoints = [];
for(let n=0; n <= rotres; n++){
let rotang = TWO_PI / rotres * n;
let rotdir = getRotatePos(pdir, dir, rotang);
rotdir.normalize();
rotdir.mult(pipeR);
let rpos = p5.Vector.add(pos1, rotdir);
geom.vertices.push(rpos);
geom.uvs.push([i / (segPos.length -2), n / rotres]);
}
}
//スキップの可能性があるので、頂点数を再計算
geom.detailX = rotres;
geom.detailY = geom.vertices.length/(rotres+1)-1;
geom.computeFaces();
geom.computeNormals().averageNormals();
geom._makeTriangleEdges()._edgesToVertices();//make stroke vert
this._renderer.createBuffers('custom', geom);
}
function draw() {
background("#3C343C");
orbitControl();
setCol(col);
const frameRatio = (frameCount%CYCLE)/CYCLE;//0-1
rotateX(-PI/40);
rotateY(frameRatio*TAU);
this._renderer.drawBuffers('custom');
setCol("#EDB59B");
const coneH = height*0.4;
translate(0,maxY-pipeR*1.5+coneH/2,0);
cone(maxRadius+pipeR*2, coneH,30,1,false);
}
//回転行列から座標を算出 cv = 回転軸のベクトル
function getRotatePos(_pos,_cv,_angle)
{
let s = sin(_angle);
let c = cos(_angle);
let nx = _cv.x;
let ny = _cv.y;
let nz = _cv.z;
let mat = [
[c + nx*nx*(1-c), nx*ny*(1-c)-nz*s, nz*nx*(1-c) + ny*s],
[nx*ny*(1-c)+nz*s, c+ny*(1-c), ny*nz*(1-c)-nx*s],
[nz*nx*(1-c)-ny*s, ny*nz*(1-c)+nx*s, c+nz*nz*(1-c)]
];
let newPos = [];
for(let i = 0; i < mat.length; i++)
{
newPos[i] = mat[i][0]*_pos.x + mat[i][1]*_pos.y + mat[i][2]*_pos.z;
}
return createVector(newPos[0],newPos[1],newPos[2]);
}
function getSegPos(cx,cz,minY,midY,maxY,posNum,minRadius,maxRadius)
{
let posList = [];
for(let ratio = 0 ; ratio <100; ratio += 100/posNum){
const y = map(easingEaseOutCubic(ratio/100),0,1,minY,maxY);
let angleXZ = map(y,midY,maxY,0,1,true);
angleXZ = easingEaseInCubic(angleXZ)*TAU*4;
let radiusXZ = map(y,midY,maxY,0,1,true);
radiusXZ =easingEaseInCubic(radiusXZ)*(maxRadius-minRadius) + minRadius;
const x = cx + cos(angleXZ)*radiusXZ;
const z = cz + sin(angleXZ)*radiusXZ;
posList.push(createVector(x,y,z));
}
return posList
}
//_col color or number
function setCol(_col,_shader = sh,_uniformName = "u_col")
{
const col = typeof (_col) == "string" ? color(_col) : _col;
let colArray = col._array;
colArray.pop();
_shader.setUniform(_uniformName,colArray);
}
//cubic
function easingEaseInCubic (x) {
return pow(x,3);
}
function easingEaseOutCubic (x) {
return pow(x-1,3) + 1;
}
function easingEaseInOutCubic (x) {
if(x < 0.5)return 0.5 * pow(2*x, 3);
else return 0.5 * pow(2*(x-1), 3) + 1;
}
// SHADER
var 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);
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);
}
`;
var 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;
float random (in vec2 st) {
highp float a = 12.9898;
highp float b = 78.233;
highp float c = 43758.5453;
highp float dt= dot(st.xy ,vec2(a,b));
highp float sn= mod(dt,3.14);
return fract(sin(sn) * c);
}
float noise(vec2 st) {
vec2 i = vec2(0.);
i = floor(st);
vec2 f = vec2(0.);
f = fract(st);
vec2 u = vec2(0.);
u = f*f*(3.0-2.0*f);
return mix( mix( random( i + vec2(0.0,0.0) ),
random( i + vec2(1.0,0.0) ), u.x),
mix( random( i + vec2(0.0,1.0) ),
random( i + vec2(1.0,1.0) ), u.x), u.y);
}
float grid(vec2 uv){
uv *= 10.;
uv = fract(uv);
float v = uv.x >= 0. && uv.x < 0.1 || uv.y >= 0. && uv.y < 0.1 ? 1. : 0.;
return v;
}
float gridGra(in vec2 uv , float gridNum){
float scale = gridNum;
uv *= scale;
uv = fract(uv);
float o = abs(uv.y + -0.5)*2.;
o *= abs(uv.x + -0.5)*2.;
return o;
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec2 centerPos = var_centerGlPosition.xy/var_centerGlPosition.w;//スクリーン変換
centerPos = (centerPos + 1.0)*.5*u_pixelDensity;//gl_FragCoordと座標を合わせる pixelDensityによって係数が変化する
centerPos.x *= u_resolution.x/u_resolution.y;//gl_FragCoordと座標を合わせる
vec3 vertNormal = normalize(uNormalMatrix * var_vertNormal);
float dot = dot(vertNormal,-normalize(u_lightDir));
dot = pow(dot *.5 + .5,1.) ;
//texture
//vec4 smpColor0 = texture2D(u_tex, var_vertTexCoord);
float noise1 = noise((st-centerPos)*500.);
float noise2 = noise((st-centerPos)*1000.);
float tone = step(noise1,dot);
vec3 col = u_col * tone + (u_col-0.2) * (1.-tone);
col *= clamp(dot*1.5+0.5,0.,1.);
col += noise2*.25;
gl_FragColor = vec4(col,1.);
}
`;