/**/

チュートリアル 41:
シェーダ

グラフィックカードの主な目的1つは、2Dフレームバッファに3Dにオブジェクトを描画し、ディスプレイに表示することです。オブジェクトがどのように描画されるかは、呼び出される「シェーディングモデル」によって決まります。通常、シェーディングモデルには、オブジェクトの色と位置、ライティング(照明効果)の色と位置、テクスチャ座標、光沢があるかどうかといった表現される素材の特徴などの情報が与えられます。このような計算をハードウェアまたはソフトウェアによって実行するプログラムをシェーダと呼びます。以前は、慣習的にグラフィックカードは、オブジェクトにシェーディングモデルを適用するための固定型シェーディングパイプライン(fixed shading pipeline)を使用していましたが、近年では、グラフィックカードにプログラマブルパイプライン(programmagle pipeline)が実装され、固定型パイプラインの代わりにカスタムシェーダが実行されるようになりました。多くの固定型OpenGLパイプラインの制御方法についての概要は、「チュートリアル35:ライティングとフォグ」を参照して下さい。

ハードウェア動作環境:このチュートリアルすべてを実行するためには、プログラマブルシェーダをサポートしたグラフィックカード(例:ATI Radeon 9200, NVIDIA GeForce 5000シリーズ以降のグラフィックカード)が必要になります。また、グラフィックカード用のOpenGLドライバは最新のものにアップデートされることを推奨します。これは、Macintoshでは最新のOSアップデートにより提供されています。PCの場合はグラフィックカードの製造元、もしくはコンピュータの製造元から最新のドライバを得ることができます。

フラットシェーディング

ライティング(照明)を考慮した最もシンプルなシェーディングモデルの1つに、フラットシェーディングまたはファセットシェーディングと呼ばれるものがあります。この方法では、各々のポリゴンは1つの色だけを持ちますが、この色は標準的な状態の表面に対するライティング特性(プロパティ)に基づいて決定されます。チュートリアル35で見たように、これを行うためには、Jitter OpenGLオブジェクト(例:jit.gl.gridshape)の lighting_enable アトリビュートを1にセットします。

最初に

・Jitter Tutorial フォルダの41jShaders.patというチュートリアルパッチを開いて下さい。Start Rendering と表示された toggle ボックスをクリックして下さい。

lighting_enable $1 と書かれたメッセージボックスオブジェクトの上にある toggle をクリックして、トーラスを描いている jit.gl.gridshape オブジェクトのライティング(照明効果)をオンにして下さい。smooth_shading アトリビュートはデフォルトでは 0 になっています。

トーラスのライティングが変化したことに気づくと思います。最初はぼんやりとした灰色だったものが、このような輝きを持った灰色として描かれているのを見ることができるでしょう。


レンダリングされたトーラスはフラットシェーディングで表示されています.

スムーズシェーディング

これでも十分価値があると思うかもしれませんが、現実に存在するほとんどのオブジェクトは表面全体にわたってスムーズな変化をもっています。「グロー・シェーディング」(1971)は通常の表面とライティング特性に基づいて頂点ごとに色の計算を行うことにより、この問題に効率よく対処する最初のシェーディングモデルの1つでした。この方法では、スムーズシェーディングによる表示のために、ポリゴン全体にわたって線形補間を行っています。表面を表すために用いるポリゴンの数が小さい場合、この単純なアプローチによる「不自然さ」は奇妙なものと感じられるかもしれませんが、数多くのポリゴンを使用した場合、この不自然さは最小限に抑えることができます。このシェーディングモデルの計算効率によって、グロー・シェーディングは非常にポピュラーなものとなり、現在でも、コンピュータグラフィックカードによって使用される基本的なシェーディングモデルとして、シェーディングパイプラインの中に標準装備されています。Jitter では、smooth_shadhing アトリビュートを1 にセットすることによって行うことができます。私たちのパッチで実際に行ってみましょう。 jit.gl.gridshape オブジェクトの dim アトリビュートを変化させると、ポリゴン数が増加、減少します。

smooth_shading $1 と書かれたメッセージボックスに接続されているトグルボックス をクリックして下さい。パッチの右下隅にある dim $1 $1 と書かれたメッセージボックスに接続されているナンバーボックスを変化させて、ポリゴン数を増加、減少させてみて下さい。


スムーズシェーディングでレンダリングされたトーラス

ピクセル単位のライティング (Per-Pixel Lighting)

上記のように、少ないポリゴン数でのスムーズシェーディングは不自然に見えてしまいます。これは、まさに頂点をベースとして、ポリゴンを横切るように補間を行うというライティングの演算の実行方法に起因するものです。フォンシェーディング(1975)は、ポリゴンを横切る頂点間の色の変化を滑らかにするだけでなく、ポリゴンを横切るそれぞれの頂点の表面法線間をも滑らかにし、断片(あるいはピクセル)ごとの色を滑らかにされた法線とライティングのパラメータに基づいて計算します。ピクセルベースで行うライティングの演算は「ピクセル単位のライティング ( Per-Pixel Lighting)」と呼ばれます。これは、グローシェーディングより負荷の大きい処理になりますが、少ないポリゴンの場合にはより良い結果をもたらします。ピクセル単位のシェーディングはOpenGLに装備されたパイプラインではありません。しかし、私たちのオブジェクトにこのシェーディングモデルを適用するために、プログラマブルパイプラインにカスタムシェーダーを読み込ませることが可能です。

jit.gl.shader オブジェクトに接続されている read mat.dirperpixel.jxs と書かれたメッセージボックスをクリックして、ピクセル単位のライティングによるシェーダを読み込ませて下さい。

jit.gl.gridshape オブジェクトに接続されている shader shademe と書かれたメッセージボックスをクリックして、オブジェクトにシェーダを適用させて下さい。これは、オブジェクトの shader アトリビュートをセットし、 jit.gl.shader オブジェクトを名前(shademe)によって参照できるようにします。


トーラスにピクセル単位のシェーディングを適用します

プログラマブルシェーダ

1984年に、ロバート・クックは、「シェーディング言語」を用いて、いくつかの基本的なプリミティブから任意のシェーディングモデルを構築できる「シェードツリー」の概念を提唱しました。このシェーディング言語でそれを構築することによって、小数の定義済みシェーダではなく、無限のシェーダをサポートするためにレンダリングパイプラインを拡張することが可能になりました。クックのシェーディング言語は、ケン・パーリンによって制御構造を持つように拡張され、よく知られているPixarのRenderMan言語によって使用されるモデルになりました。より最近では、GPUに焦点をあてた Cg および GLSL シェーディング言語が同様の原理に基づいて作られています。このチュートリアルで使用される、ピクセル単位のライティング演算を含むカスタムシェーダは、GLSL によって書かれています。

 次の章では、独自のシェーダを書く方法についての簡単な手引きを行います。ここでは、既存のシェーダを使って、動的なシェーダのパラメータの変更を可能にする方法についての説明を続けましょう。グーチシェーディングは、主としてテクニカルイラストレーション向けに開発された、非フォトリアリスティック・シェーディングモデルです。これは、オブジェクトの輪郭を描き、暖色と寒色を使ってテクニカルイラストレーションで要求される深さの感覚を表現します。私たちは、カスタムシェーダーとして、輪郭の適用を無視したグーチシェーディングの簡略化バージョンを実装しています。

jit.gl.shader オブジェクトに接続された、read mat.gooch.jxs と書かれたメッセージボックスをクリックして、簡略化されたグーチシェーディングを読み込ませて下さい。


トーラスに適用された、簡略化されたグーチシェーディング

暖色が黄色、寒色がブルーになっている点に注意して下さい。これらの値は私たちのシェーダファイルの中でデフォルトとして定義されています。しかし、これらはパラメータとして公開されているため、jit.gl.shader オブジェクトへのメッセージによってオーバーライド(上書き)することができます。

・パッチ内のナンバーボックスを使って、メッセージ param warmcolor <red> <blue> <green> <alpha> および、param coolclolor <red> <green> <blue> <alpha>jit.gl.shader オブジェクトに送り、暖色と寒色に使われている色調を変更してみて下さい。

jit.gl.shaderオブジェクトにメッセージ dump params を送ってMax ウィンドウにパラメータを表示させたり、メッセージ getparamlist を送ってオブジェクトの最も右のアウトレット(ダンプアウトレット)からパラメータリストを出力させることによって、シェーダが使うことのできるパラメータを判断することができます。個々のパラメータの現在の値は、メッセージ getparamval <パラメータ名>によって問い合わせることができます。パラメータのデフォルトの値は、メッセージ getparamdefault <パラメータ名> によって問い合わせることができます。そして、パラメータの型は getparamtype <パラメータ名> によって問い合わせることができます。

頂点プログラム

シェーダはオブジェクトの表面の色を決定するためだけではなく、オブジェクトの頂点の位置やアトリビュートを決定するためにも使われます。これについては次のチュートリアルで見ていくことにします。さしあたって、ここでは頂点処理について見ていきましょう。これまでのシェーダでは、まさに様々なシェーダがピクセルをレンダリングする方法について説明してきました。実際に、これらのサンプルの各々のために私たちは2つのプログラムを実行させてきました。その1つは頂点を処理するためのもの(頂点プログラム)、そしてもう1つはピクセルのレンダリングのためのもの(フラグメントプログラム)です。頂点プログラムは、頂点ごとのライティング、色、その他のアトリビュートの演算を行うために必要であるのと同様に、オブジェクトの3D空間の中での変換(回転、移動 、拡大/縮小)を行うためにも必要なものです。私たちはパッチの中で jit.handle オブジェクトを使って、オブジェクトの移動や回転を見てきました。これは、明らかに何らかの頂点プログラムが実行されていたに違いありません。論理的には、頂点プログラムはプログラマブル頂点プロセッサで実行され、フラグメントプログラムはプログラマブルフラグメントプロセッサで実行されています。このモデルは、組み込まれている関数パイプラインに適合したものですが、このパイプラインもまた、頂点処理タスクとフラグメント処理タスクにわかれています。

しかし、これまでのサンプルの中での頂点プログラムは、見た目でわかるような、組み込みパイプラインの頂点プログラムとの顕著な違いを持つような操作を実行していませんでした。そこで、よりドラマティックな効果を持った頂点シェーダを読み込ませてみることにしましょう。vd.gravity.jxs シェーダは、3D空間内の点からの頂点の距離に基づいて、ジオメトリを 「押し」たり「引い」たりすることができます。

jit.gl.shaderオブジェクトに接続されている、read vd.gravity.jxs と書かれたメッセージボックスをクリックして、簡略化された重力頂点変位シェーダ(gravity vertex desplacement shader)を読み込ませて下さい。

・それぞれpram gravpos <x> <y> <z> および、param amount <n> というメッセージを出力する、pak オブジェクトとメッセージボックスに接続されたナンバーボックスの値を変更して、重力頂点変位シェーダの位置と量をコントロールして下さい。


頂点ディストーション.

まとめ

このチュートリアルでは、グラフィックスカードで利用できる組み込みの、そしてプログラマブルなパイプラインについて説明し、jit.gl.shader オブジェクトへカスタムシェーダを読み込むことによって、プログラマブルパイプラインをどのように使うことができるかについて示しました。シェーダはそれらの適用を受けることが可能で、それにより3Dオブジェクトは様々なエフェクトを得ることができます。私たちはまた、jit.gl.shader オブジェクトにメッセージを送ることによって、シェーダのパラメータのセットや問い合わせを行うことができます。