GLSLスクール第1回目とホットケーキ

こんにちは、いきなりですがGLSLスクールの第一回目に参加してきましたので自分なりに振り返りを綴っていきます。

今回参加することになったのはWebGLのデベロッパを務めておられるh_doxasさん、
https://webgl.souhonzan.org/こちらのサイトを運営されており
WebGLやJavaScriptを用いたインタラクティブなコンテンツをとにかく普及させようという熱意が凄い方、というのが
先生のサイトやQiitaの投稿を見ると何となく掴めたところです。

自分が当スクールを受講したいなと思ったきっかけが
「なんか面白いものを身に付けたくてWebで誰でも見れるWebGLってのみつけたけれど、取っ付き辛くて難解で分からないや」
みたいなところがスタートでした。
実際、WebGLを一から学ぶというような書籍は確かにチラホラ本屋さんで見かけましたが、いかんせんそれすらも
取っ付き辛くどうしたものか、と悩んでいるところで見かけてすぐ応募しました。

WebGLというのはまだまだ浸透した技術領域ではなく、またスクールとして開催するにあたって難解なものを、
不特定多数のランダムな受講者のレベルからスタートして身に付けさせるところまで持っていくというのは
その道で活躍されている方でもなかなか困難だというのは予想に難くないようです。
また、東京という土地柄はやはりこういうIT系(より分かりづらい表現)を学べる機会が他の都市の比ではないほど
盛んに開かれているのですが、その土地柄をもってしてもWebGLを教えますよってのは
おそらく先生ぐらいだけじゃないかなってぐらいな状況のようです。

さて、前置きはこのぐらいにしておいて、そもそもGLSLって何なのっていう前置きを講義の内容から
自分なりにピンポイントで連ねていきます。

今の時代、どのハードウェアにもだいたいCPUとGPUが搭載されております。
そしてGPUではより高速な処理を行うことが出来るので、結果的に処理の負荷の高い3Dグラフィックスなどを
実現するには、CPUではなくGPUの力を借りて行うことになります。
ただ、GPU自体は単なる高処理能力を持っているというだけなので、グラフィックスだけでなく機械学習にも
用いられることもあるようです。

そしてこのGPUを利用するためのシェーダ(シェーダという言葉は難しいのでカタカナの羅列としておく)が様々に存在している。

シェーダには有名なところだとDirectXやOpenGLなどの仲介役(API)があり
それらAPIはCPUからの命令(JavaScriptやC++などで書かれたもの)を
GPUに渡して処理を行わせるというフローになります。

他には、WebGLがあって名前の通りウェブを実行環境としていてJavaScriptのAPIとなっています。
(内部的にはOpenGL ES 2.0のグラフィックスAPIを踏襲したものである)

そしてお待たせしました、本題のGLSLの登場になります。ここからもう少し更に前置きが続いていきます。

GLSLは上記OpenGLでシェーダを制御するための記述をしておく言語という位置付けになります。
このGLSLという言語はWebGLのシェーダを制御するためにも用いられているのでGLSLと少しのJavaScriptを
学べばウェブというイージーアクセスな環境で、ユーザーが見る・体験するということが可能です。

ここで歴史の話を少し混ぜると、昔はこのシェーダを制御するという概念(仕組みあるいは言語)がなかったので
同じような表現しかできなかったが、GLSLなどの言語によってプログラマがGPUを利用したより自由な
表現を実現することが可能になったという経緯がある。

そうして生まれたGLSLを用いて、様々なシェーダを制御していくのですがその中でも代表的なものが

・頂点シェーダ
3DCGは不特定多数の頂点座標によって描かれることになるので、その頂点に対して様々な情報(例えばマウスの動き
など)をまずCPU側(JavaScriptやC++)で設定してGLSLの頂点シェーダに渡し、
その情報を元にGLSLで更に座標情報を変換・設定するという役割を果たす。
そしてこれらの頂点を結べば線や三角形、四角形などという図が描画される。
※頂点シェーダの数が多いほど処理の負荷は高くなる

・フラグメントシェーダ
最終的にスクリーンに描かれることになるピクセル1つ1つに対して行う処理を担う。
処理のフローとしては頂点シェーダが実行された後にフラグメントシェーダが実行される。
※画面解像度が大きくなるほど処理の負荷は高くなる

WebGLとGLSLではこの2つのシェーダを用いて描画を行います。

先ほどの歴史、という視点に立ち返るとかつてはグラフィックスを描画するまでに様々な情報(上記の頂点シェーダ
やフラグメントシェーダなど)が適切な順を追って処理され、最終的に絵として現れるというところに
介入の余地が無かったが、今日ではGLSLなどを用いてそこを制御可能になった。
先生はこれを「グラフィックスパイプラインが民主化された!」と表現されておりました。いいですね、そういうの好きです。

以上でざっとGLSLの概要となります、説明が適切かどうかも分からない上に、頭がかち割れちゃいそうだよ。

ここからはいよいよCPU側でアプリケーションを設定していきます。
処理のフローとしてはJavaScript(CPU)の処理で最終的にGPUを動かしたいので、
その仲介役を果たすGLSLに向かって

・CPU側からGLSLが認識できる変数・処理を記述
・GLSLにはGPUにさせたい処理を記述して再びCPU側に返す
・最終的な処理をCPUが実行する

こういう流れであると講義の内容とスライドから解釈して書き表してみましたが、もう何が何だか状態です。

今の段階で細部を事細かに把握するのは無理があるので、ここはふ〜んアンタが私のプロデューサー?ぐらいなクールさ
で流して次に進んでいきます。

ここからはGLSLの書き方について、ある程度かいつまんで振り返っていきます。

GLSLの特徴としては

・変数の種類を表す修飾子が存在する

例えば
attribute
attribute 修飾子は、アプリケーションから送られてきた「頂点の情報」が格納される変数に用いる
      上に記述した、頂点シェーダ内の定義をする際に用いられる

uniform
uniform  修飾子は、アプリケーション(javascript)から渡されるグローバル変数に用いる
      attribute修飾子に対し、GLSL内で変換されないのでどの頂点にも均一に作用する

varying
varying  修飾子は上に記述したシェーダ間のやりとり(フローとしては頂点シェーダ→フラグメントシェーダ)を
      する際に値の受け渡しをする変数に用いる

これらは避けて通れないので絶対に覚えるしかありません。

もう一つの特徴として
・変数のデータ型は型定義に厳しく、型を省略した暗黙の宣言はできない

それぞれデータ型は以下です。

int: 整数
float: 浮動小数点
bool: 真偽値
vec系: ベクトル(vec2 ~ vec4 があり中身は float)
mat系: 行列(mat2 ~ mat4 があり中身は float)
sampler系: サンプラ(始めはテクスチャと読み替えても良い)

GLSLは型定義に厳しいという特徴、初学者JavaScriptマンである僕が何気なく実行しようとしたら
いい感じでエラーを吐いてくれました。
以下に例として頂点シェーダの記述をしてみます。(サンプルファイルまんまです)

9行目の
gl_Position = vec4(position * 2.0 , 10.0);
この「2.0」を「2」とするとエラーが出ます。
vec4(浮動小数点)で宣言しているのに整数値が入ったことによるエラーでしょう。

他にもJavaScriptで定義するローカル座標(例えばマウスカーソルの位置)に対して
GLSLの座標はy軸は上下が逆になったりという特徴などもあります。

大事なことは、JavaScriptとGLSLの間で、どこを変換するのか(attribute修飾子を用いる)
どこを変換しないのか(uniform修飾子を用いる)かの違いを意識すること、ということです。

以上で一通りおさらい出来たと思うのでこの辺にしましょう。
(ロケーションという大事な概念を書いていませんが、実際のコードを目で追わないと何も分からないのであえて省きました)

本スクールでは、
「絵を出す」というしんどい過程については省略していて、その先で必要になってくるフローや書き方などについて
回を追って内容が濃く深くなっていくという構成になっているようです。
自分が意図する絵を出力するためにはCPU側の記述に対してGLSL側でどのような記述をするべきなのか、であったり
論理的で数学を用いた思考が必要になってきます。
しかし、一旦はそれを頭の片隅に置いやり、「とにかくコードや数式などを色々書いて、絵を動かしてみること」が
理解・上達の近道になると先生は仰られておりました。

冒頭で述べました通り「GLSL・WebGLはとにかく取っつき辛い」という理由から本スクールを受講された方達の心理を
上手に汲み取っておられていて、

・避けては通れないので必ず無理してでも覚えておかねばならないこと
・細部について暗記する必要は無いが、ざっとフローを把握する必要があること
・座学になりすぎないよう、ライブ感のあるハンズオンな形式となっていること

これらを意識した、とてもよく練られた講義内容だなと感じました。今から次回以降も楽しみです。

繰り返しになりますが「とにかくコードや数式などを色々書いて、絵を動かしてみること」
これを強く強く意識して臨むこと、ですね。
実際、適当に数値を変えたり数式をぶち込んでみたりして偶然得られた結果を基に、順を追ってフローを把握する
というのが初学者・あるいは数学を特に専攻したわけではなく、苦手意識もある人にとっての
唯一の道になることでしょう。
何かしらの絵が出るというのは大体の人にとって面白いですから。

最近はちょっとお休みしているのですが、以前ホットケーキ作りにハマっていた時期があって
とにかくいろんな具材を混ぜて美味しくなるかどうかであったり、
綺麗に焼くにはどうしたらいいかなど試してしたりしていました。

(バナナ、マンゴー、ドラゴンフルーツをミックスした生地は美味しかった記憶があります)

講義中に先生の言葉を聞いた時「お、3DCGってホットケーキやん」と自分の中の時制が一致した瞬間です。

「3DCGはゴールのない荒野である」先生はこうも仰られていて、荒野マニアの僕は思わず破顔してしまったのでした。
(実際には荒野マニアではありませんが、こういう言葉が好きだということです)