Generative風呂敷を作った。

myFuroshiki

これはなに?

こんにちは、senbakuです。
ジェネラティブな風呂敷をつくりました。

○ジェネラティブ?

p5.jsライブラリを用いたJavaScriptのコードで作品を作っています。
この写真の布も、もともとはコードで書かれています。
このように、コードで書いた作品を、"Creative Coding"や、"Generative Art"と呼びます。特にrandom関数や、noise関数などを用いるなどして、実行するたびに現れる画像が違っていたり、変化があるものを、Generative Artと呼ぶんだと思います。毎回生成されているイメージ。
↓リロードしてみると、毎回違う画像が生成されることが確認できます。

○風呂敷?

正方形の、便利な布です。結び方次第でいろんな大きさや形のものを包めます。
買い物のときにエコバッグ代わりによく使います。


どうやって作ったの?

○コード

コードは今回長いので、折りたたみます。

見たい人は、>こちら

~~~js
let num;
let palette_selected1;
let palette_selected2;
let h, w;
let wSize;
//Hello, I am @senbaku.
//2022-03-06
function setup() {
wSize = min(windowWidth, windowHeight)
//wSize = 5000;
createCanvas(wSize, wSize);
//pixelDensity(2)
angleMode(DEGREES)
noStroke();
noLoop();
palette_selected1 = random(palettes);
palette_selected2 = random(palettes);
num = random(100);

//randomEllipse
pg2 = createGraphics(wSize, wSize);
for (let i = 0; i < 700; i++) {
pg2.noStroke();
let rnum = random(70, 200)
pg2.fill(255, rnum);
pg2.ellipse(random(wSize), random(wSize), random() < 0.96 ? random(wSize * 0.001, wSize * 0.005) : random(wSize * 0.009, wSize * 0.02))
}
}

function windowRewSized() {
wSize = min(windowWidth, windowHeight)
resizeCanvas(wSize, wSize);
angleMode(DEGREES)
noLoop();
}

function draw() {
randomSeed(num)
background("#f1f4f8");
let gradientFill = drawingContext.createLinearGradient(
0, 0, wSize, wSize
);
gradientFill.addColorStop(0, "#f1f4f8");
gradientFill.addColorStop(1, &#039;#95adbe&#039;);
drawingContext.fillStyle = gradientFill;

rect(0, 0, wSize, wSize)

translate(wSize / 2, wSize / 2);
push();

for (let j = 0; j < 70; j += 1) {
let colNum1 = int(random(palette_selected1.length));
col1 = color(palette_selected1[colNum1]);
let colNum2 = int(random(palette_selected2.length));
col2 = color(palette_selected2[colNum2]);
let x = randomGaussian(0, wSize / 6);
let y = randomGaussian(0, wSize / 6);
push();
translate(x, y)
rotate(random(360))
h = random(wSize * 0.1, wSize * 0.8)
w = h * (random() < 0.8 ? random(0.05, 0.5) : 1);
let gradientFill = drawingContext.createLinearGradient(
-w / 2,
-h / 2,
w / 2,
h / 2
);
gradientFill.addColorStop(0, col1);
gradientFill.addColorStop(1, col2);
drawingContext.fillStyle = gradientFill;

rect(0, 0, w, h, w * 0.8)
pop();
}
pop();

//randomEllipse
push();
translate(-wSize / 2, -wSize / 2)
blendMode(OVERLAY)
image(pg2, 0, 0)

pop();

//randomShapes
push();
for (let i = 0; i < 80; i++) {
rotate(random(HALF_PI))
randomShapes(randomGaussian(0, wSize * 0.3), randomGaussian(0, wSize * 0.3), randomGaussian(wSize * 0.012, (wSize * 0.012) * 0.4))
}
pop();
}

function randomShapes(x, y, s) {
noFill();
stroke("#f1f4f8")
strokeWeight(s * 0.05);
strokeCap(ROUND);
strokeJoin(ROUND)
push();
let hs = s / 2;
translate(x + hs, y + hs);

if (random(1) > 3.0 / 4.0) {
ellipse(0, 0, s);
} else if (random(1) > 2.0 / 4.0) {
rect(0, 0, s, s)
} else if (random(1) > 1.0 / 4.0) {
triangle(0, -hs * 0.8, hs, hs, -hs, hs);
} else {
push();
strokeWeight(s * 0.15);
line(-hs, -hs, hs, hs);
line(hs, -hs, -hs, hs);
pop();
}

pop();
}

const palettes = [
["#e9dbce", "#fceade", "#ea526f", "#e2c290", "#6b2d5c", "#25ced1"],
["#223843", "#e9dbce", "#eff1f3", "#dbd3d8", "#d8b4a0", "#d77a61"],
["#e29578", "#ffffff", "#006d77", "#83c5be", "#ffddd2", "#edf6f9"],
["#e9dbce", "#ffffff", "#cc3528", "#028090", "#00a896", "#f8c522"],
["#e9dbce", "#f8f7c1", "#f46902", "#da506a", "#fae402", "#92accc"],
["#e42268", "#fb8075", "#761871", "#5b7d9c", "#a38cb4", "#476590"],
[&#039;#f9b4ab&#039;, &#039;#fdebd3&#039;, &#039;#264e70&#039;, &#039;#679186&#039;, &#039;#bbd4ce&#039;],
[&#039;#1f306e&#039;, &#039;#553772&#039;, &#039;#8f3b76&#039;, &#039;#c7417b&#039;, &#039;#f5487f&#039;],
[&#039;#e0f0ea&#039;, &#039;#95adbe&#039;, &#039;#574f7d&#039;, &#039;#503a65&#039;, &#039;#3c2a4d&#039;],
[&#039;#413e4a&#039;, &#039;#73626e&#039;, &#039;#b38184&#039;, &#039;#f0b49e&#039;, &#039;#f7e4be&#039;],
[&#039;#ff4e50&#039;, &#039;#fc913a&#039;, &#039;#f9d423&#039;, &#039;#ede574&#039;, &#039;#e1f5c4&#039;],
[&#039;#99b898&#039;, &#039;#fecea8&#039;, &#039;#ff847c&#039;, &#039;#e84a5f&#039;, &#039;#2a363b&#039;],
[&#039;#69d2e7&#039;, &#039;#a7dbd8&#039;, &#039;#e0e4cc&#039;, &#039;#f38630&#039;, &#039;#fa6900&#039;],
[&#039;#fe4365&#039;, &#039;#fc9d9a&#039;, &#039;#f9cdad&#039;, &#039;#c8c8a9&#039;, &#039;#83af9b&#039;],
[&#039;#ecd078&#039;, &#039;#d95b43&#039;, &#039;#c02942&#039;, &#039;#542437&#039;, &#039;#53777a&#039;],
[&#039;#556270&#039;, &#039;#4ecdc4&#039;, &#039;#c7f464&#039;, &#039;#ff6b6b&#039;, &#039;#c44d58&#039;],
[&#039;#774f38&#039;, &#039;#e08e79&#039;, &#039;#f1d4af&#039;, &#039;#ece5ce&#039;, &#039;#c5e0dc&#039;],
[&#039;#e8ddcb&#039;, &#039;#cdb380&#039;, &#039;#036564&#039;, &#039;#033649&#039;, &#039;#031634&#039;],
[&#039;#490a3d&#039;, &#039;#bd1550&#039;, &#039;#e97f02&#039;, &#039;#f8ca00&#039;, &#039;#8a9b0f&#039;],
[&#039;#594f4f&#039;, &#039;#547980&#039;, &#039;#45ada8&#039;, &#039;#9de0ad&#039;, &#039;#e5fcc2&#039;],
[&#039;#00a0b0&#039;, &#039;#6a4a3c&#039;, &#039;#cc333f&#039;, &#039;#eb6841&#039;, &#039;#edc951&#039;],
[&#039;#5bc0eb&#039;, &#039;#fde74c&#039;, &#039;#9bc53d&#039;, &#039;#e55934&#039;, &#039;#fa7921&#039;],
[&#039;#ed6a5a&#039;, &#039;#f4f1bb&#039;, &#039;#9bc1bc&#039;, &#039;#5ca4a9&#039;, &#039;#e6ebe0&#039;],
[&#039;#ef476f&#039;, &#039;#ffd166&#039;, &#039;#06d6a0&#039;, &#039;#118ab2&#039;, &#039;#073b4c&#039;],
[&#039;#22223b&#039;, &#039;#4a4e69&#039;, &#039;#9a8c98&#039;, &#039;#c9ada7&#039;, &#039;#f2e9e4&#039;],
[&#039;#114b5f&#039;, &#039;#1a936f&#039;, &#039;#88d498&#039;, &#039;#c6dabf&#039;, &#039;#f3e9d2&#039;],
[&#039;#3d5a80&#039;, &#039;#98c1d9&#039;, &#039;#e0fbfc&#039;, &#039;#ee6c4d&#039;, &#039;#293241&#039;],
[&#039;#06aed5&#039;, &#039;#086788&#039;, &#039;#f0c808&#039;, &#039;#fff1d0&#039;, &#039;#dd1c1a&#039;],
[&#039;#540d6e&#039;, &#039;#ee4266&#039;, &#039;#ffd23f&#039;, &#039;#3bceac&#039;, &#039;#0ead69&#039;],
[&#039;#c9cba3&#039;, &#039;#ffe1a8&#039;, &#039;#e26d5c&#039;, &#039;#723d46&#039;, &#039;#472d30&#039;],
["#3c4cad", "#5FB49C", "#e8a49c"],
["#1c3560", "#f2efdb", "#fea985", "#ff6343"],
["#e0d7c5", "#488a50", "#b59a55", "#bf5513", "#3b6fb6", "#4f3224", "#9a7f6e"],
["#DEEFB7", "#5FB49C", "#ed6a5a"]
];
~~~

  • たくさんのカラーパレットのなかから、2つのカラーパレットを、毎回ランダムに選び、角を丸めた四角の片方から片方へとグラデーションさせています。
  • 角丸の四角の配置は、中心にまとまっていてほしかったので、中心からrandomGaussianで適度にちらしています。
  • 小さな円、線のみの○、△、□、× の四種類の形をランダムに配置しています。

○出力

布に印刷するにあたって、200DPI程度の画像が必要となりました。
width,heightを5000に設定し、さらにpixelDensity(2)にし、倍の大きさのファイルにしました。縦横10000pixelにしました。これで110cm*110cmの印刷は問題ない画質でした。

○布化

  • ここで注文しました。
    https://realfabric.jp/
    二枚注文し、9日でとどきました。
  • 生地見本もあるので、迷ったらそれを買ってどの布にするか決めるといいかもしれないです。
  • ちょうど、以前Lushで買った風呂敷がポリエステル製だったので、ポリエステル生地の中でもその風呂敷に近い感触の、マイクロポリエステルを選びました。(Lushの風呂敷、安価で可愛いです!おすすめ。 https://www.lush.com/jp/ja/c/knot-wraps )
  • もう一枚、ポリエステルシフォンでスカーフ用にも印刷しました。そちらはまだ縫えていません(糸を切らしてしまった…)
  • 風呂敷の中でも大きい、三巾(105cm)程度に縫えるように、110cm*110cmで画像を用意し、繰り返し印刷で2m分頼みました。

なぜ作ってみたの?

twitterでPCJ主催で2月に行われた#AltEdu2022 を追うなかで、@TaznNishimura さんのツイートに出会いました。

以前、suzuriでバンダナに作品を印刷したことがあります。(https://suzuri.jp/senbaku/7363692/bandana/m/white)。
布になることに大興奮したのですが、「もっと大きな布にできたらいいのに」と思いました。なので、できると知り早速注文しました。

まとめ

  • 大きい布、いい。自分の作品が目の前に大きなサイズで存在しているのは、思った以上に感慨深いです。
  • 実用できる、風呂敷にしたのも良かった。自分の作品と買い物にいけます。
  • マイクロポリエステル、発色がとても良いので、このまま飾る用途でも良いかもしれない。展示とか、布でしても面白いかもしれない。
  • 次回fx_hashなどに作品を出すときは、布にしたり、印刷できるように、大きなサイズを書き出せる機能をつけたいと思った。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA