← INDEX / 一覧 NYAMCO WORKS 36 / 71
p5.js sketch works/kamawanai/sketch.js runs here
作品はここで実行されます(後から差し替え)

WORK 36

No Matter

かまわない

YEAR
2026
TOOLS
p5.js
TECHNIQUE
noise / layered point field

One cloud of points, drawn thirty-four times, each pass a little lower. The positions never move; neither does the density, nor the shape of the flock. What drains away, pass by pass, is colour and size — that is, whether a point counts as good or bad to the one looking. Nothing is removed. It still reads as loss.

同じ点群を三十四回、少しずつ下へずらして重ねた。位置も、密度も、群れの形も、一度も変わっていない。段が下がるごとに抜けていくのは色と大きさの差——その点が見る側にとって good か bad か、という符号だけ。何も取り除いていない。それでも、失われたように読める。

八木重吉「うつくしいもの」を読んだ。「それが 敵であつても かまわない/及びがたくても よい/ただ 在るといふことが 分りさへすれば」。

三回ゆずっている。自分の中でも外でもいい、敵でもいい、届かなくてもいい。けれど捨てられているのは関係そのものではない。敵であることも、遠いことも、関係としては残る。手放されたのは、その関係が自分にとって得か損か、という符号のほうだった。

だから符号だけを抜いてみた。配置には指一本触れていない。

SOURCE / ソース
// #36 かまわない (Kamawanai)
//
// 八木重吉「うつくしいもの」——「それが 敵であつても かまわない」。
// 詩人が捨てたのは関係ではなく、その関係が自分にとって good か bad かという符号だった。
//
// 同じ点群を 34 回、少しずつ下へずらしながら描く。位置も、密度も、群れの形も、
// 一度も変わらない。段が下がるごとに抜けていくのは色と大きさ——つまり価値の表現だけ。
// 最下段では、点はすべて同じ灰色、同じ大きさになる。
// それでも配置は 1 ビットも失われていない。

export default function sketch(p) {
  const W = 720;
  const H = 720;

  const N = 300;          // 点の数(全段で共通)
  const LAYERS = 34;      // 段の数
  const TOP = 170;        // 最初の段の中心 y
  const BOTTOM = 575;     // 最後の段の中心 y

  const SPREAD_X = 268;   // 点群の横の広がり
  const SPREAD_Y = 44;    // 点群の縦の広がり(横長にして段の重なりを保つ)

  const BASE_R = 3.4;     // 価値が抜けたときの半径(全点共通)

  const paper = [252, 250, 245];
  // 中立は「薄い」ではない。暖色・寒色と同じ重さの灰にする——
  // 価値を抜いたときに点が弱く見えたら、それはもう別のことを言っている。
  const neutral = [104, 102, 100];
  const warm = [206, 92, 48];    // 価値 +
  const cool = [52, 96, 158];    // 価値 −

  let pts = [];
  let meanAbsV = 0.5;     // |v| の平均。大きさを抜くときに総量を保つための基準

  const mix = (a, b, t) => [
    a[0] + (b[0] - a[0]) * t,
    a[1] + (b[1] - a[1]) * t,
    a[2] + (b[2] - a[2]) * t,
  ];

  p.setup = () => {
    p.createCanvas(W, H);
    p.noLoop();

    const today = new Date();
    const seed =
      today.getFullYear() * 10000 + (today.getMonth() + 1) * 100 + today.getDate();
    p.noiseSeed(seed);
    p.randomSeed(seed);

    // 密度場からの棄却サンプリング。群れの形はここで一度だけ決まる。
    let guard = 0;
    while (pts.length < N && guard < N * 400) {
      guard++;
      const x = p.random(-SPREAD_X, SPREAD_X);
      const y = p.random(-SPREAD_Y, SPREAD_Y);
      const d = p.noise(x * 0.0042 + 120, y * 0.0135 + 120);
      if (p.random() > Math.pow(d, 2.6)) continue;

      // 価値。構造と近いスケールの別の場から取る——完全な独立ではなく、
      // 群れの濃いところに符号のかたよりが生まれるくらいの相関。
      const raw = p.noise(x * 0.0115 + 700, y * 0.0150 + 700);
      const v = p.constrain((raw - 0.5) * 3.0, -1, 1);

      pts.push({ x, y, v });
    }

    meanAbsV = pts.reduce((s, q) => s + Math.abs(q.v), 0) / Math.max(pts.length, 1);
  };

  p.draw = () => {
    p.background(paper[0], paper[1], paper[2]);
    p.noStroke();

    for (let L = 0; L < LAYERS; L++) {
      const t = L / (LAYERS - 1);        // 0 → 1(下へ)
      const e = 1 - t;                   // 価値の表現量。1 でフル、0 で完全に中立
      const cy = TOP + (BOTTOM - TOP) * t;

      for (const q of pts) {
        const target = q.v >= 0 ? warm : cool;
        const c = mix(neutral, target, e * Math.abs(q.v));

        // 大きさもまた価値の表現。抜けるのは点どうしの差であって、量ではない——
        // |v| の平均を基準にするので、大きい点は縮み、小さい点はふくらむ。
        const r = BASE_R * (1 + e * (Math.abs(q.v) - meanAbsV) * 1.5);

        p.fill(c[0], c[1], c[2], 44);
        p.circle(W / 2 + q.x, cy + q.y, r * 2);
      }
    }
  };
}