openFrameworksでシェーダを扱う
openFrameworksでシェーダ扱える。ofShaderというオブジェクトがあるので、そのオブジェクトにvertexシェーダとfragmentシェーダのファイルを読み込ませて使う。僕の理解ではvertexシェーダが頂点の位置を動かし、fragmentシェーダがある頂点の色を指定する。
class ofApp : public ofBaseApp { public: void setup() { shader.load("vert.vs", "frag.fs"); } void draw() { shader.begin(); ofEllipse(mouseX, mouseY, 100, 100); shader.end(); } ofShader shader; }
こんな感じ。こうするとカーソルのいちに書いた円にシェーダが適用される。(言葉遣いあっているか不明。)
僕はGL3を使っているので、ofGLProgrammableRenderer.hをインクルードして、main関数内で ofSetCurrentRenderer(ofGLProgrammableRenderer::TYPE);
を呼ぶ。
vertexシェーダ
このvertexシェーダはたぶんy座標を累乗して返す。
#version 150 //OpenGL 3.2系はこれ uniform mat4 modelViewProjectionMatrix //このマトリクスにベクトルかけて返すと良い in vec4 position //いま取り扱っている座標が入っている void main() { vec4 pos = position; pos.y *= pos.y; //最終的にgl_PositionにぶちこめばOK gl_Position = modelViewProjectionMatrix * pos; }
ポイントはgl_Position
ですかね。
fragmentシェーダ
このfragmentシェーダは赤色でグラデーションをする。
#version 150 out vec4 outputColor; //ここに座標の色を入れればOK void main() { //sin, absなどは使える。gl_FragCoordで現在取り扱っている座標がわかる。 outputColor = vec4(abs(sin(gl_FragCoord.x / 20)), abs(cos(gl_FragCoord.y / 20)), 0, 1); }
ポイントはgl_FragCoord
やout vec4 outputColor
ですね。
色を渡す
fragmentシェーダに色を渡せる。ofSetColor()
で設定した色は、uniform vec4 globalColor
として使える。
追記:modelViewProjectionMatrixについて
とりあえずmodelViewProjectionMatrixに座標をかけるということをしていたが、いったいなんだったのか。それについて。
まず、3Dにおいて座標系がいくつかあるということを知らないといけない。
- Object Space
- オブジェクト自身が原点になっている座標系。物体ごとに座標系がある
- モデリングしてるときの座標系と考えればわかりやすいか。
- World Space
- ワールド座標系。どこどこになになにがある、といった感じ。
- これを仮想空間の座標系と捉えれば良さそう。
- Eye Space
- 視点座標系。たとえばカメラの位置とか。視点の位置が原点になる。
- Clip Space
- 視点座標系から少しズームしたりして、切り取った座標系。クリップ座標系というらしい。
- スクリーンみたいな感じだと思う。(それの逆?)
- Normalized Device Space
- すべてが絶対値1に収まるようにした座標系。
- Window Space
- ウィンドウの座標系。みんながまさに見ている座標系のこと。
- 原点が左上だったり左下だったり。。。
今回の話において重要なのは最初の4つ。んで、Object Space -> World Space -> Eye Spaceと変換をしていくのに、ModelViewMatrixが必要。さらに、Eye Space -> Clip Spaceに変換していくのにProjectionMatrixが必要なのだ。modelViewProjectionMatrixは、それを一緒にしてしまったものなのかもしれないと考えてみた。
たぶんin vec4 position
で得られるのはワールド座標系。そこでの情報を取り扱って、クリップ座標系にして返す。これがvertexシェーダのしていることなのだろうかと。
詳しい情報はこのpdfから得た。図もわかりやすい。http://www.inftyproject.org/suzuki/lectures/java/ToBegin.pdf
Light Leaksの話は、Window SpaceがProjection Spaceとなり、ミラーボールがmodelViewProjectionMatrixの逆行列となっていて、まさにWorld Spaceに投影しているんだと思う。だとすると、写真などから得られた情報からその行列を求める、みたいなことをしていたってことなのだろうか。逆問題。。。