thebookofshaders/02/README-jp.md
2015-08-13 23:47:07 -07:00

6.1 KiB
Raw Blame History

ハロー・ワールド!

新しいプログラミング言語を学ぶときはたいてい最初に「Hello World」を表示します。一行のシンプルなプログラムで新しい世界に高らかにご挨拶というわけです。

しかしGPUの世界で文字を書くのは第一歩にしてはかなりの大仕事です。代わりに鮮やかな色でこの熱意を表現することにしましょう。

もしこの本をブラウザーで読んでいるのであれば、上のサンプルコードをクリックして好きなところを編集することができます。GPUは変更した内容を反映してコードをコンパイルし、シェーダーを即座に置き換えます。試しに6行目の値を書き換えてみましょう。

一見シンプルなコードですが、ここから多くのことが読み取れます。

  1. C言語と同じように、シェーダー言語は結果として色を返すmain()関数を持っています。

  2. 最終的なピクセルの色は、予約語として確保されたグローバル変数、gl_FragColorに割り当てられます。

  3. このCによく似た言語にはgl_FragColorのような組み込みの「変数」や「関数」、「型」があります。このサンプルでは浮動小数点精度を持つ4次元ベクトルvec4型が使われています。またこの後、vec3vec2のような型や、おなじみのfloatintboolなども登場します。

  4. vec4型をよく見ると、4つの引数はそれぞれ赤RedGreen、青Blue、透過度Alphaの各チャンネルに対応していることが分かるでしょう。またこれらの値が正規化されているnormalized、つまり0.0から1.0の値をとることも読み取れます。後ほど、値が正規化されていると変数間の写像に便利であることを学びます。

  5. プリプロセッサマクロが使えるのも、このサンプルから読み取れるもう一つの大事な「C言語的」特徴です。マクロはコンパイルの前に処理されます。マクロを使うとグローバル変数を定義#define)したり、#ifdef#endifを使って場合分けを行うことができます。全てのマクロの命令はハッシュタグ(#)で始まります。コンパイルの直前には全ての#defineの呼び出しが置き換えられ、#ifdef#ifndefといった条件文のチェックが行なわれます。上のサンプルでは、GL_ESが定義されているときにだけ2行目のコードを挿入します。GL_ESは多くの場合、モバイル機器やブラウザー上でコンパイルされたことを意味します。

  6. 浮動小数点型はシェーダーに不可欠で、その精度はとても重要な意味を持ちます。精度が低いとレンダリングが速くなる代わりに品質が下がります。もしこだわりたければ、GLSLでは浮動小数点を使うそれぞれの変数ごとに精度を指定できます。一行目のprecision mediump float;は、全ての浮動小数点型の変数に中レベルの精度を指定しています。より低い精度(precision lowp float;)や高い精度(precision highp float;)を選ぶこともできます。

  7. 最後に、そしておそらく一番大切なことですが、GLSLの仕様では変数の自動的な型変換は保証されていません。どういうことでしょう。メーカーは色々な方法でグラフィックカードを高速化しようとしますが、同時に最低限の仕様を満たす必要があります。自動的な型変換はこの最低限の仕様には含まれていません。上のサンプルではvec4型は浮動小数点精度を持っているので、float型の値が割り当てられることになっています。コードの一貫性を保ち、真っ白な画面で何時間もデバッグするのを避けるために、浮動小数点型の値には小数点(.)を使うことを習慣にしましょう。下記のようなコードはうまく動くとは限りません。

訳注gl_FragColorはGLSL1.3から非推奨になりました。以降のバージョンでは開発者が自由に名前をつけることができます。この本のサンプルは1.2以前のバージョンで書かれているため、gl_FragColorを出力用の変数として用います

void main() {
	gl_FragColor = vec4(1,0,0,1);	// ERROR
}

さて、冒頭のサンプルで大事なことはほとんど説明しました。そろそろコードをクリックして、学んだことをひととおり試してみましょう。エラーが起きたときはプログラムがコンパイルに失敗し真っ白な画面が表示されます。

次のような例を試すと面白いでしょう。

  • 浮動小数点型を整数型に置き換えてみましょう。グラフィックカードによって、そのまま動くこともエラーになることもあります。

  • 6行目をコメントアウトして好きな値を関数に割り当ててみましょう。

  • 特定の色を返す別の関数を用意してmain()関数の中で使ってみましょう。ヒント:下記のコードは赤色を返す関数です。

vec4 red(){
    return vec4(1.0,0.0,0.0,1.0);
}
  • vec4型の変数を生成するには幾つかの方法があります。他の方法を見つけてみましょう。下記は一つの例です。
vec4 color = vec4(vec3(1.0,0.0,1.0),1.0);

この章のサンプルはさほど面白くはありませんが、キャンバス上のピクセルを全て同じ色に変える最も基礎的な例です。この後に続く章ではピクセルの色を2種類の入力、空間画面上のピクセルの位置と時間ページがロードされてから経過した秒数を使って変化させる方法を学びます。