xxxxxxxxxx
// TransformFeedbackによる動的更新のテスト。
// https://wgld.org/d/webgl2/w015.html
// じゃあ本題。パーティクル動かそう。
// これで:https://openprocessing.org/sketch/1821763
// 堂々と512x512の全画面でいくか。まあできるでしょ。
// できたよ
// おつかれさま~
// って思ったけどアスペクト比考慮するか
// 描画するときにたとえば横2縦1なら2/1で横を割ればいい
// 単純にw/hで横を割ればいいと思う?
// 横1縦2の場合は縦に1/2を掛けることになるわね
// つまり横長の場合はvec2(h/w,1)を掛ける
// 縦長の場合はvec2(1,w/h)を掛ける
// スマホの方、死ぬほど重いですね...
// ていうか本家のparticleも重くなってるし
// あんなヌルヌルだったpavelさんの流体シミュレーションもめっちゃカクカク
// どうもスマホに原因があるみたい
// まあ3年ものだし...そのうち新しくなったら試してみよ
// 今興味あるのはこのp5wgexを作り始めたころ話題になってたmikuさんの粘性流体のやつ
// 原因スマホだと思うよ
// pavelさんのあれ、p5もThreeも使ってないから。まあp5はそもそもwebgl libraryではないけれど...
// ごめんなさいuMouseをuAspectFactorで割らないとまずかったですね
// スマホでもヌルヌル動くやん。なんじゃーい。一時的な不具合だったのね。
// ポインタ複数にしたい。foxIA使えばできる。んで、まあ、
// タッチの場合です。
// 単純に増やせばいいと思う。vを配列にして、全部足して平均を取って、それをvelocityに加えて更新する形。
// uniformによって個数を渡す必要があると思う。
const ex = p5wgex;
let _node;
const _SIZE = 512;
let acceleration = 0;
const _timer = new ex.Timer();
let pfc;
let IA;
let LC;
// vec3
// 重心と方向
// 重心をマウスで動かし
// 方向は速度を随時足す感じで
// 速度は重心位置とマウス位置で計算
const vs =
`#version 300 es
in vec4 aPV;
out vec4 aNextPV;
uniform vec2 uMouse;
uniform float uAcceleration;
uniform vec2 uAspectFactor;
const float SPEED = 0.05;
void main(){
// 位置と速度を抽出
vec2 position = aPV.xy;
vec2 velocity = aPV.zw;
// マウスによる速度の遷移
vec2 v = normalize(uMouse / uAspectFactor - position) * 0.2;
// 遷移して正規化する
vec2 w = normalize(velocity + v);
// 更新
position += w * SPEED * uAcceleration;
velocity = w;
aNextPV = vec4(position, velocity);
// 位置はfsに送る
gl_Position = vec4(position * uAspectFactor, 0.0, 1.0);
gl_PointSize = uAcceleration + 0.1; // 加速度に応じて点の大きさを変える
}
`;
const fs =
`#version 300 es
precision highp float;
uniform vec4 uColor;
out vec4 particleColor;
void main(){
// ここでalphaを0.0にすると加算合成にできる
particleColor = uColor * vec4(vec3(uColor.a), 0.0);
}
`;
function setup() {
_timer.initialize("slot0", {scale:5000}); // 5秒周期
createCanvas(window.innerWidth, window.innerHeight, WEBGL);
pixelDensity(1);
_node = new ex.RenderNode(this._renderer.GL);
_node.registPainter("particle", vs, fs, ["aNextPV"]);
// SIZExSIZE個のパーティクルを用意
const data = new Array(_SIZE * _SIZE);
for(let y=0; y<_SIZE; y++){
for(let x=0; x<_SIZE; x++){
const i = x + y*_SIZE;
const px = x*2/_SIZE-1 + 1/_SIZE;
const py = y*2/_SIZE-1 + 1/_SIZE;
data.push(px, py, 0, 0);
}
}
_node.registFigure("particle", [
{name:"aPV", size:4, data:data, usage:"dynamic_copy", outIndex:0},
{name:"aNextPV", size:4, data:data, usage:"dynamic_copy", outIndex:0}
]);
// おわりです。
pfc = new ex.PerformanceChecker(this.canvas);
LC = new foxIA.Locater(this.canvas, {factor:0.1});
_node.registTexture("logo", (function(){
const gr = createGraphics(width, height);
gr.textAlign(CENTER,CENTER);
gr.textStyle(ITALIC);
gr.textSize(20);
gr.fill(255);
gr.text("Transform feedback", width/2, height/2);
return gr;
})());
}
function draw() {
pfc.update();
LC.update();
_node.clear(0);
if (LC.isActive()) {
acceleration = 1.0;
} else {
acceleration *= 0.95;
}
// アスペクト調整
const aspectFactor = [];
if (width > height) {
aspectFactor.push(height/width, 1);
} else {
aspectFactor.push(1, width/height);
}
const p = LC.getPos({normalize:true});
const t = _timer.getElapsed("slot0"); // 経過秒数
const particleColor = ex.hsvArray(fract(t), 0.8, 1);
particleColor.push(1);
_node.use("particle", "particle", "points")
.setUniform("uMouse", [p.x*2-1, 1-p.y*2])
.setUniform("uAcceleration", acceleration)
.setUniform("uColor", particleColor)
.setUniform("uAspectFactor", aspectFactor)
.drawArrays("points", {blend:"blend"})
.swapAttribute("aPV", "aNextPV")
.unbind();
_node.renderTexture("tex", "logo", {blend:"blend", depthTest:"disable"});
_node.flush();
}