Processing.pyでアート #4 Shader
PCD2019のFMS_Catさんワークショップで教わったシェーダーが面白かったので、pythonモードでもやってみました!
まず以下のコードをProcessingで書いて、
def setup():
size(400, 400, P2D)
global sh
sh = loadShader("shader.frag")
def draw():
background(0);
noFill()
stroke(255)
strokeWeight(100)
rectMode(CENTER)
rect(width/2, height/2, 140, 140)
sh.set("time", frameCount*0.005)
filter(sh)
このProcessingのコードがおいてあるフォルダにdataフォルダを作って、その中に以下のshader.fragファイルを置きます。
(ということになってるけど、dataフォルダを作らず、.pydeファイルと.fragファイルを同じ場所に置いても動くっぽい)
uniform vec2 resolution;
uniform sampler2D texture;
uniform float time;
const float PI = 3.141592653589793;
void main(){
vec2 uv = gl_FragCoord.xy/resolution;
vec2 xy = uv-0.5;
float t = 10.*cos(PI*time);
float a = 0.8;
xy.x = xy.x+a*sin(xy.x*t)*sin(xy.y*t);
xy.y = xy.y+a*sin(xy.y*t)*sin(xy.x*t);
gl_FragColor = texture2D(texture, xy+0.5);
}
そうすると、Processingで描いた四角形をシェーダーでグネグネ曲げることができます!楽しい!
Pythonモードでの注意
これをpythonで書くときにハマったことはいくつかあって、ひとつは
sh = loadShader("shader.frag")
def setup():
size(400, 400, P2D)
def draw():
...
みたいに、setup()の外でグローバル変数を作ると同時にシェーダーを読み込むのはダメ、ということ。pythonは型宣言がないので、変数を作ったら同時に初期化しがち。setup()を呼ぶ前だと解像度が定まってないからシェーダー読めないのかな?
あとはシェーダーに時間を渡す際に、
sh.set("time", frameCount)
とするのもダメでした(常にtime=0になってしまう)。これ一見問題なさそうなんですが、シェーダー側でfloatで受け取るものは、こちらもfloatで渡す必要があるみたい(pythonって型を書かないのでこれもしばらく謎でした...)。frameCountに適当な計算をして小数にすればOKでした。
この記事が気に入ったらサポートをしてみませんか?