シェーダ
コンピュータグラフィックスのシェーダ(英: shader)は、主にライティング(光源計算)・シェーディング(陰影処理)とレンダリング(ピクセル化)を実行するためにグラフィック リソースに対して使用するソフトウェア命令の組み合わせである。「shade」とは「次第に変化させる」「陰影・グラデーションを付ける」という意味で、「shader」は頂点色やピクセル色などを次々に変化させるもの(より具体的に、狭義の意味で言えば関数)を意味する。
目次 |
解説 [編集]
技術的な視点から見るとシェーダは(オブジェクトの位置を計算するのとは違い)オブジェクトの色の計算を担当するレンダラの一部である。すなわち、CGレンダリングソフトはリアルタイム/非リアルタイムを問わず、ソフトウェアあるいはハードウェアによるシェーダを必ず備えていることになる。
GPUがシェーダ機能を強化するにつれ、OpenGLやDirect3Dといった主なグラフィックライブラリはAPIに専用のプログラマブル(プログラム可能)なシェーディング機能(プログラマブルシェーダ)を備えるようになった。OpenGLはバージョン1.5で、Direct3D(DirectX)はバージョン8でプログラマブルシェーダが導入された。近年はシェーダと言えば大抵プログラマブルシェーダのことを指す。
リアルタイム処理系におけるプログラマブルシェーダの隆盛 [編集]
従来、CADソフトやゲームなどのリアルタイム 2D/3Dグラフィックス アプリケーション開発者は、ハードウェア(グラフィックカードにおけるGPU)に固定機能として実装されていた「定形のパイプライン」(固定機能パイプライン)を使用してグラフィック表示を行なっていた。 しかし、多数のグラフィック表現技術が次々と開発されていく中で、それらの技術をGPUメーカーが逐一ハードウェアに実装していく形態は非効率であり、またユーザープログラマが新しい技術を試すにはメーカーの対応を待たねばならなかった。この問題を解決するアイディアとして、GPUのパイプラインをソフトウェアにより組み立てる「プログラマブル パイプライン」と呼ばれるアーキテクチャが構築されることになる。グラフィックパイプラインがユーザープログラマに対して開放されることで、新たな陰影処理や各種エフェクト(画面効果)を試験的に実装することが容易になり、先進的なGPUの機能を利用する優れた柔軟性と、表現力の爆発的な向上がもたらされた。 なお、従来のOpenGLあるいはDirect3DのAPIによって提供されていたシェーダは、固定機能シェーダと呼ばれ、プログラマブルシェーダと区別される。OpenGL 3.1、OpenGL ES 2.0、およびDirect3D 10以降はそれぞれ固定機能シェーダを完全に廃止しており、グラフィックパイプラインはプログラマブルシェーダによって記述することが必須となっている。
CGレンダリングソフトの多くは、最終的な出力結果を得るための計算モデルとしてグローバルイルミネーションやレイトレースといったレンダリング方程式に基づく、より厳密なモデルを採用しているが、モデリングやパラメータ設定の作業中は、プレビューのために描画品質を落としてOpenGLあるいはDirect3Dによってリアルタイム表示する必要がある。GPUが固定機能シェーダのみをサポートしていた頃は、プレビューは最終描画結果とは ほど遠いものであったが、プログラマブルシェーダをサポートするようになってからは、各CGソフトもプレビューにプログラマブルシェーダを使用するようになり、プレビューの品質が飛躍的に向上した。2009年現在、Autodesk 3ds Max、Autodesk Maya、Autodesk Softimage、およびNewTek LightWave 3Dといった有名なソフトウェアの最新版はいずれもプログラマブルシェーダによるプレビューを実装している。 また、近年シェーダはAdobe PhotoshopやAdobe Flashのように2DCGを主に扱うソフトウェアにもアクセラレータとして導入されることが多くなっている。ハードウェア(グラフィックカード)が一定のシェーダ機能を満たす場合、表示や応答が高速化されるなどのメリットがある。
シェーダの種類 [編集]
OpenGLとDirect3D 10では3種類のシェーダを使用できる。
- バーテックスシェーダ(頂点シェーダ)は頂点の集合に対してのみ作用し、位置、色、テクスチャマッピング座標といった頂点の属性だけを参照・変更できる(ただしシェーダモデル3.0で導入されたVertex Texture Fetching(VTF)を使用すると、テクスチャデータを参照することが可能となる)。バーテックスシェーダで計算された頂点は通常はジオメトリシェーダに渡されるか、そのままピクセルシェーダに渡される。
- ジオメトリシェーダ(プリミティブシェーダ)はピクセルシェーダに渡されるオブジェクト内の頂点の集合を加工するために使用される。ジオメトリシェーダ(プリミティブシェーダ)により、実行時に頂点数を増減させることが可能となる。
- ピクセルシェーダ(フラグメントシェーダ)は既存のプリミティブの各ピクセルに影響し、テクスチャを参照することでバンプマッピングやフォグ、シャドウ、ブルームといったエフェクトを最終レンダリング結果に適用する。
Direct3D 10のUnified Shader Model(統合シェーダモデル)は上記3つのシェーダを統合する。NVIDIAのFAQを参照のこと。
これらのシェーダはGPUのパイプライン内で実行される。下記はパイプライン内にどのように埋め込まれているのかを示す例である。
GPUパイプラインの概略 [編集]
- CPUは命令とジオメトリデータをグラフィックカードのGPUに送信する。
- バーテックスシェーダ内でジオメトリを変換しライティングの計算などを実行する。
- GPUにジオメトリシェーダが搭載されている場合はここでシーン内のジオメトリの変更を行う。
- これまでの処理で計算されたジオメトリをトライアングルセットアップに設定する。トライアングルはquadに変換される(1つのquadは2 × 2ピクセルのプリミティブである)。
- ピクセルシェーダを適用する。
- 視界判定を実行する。もし視界内にある場合はフレームバッファにピクセルを書き込む。
並列処理 [編集]
シェーダは同時に膨大な要素の集合に対して変換を適用するように記述される。例えばスクリーンの特定の範囲内の各ピクセルに対して、あるいはモデル内の全ての頂点に対して等である。これは並列処理に非常に適しており、多くの先進的なGPUではこれを促進するべくマルチコア設計となっており、処理効率を大幅に改善している。
なお、この並列処理における優位性を汎用計算に利用しようという試み(GPGPU)が近年活発化している。
シェーダのプログラミング [編集]
OpenGLのバージョン1.5からはGLSLというシェーダ言語を利用できる。
Direct3DのシェーダはHLSLという言語でプログラムする(ただしDirect3D 8ではアセンブリのみをサポートしていた)が、利用可能なシェーダプログラムの形式と機能はDirectXのバージョンによって異なる。また、GPUメーカーによっては独自拡張された機能や、未実装の機能が存在するため、完全に互換性のあるシェーダプログラムを記述するのが困難になっているのが実情である(Direct3D 10においては、最低限すべての機能を満たすことが仕様として要求されているため、この問題は解消されている)。
以下の表はDirectXのバージョンとシェーダのバージョン間の関係を示している。
| DirectX Version | Pixel Shader | Vertex Shader | Geometry Shader |
|---|---|---|---|
| 8.0 | 1.0, 1.1 | 1.0 | - |
| 8.1 | 1.2, 1.3, 1.4 | 1.1 | - |
| 9.0 | 2.0 | 2.0 | - |
| 9.0a | 2_A, 2_B | 2.x | - |
| 9.0c | 3.0 | 3.0 | - |
| 10.0 | 4.0 | 4.0 | 4.0 |
| 10.1 | 4.1 | 4.1 | 4.1 |
| 11.0 | 5.0 | 5.0 | 5.0 |
GLSLおよびHLSLはともにC言語に似た構文を採用しており、さらにベクトル演算を記述しやすいようにC++言語風の拡張を行なっているが、両者に互換性はない。
また、NVIDIAが開発したCgというシェーダ言語も存在し、OpenGLおよびDirect3D両環境で動作するプログラムを記述できる。なお、CgはNVIDIAがMicrosoftと緊密に協力して開発した言語であるため、HLSLと似た構文になっており、ある程度の互換性も確保されている。
Adobe Flash 11以降では、C言語風の Pixel Bender 3D から Adobe Graphics Assembly Language (AGAL) にコンパイルして使用できる。