GLSL:実際GLSL書いてみる

GLSLのコードを書いてみよう

 ぜんぜん全く早速ではないですが、コード書きましょう。  以下、ほとんど[連載]やってみれば超簡単! WebGL と GLSL で始める、はじめてのシェーダコーディング(1) - Qiitaの引き写しなので、向こうの記事が消えてるとか、読んでもよくわからなかったときだけ読んでいただければよろしい。
 この学習日記の目的はは自分のためのメモなので、読まなくていいです。むしろ読むな!(笑)
 GLSLは、mainが呼び出されるCっぽい言語仕様になってるようで、基本次のような感じで書きます。

void main(void){
	// ここになんかいろいろ書く
}

 JavaScriptでいうところのonloadハンドラみたいなもんですかね。

色塗ってみよう

 で画面に何も映らないと意味ないんで、なにか描いてみる。

void main(void){
    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}

 これで、画面(というかポリゴンというか)全体を緑にできる。
 gl_FragColorってのが特殊な変数、というかグローバルプロパティというか、そんなやつなので、そこに色のデータを設定してやる、というのがこのコードの意味。
 vec4が4次のベクトルを作る関数で、各要素がR,G,B,αに対応している。
 んで、各値は0〜1の数値で表されるので、0101で緑の不透明で塗られる。
 なんで全画面が塗られるかというと、座標を指定してないので、全部同じに塗られた、ということらしい。

 ちなみに、0.0とか1.0とか書かずに0と1でいいんじゃねーの? って思うんだけど、GLSLは厳密にfloatとintを区別するらしく、ループカウンタとかフラグとかでもないかぎりfloatを使っていく(.付きの数字)のが基本みたい。
 さらについでの情報だけど、0.0は後ろを省略して0.とは書ける。若干タイプ数が減るぞ!!
 ついでのついでに、小数点の前が0の時も省略して.5とか書ける。完全に蛇足だが小数点のみだとエラー、.0は0.0として扱われる。

座標を組込もう

 で、次は座標を指定してみようというのがこのコード。

precision mediump float;

void main(void){
    float a = gl_FragCoord.y > 200.0 ? 1.0: 0.5;
    gl_FragColor = vec4(vec3(a), 1.0);
}

 gl_FragCoordに、現在処理中の座標が入ってるので、それを使ってgl_FragColorの値を変えれば、座標と表示色を関連づけられる、というスンポー。
 ちなみに、coordはcoordinate(座標)の略ですね。
 最初の行のprecisionは、まだよくわかんないんですが、これつけとかないとfloatでの変数定義が働かないのでつけてます。なんなんでしょうね。

 mainの次の行は三項演算子で座標200を起点に色を分けてます。どうやら演算はC言語のノリでやっていいようです。
 こういう単純なのはいいとして、線とか円とかどうすんだろ? って感じです。
 おそらく、行列変換とかあるんでしょうが、まだよくわからず。

 vec3(a)とやるとa,a,aが生成されるようです。この使い方面白いですね。
 普通のプログラミング言語だと、(a,a,a,1.0)ではなく((a,a,a),1.0)って展開されそうなのに。

距離で描こう

precision mediump float;

void main(void){
    float l = 32.0 / length(gl_FragCoord.xy -256.0);
    gl_FragColor = vec4(vec3(l), 1.0);
}

 gl_FragCoord.xyって書くと2次元(XY平面)のベクトルがとりだせるんで、そこから-256.0するとベクトル要素1つずつから256.0引ける。
 座標からそれぞれ、256.0引いたんで、座標系が右上に移動しているはず。GLSLは数学の座標系準拠でYは下からなのです。
 ベクトル計算が最初からできるようになっているのは非常に便利。
 一般的なプログラミング言語も、いいかげんベクトルと行列は標準の演算として持ってていいと思う。

 そんで出てきたベクトルの長さをlengthって関数で取り出す。簡単! ベクトル演算簡単で感動です。
 なお、GLSLを策定しているクロノスのサイトに行くと、リファレンスカードが用意されていて、いわゆるチートシートみたいなのも用意されてます。
 この中でGLSLのチートシートはWebGLの1.0を選んで出てきたPDFの3,4ページにいろいろ書いてある。
 プログラミング言語をいくつも身につけてる人は、 これ見ただけで結構全体がつかめるんじゃないでしょうか。
 私はいろんなプログラミング言語をやってみてますが、いまいち身についてない上に英語もあいまいなので、このシート見ても、いまいちです(笑)

 シートに乗ってた組み込み関数(Built-In Functions)には、次のような関数が並んでました。
 ざっと見た感じでは、ベクトル関連に必要そうなのが揃っているようです。というかこのへんGPUが持ってる命令とかなり対応してるんじゃなかろーか。GPUは詳しくないんでわかんないんですけど。
abs, acos, all, any, asin, atan, ceil, clamp, cos, cross, degrees, distance, dot, equal, exp, exp2, faceforward, floor, fract, greaterThan, greaterThanEqual, inversesqrt, length, lessThan, lessThanEqual, log, log2, matrixCompMult, max, min, mix, mod, normalize, not, notEqual, pow, radians, reflect, refract, sign, sin, smoothstep, sqrt, step, tan, texture2D, texture2D, texture2DLod, texture2DProj, texture2DProj, texture2DProj, texture2DProj, texture2DProjLod, texture2DProjLod, textureCube, textureCube, textureCubeLod

 でまーそうやって取り出した距離を適当な数字を割ることで輝度に変換して、そろそろおなじみのgl_FragColorにブッ込むと、(256,256)の位置に明るい球体的なものが出現する。
 全ピクセルでmainが実行されていて、「gl_FragColorは現在処理中の座標の色」というプロパティなのだ、という理解でいいのかな。
 だとすると単純でわかりやすいけど、迂闊な処理を書くと、一気に重くなりそうだなー。

 今日はここまで。