見出し画像

Processing.pyでアート #10 Medal

前の記事で作った反応拡散系は、3色がぐるぐるするだけのシンプルなものでした。

方程式の反応に関する項を変えると、もっと複雑な模様が賭けるみたいです。

でも、反応項の式を自分で書くのは大変そう。いやそれも楽しいんだけど、乱数とかでそれっぽい関数が作れないかな...? って、前にもこんなことを思ったような...?

というわけで、前の記事(反応拡散方程式)と、前の前の記事(乱数行列&非線形変換)のコードを組み合わせ!

さらに、模様に対称性があったほうがカッコイイ!ということで少しアレンジしたものがこちら。

5回回転対称なこともあって、なんか勲章の模様みたいな感じ?

Processingのコードはこちらです。ほぼシェーダーを呼ぶだけ。

def setup():
    size(720, 720, P2D)

    global sh
    sh = loadShader("shader.frag")
    init()
            
# 背景と乱数シードのリセット
def init():
    background(255)
    # background(0) # 黒背景スタートも面白い感じ
    sh.set("seed", random(1))
    
            
def draw():
    for _ in range(10): # 早回し
        filter(sh)

def mousePressed():
    init()

sheder.fragに書いたGLSLはこちら。拡散反応方程式の反応項を、乱数行列と非線形変換で生成します。

uniform vec2 resolution;
uniform sampler2D texture;
uniform float seed;

float dx = 1.5/resolution.x;
float dy = 1.5/resolution.y;
float C = 0.2;
float S = 0.01;

const float PI  = 3.141592653589793;

float atan2(in float y, in float x){
    return x == 0.0 ? sign(y)*PI/2 : atan(y, x);
}

// -1~1のランダム
float rand(int i){
  return 2*fract(sin(i*12.9898+seed) * 43758.5453) - 1.;
}

// なにか非線形な関数
float act(float x){
  return sin(PI*x);
}

// 乱数行列との積 → 非線形変換
vec4 trans(vec4 v){
  mat4 m = mat4(rand(1), rand(2), rand(3), rand(4),
                rand(5), rand(6), rand(7), rand(8),
                rand(9), rand(10), rand(11), rand(12),
                rand(13), rand(14), rand(15), rand(16));
  vec4 w = m*v;

  return vec4(act(w.x), act(w.y), act(w.z), act(w.w));
}

void main() {
  vec2 uv = gl_FragCoord.xy / resolution;

  vec4 p0 = texture2D(texture, uv);
  vec4 p1 = texture2D(texture, fract(uv + vec2(+dx, 0)));
  vec4 p2 = texture2D(texture, fract(uv + vec2(-dx, 0)));
  vec4 p3 = texture2D(texture, fract(uv + vec2(0, +dy)));
  vec4 p4 = texture2D(texture, fract(uv + vec2(0, -dy)));

  float x = uv.x - 0.5;
  float y = uv.y - 0.5;
  float l = length(uv-0.5);
  float q = atan2(y, x);

  // RGB値と、座標を反映した何らかの値をもとに反応項を生成
  vec4 v_in = vec4(p0.rgb, sin(5*q));
  // vec4 v_in = vec4(p0.rgb, sin(5*q + 3*l)); // ねじるパターン

  vec4 react = S*vec4(trans(trans(v_in)));

  gl_FragColor = p0 + C*(p1+p2+p3+p4-4*p0) + react;
}

模様に対称性をもたせる工夫として、入力にRGB値の他に座標に依存する項を追加。反応拡散方程式の意味的には化学反応のルールが場所によって変化する、という状況に。こういう無茶苦茶な状況を作れるのはジェネラティブ・アートの特権ですね。

この「化学反応のルールが場所ごとに異なる反応拡散方程式」の利点の一つは、始状態が真っ白や真っ黒でも、ルールの差異が駆動力になって勝手に反応が始まること。

黒背景スタートだとこんな感じ。

あと反応項を生成するのに使う、座標に依存した変数の組み合わせを変えることで、パターンをねじったりできます。

この記事が気に入ったらサポートをしてみませんか?