High Level Shader Language
High Level Shader LanguageないしはHigh Level Shading Language(ハイレベル シェーダー ランゲージ、- シェーディング - 、略称: HLSL)はマイクロソフトによって開発されたDirect3D APIで使われるプロプライエタリなシェーディング言語である。日本語では高級シェーダー言語(こうきゅうシェーダーげんご)と呼称される。
HLSLはOpenGL標準で使われるシェーディング言語であるGLSLと(機能的には)類似の物である。また、NVIDIAと協力して開発されたことから、言語文法がCg(C for Graphics)言語に非常によく似ている。
目次 |
[編集] 開発経緯
Direct3D 7まではグラフィックスカードに実装された固定パイプラインおよびハードウェア機能を駆使して3Dグラフィックスシーンを構築していたが、グラフィックス表現の柔軟性を向上させるべく、Direct3D 8ではプログラマブルシェーダーが搭載された。これによって、グラフィックスアプリケーション開発者がグラフィックス描画アルゴリズムをソフトウェアによってカスタマイズすることが可能となった。しかし、Direct3D 8で使用できるシェーダー言語はアセンブラ(低級言語)であったため、開発効率やプログラムコードの再利用性に限界があった。それを解消するべく、C言語風の宣言文や制御文などの記法を可能とした高級言語HLSLが開発されることとなった。
[編集] プログラマブルパイプラインステージ
HLSLによってプログラム可能なグラフィックスパイプラインステージは、対応するDirect3Dのバージョン(シェーダーモデル)によって異なる。
- Direct3D 9の場合(シェーダーモデル1.x~3.0)は、頂点シェーダー(バーテックスシェーダー)およびピクセルシェーダー(OpenGLにおけるフラグメントシェーダーに相当)の2つである。
- Direct3D 10.xの場合(シェーダーモデル4.x)は、頂点シェーダー、ジオメトリシェーダー(OpenGLではプリミティブシェーダーとも呼ばれる)、そしてピクセルシェーダーの3つである。
- Direct3D 11.xの場合(シェーダーモデル5.0)は、頂点シェーダー、ハルシェーダー(OpenGLにおけるテッセレーション制御シェーダーに相当)、ドメインシェーダー(OpenGLにおけるテッセレーション評価シェーダーに相当)、ジオメトリシェーダー、ピクセルシェーダー、そしてコンピュートシェーダー(計算シェーダー、演算シェーダー)の6つである。ただしコンピュートシェーダーだけはグラフィックスパイプラインとは独立して動作させることもできる。
頂点シェーダーはアプリケーションによって提供(入力)される頂点それぞれについて実行され、主に以下の処理を担当する。オブジェクト空間から視空間への頂点座標変換やテクスチャ座標の生成、また頂点の接線や従法線や法線ベクトルのような光線の係数の計算などである。頂点シェーダーを通して頂点のグループ(三角形であれば通常は3個)が入力された時、出力座標はその領域内で画面上のピクセルを決めるために補間される。この処理はラスタライゼーションとして知られている。これらのピクセルそれぞれがピクセルシェーダーを通ることで、結果としてスクリーン上の各点の色が計算される。
また、Direct3D 10/11インターフェイスやDirect3D 10/11ハードウェアを使うアプリケーションは、頂点シェーダーステージの後にジオメトリシェーダーを指定することもできる。このシェーダーは三角形の三頂点を入力に取り、それから追加の三角形を生成し(隙間なく埋める)、ラスタライザに送り込む。
なお、HLSLで使用可能なパーリンノイズ生成関数であるnoise()は、テクスチャシェーダーと呼ばれる特殊なシェーダーステージでのみ利用が可能となっている。
[編集] コード例
以下にDirect3D 10/11向けHLSLを用いた、単純なHalf Lambert照明モデルおよびPhong照明モデル(Blinn-Phong)の頂点シェーダーおよびピクセルシェーダーのプログラムを示す (動的分岐によって照明モデルを切り替える例であるが、これはいわゆるウーバーシェーダー(uber-shader)なので、実行速度効率などは考慮していないことに注意されたい)。
// Shader Constants. matrix TrWorldViewProj; matrix TrWorld; float4 LightPosition; float3 EyePosition; float4 DiffuseColor; float4 SpecularColor; float SpecularPower; bool IsPhongModel; struct BasicVSOutput { float4 Pos : SV_POSITION; float3 WPos : TEXCOORD1; float3 WNormal : NORMAL0; }; typedef BasicVSOutput BasicPSInput; // Vertex Shader Program. BasicVSOutput BasicVS(float3 pos : POSITION0, float3 normal : NORMAL0) { BasicVSOutput output = (BasicVSOutput)0; output.Pos = mul(float4(pos, 1), TrWorldViewProj); output.WPos = mul(float4(pos, 1), TrWorld).xyz; output.WNormal = mul(normal, (float3x3)TrWorld); return output; } float4 CalcLambert(float3 light, float3 wnormal) { // Half Lambert. float lambert = dot(light, wnormal); lambert = lambert * 0.5f + 0.5f; lambert *= lambert; return lambert * DiffuseColor; } float4 BasicLambert(BasicPSInput input) { const float3 light = normalize(LightPosition.xyz - input.WPos); const float3 normal = normalize(input.WNormal); return CalcLambert(light, normal); } float4 BasicPhong(BasicPSInput input) { // Phong lighting with specular. const float3 eye = normalize(EyePosition - input.WPos); const float3 light = normalize(LightPosition.xyz - input.WPos); const float3 halfway = normalize(light + eye); const float3 normal = normalize(input.WNormal); const float specular = pow(max(dot(normal, halfway), 0.0), SpecularPower); return CalcLambert(light, normal) + specular * SpecularColor; } // Pixel Shader Program. float4 BasicPS(BasicPSInput input) : SV_TARGET0 { if (IsPhongModel) { return BasicPhong(input); } else { return BasicLambert(input); } }
例のように、ピクセルシェーダーによってピクセル単位の正規化法線ベクトルを求めることにより、Direct3D 7以前の固定機能シェーダーでは実現が難しかったPer-Pixelライティングが容易に実装可能となっている。 もちろん、使用するシェーダーモデルおよび対応するハードウェアによっては、より複雑で長大なアルゴリズムを実装することもできる。単純な局所照明(ローカルイルミネーション)だけでなく、より厳密な物理ベースのレンダリング方程式に基づいた、大域照明(グローバルイルミネーション)モデルをHLSLによるプログラマブルシェーダーで実装することで、より現実に近いリアルタイム3Dコンピューターグラフィックスを実現することも可能となる。さらに、Direct3D 11ではコンピュートシェーダーを使って、GPUにグラフィックス用途以外の汎用計算を行なわせるGPGPUプログラムをHLSLで記述することも可能となる。
[編集] 対応環境
HLSLプログラムは主にホストとなるC++アプリケーションプログラムコードからDirect3D APIを使って入力と出力を管理する必要があるので、単体で動作させることはできない。なお、単体のコンパイラはマイクロソフトから無償提供されているDirectX SDK(あるいはバージョン8.0以降のWindows SDK)に付属する。HLSLコンパイラfxc.exeによって出力されるのは、グラフィックスハードウェアのベンダに依存しない共通バイトコードであるため、一度コンパイルしておけば異なるハードウェアであっても動作させることができる。HLSLプログラムをサポートするのはDirect3D 9以降をサポートするシステムに限られるため、2013年4月現在ではWindows OSおよびXbox 360が主な動作環境である。
[編集] エフェクト
HLSL自体は、シェーダー関数および各シェーダーステージのエントリーポイント(いわゆるメイン関数)を記述するために使われるが、この複数のシェーダーステージをまとめて管理・適用する「エフェクト」と呼ばれる仕組みも存在する。つまり、例えば2つの頂点シェーダーエントリーポイントVS1(), VS2()と2つのピクセルシェーダーエントリーポイントPS1(), PS2()を単一のHLSLソースプログラムファイル(通例.fx拡張子が付けられ、エフェクトファイルと呼ばれる)に記述し、さらにVS1+PS1, VS2+PS2, VS1+PS2, VS2+PS1といったシェーダーステージの組み合わせ(パス)のほか、各種レンダリングステートの設定をエフェクトファイル中に記述して関連付けることができる。エフェクトを扱うAPIはDirect3DコアライブラリもしくはDirect3Dエクステンションライブラリ(D3DX)に用意されており、レンダリングパイプラインの管理をC++コードから分離することができる。
[編集] シェーダーモデル比較
[編集] ピクセルシェーダーの比較
| PS_1.0から1.3 | PS_1.4 | PS_2.0 | PS_2.0a | PS_2.0b | PS_3.0[1] | PS_4.0[2] | |
|---|---|---|---|---|---|---|---|
| 依存テクスチャ制限 | 4 | 6 | 8 | 無制限 | 4 | 無制限 | 無制限 |
| テクスチャ命令制限 | 4 | 6*2 | 32 | 無制限 | 無制限 | 無制限 | 無制限 |
| Position register | No | No | No | No | No | Yes | Yes |
| 命令スロット数 | 8 + 4 | 8 + 4 | 32 + 64 | 512 | 512 | ≥ 512 | ≥ 65536 |
| 実行命令数 | 8+4 | 6*2+8*2 | 32 + 64 | 512 | 512 | 65536 | 無制限 |
| テクスチャの間接数 | 4 | 4 | 4 | 無制限 | 4 | 無制限 | 無制限 |
| Interpolated registers | 2 + 8 | 2 + 8 | 2 + 8 | 2 + 8 | 2 + 8 | 10 | 32 |
| 命令予測 | No | No | No | Yes | No | Yes | No |
| Index input registers | No | No | No | No | No | Yes | Yes |
| Temp registers | 2 | 6 | 12から32 | 22 | 32 | 32 | 4096 |
| Constant registers | 8 | 8 | 32 | 32 | 32 | 224 | 16x4096 |
| Arbitrary swizzling | No | No | No | Yes | No | Yes | Yes |
| Gradient instructions | No | No | No | Yes | No | Yes | Yes |
| Loop count register | No | No | No | No | No | Yes | Yes |
| Face register (2-sided lighting) | No | No | No | No | No | Yes | Yes |
| 動的フロー制御 | No | No | No | No | No | 24 | Yes |
| ビット演算 | No | No | No | No | No | No | Yes |
| 整数演算 | No | No | No | No | No | No | Yes |
- PS_2.0 = DirectX 9.0のオリジナルのShader Model 2の仕様である.
- PS_2.0a = NVIDIA GeForce FXに最適化されたモデル。
- PS_2.0b = ATI Radeon X700, X800, X850のシェーダーモデル, DirectX 9.0b.
- PS_3.0 = Shader Model 3.
- PS_4.0 = Shader Model 4.
実行命令数において"32 + 64"というのは"32のテクスチャ命令と64の算術命令"を意味する。
[編集] 頂点シェーダーの比較
[編集] Vertex shader comparison
| VS 1.1 | VS_2.0 | VS_2.0a | VS_3.0[1] | VS_4.0[2] | |
|---|---|---|---|---|---|
| 命令スロット数 | 128 | 256 | 256 | ≥ 512 | 4096 |
| 最大命令実行数 | 不明 | 65536 | 65536 | 65536 | 65536 |
| 命令予測 | No | No | Yes | Yes | Yes |
| 一時レジスタ(Temp Registers) | 12 | 12 | 13 | 32 | 4096 |
| 定数レジスタ(constant registers) | ≥ 96 | ≥ 256 | ≥ 256 | ≥ 256 | 16x4096 |
| 静的フロー制御 | 不明 | Yes | Yes | Yes | Yes |
| 動的フロー制御 | No | No | Yes | Yes | Yes |
| 動的フロー制御の深度 | No | No | 24 | 24 | Yes |
| Vertex Texture Fetch | No | No | No | Yes | Yes |
| テクスチャサンプラーの数 | N/A | N/A | N/A | 4 | 128 |
| Geometry instancing support | No | No | No | Yes | Yes |
| ビット演算 | No | No | No | No | Yes |
| 整数演算 | No | No | No | No | Yes |
- VS_2.0 = DirectX 9.0のオリジナルのShader Model 2の仕様である.
- VS_2.0a = NVIDIA GeForce FXに最適化されたモデル。
- VS_3.0 = Shader Model 3.
- VS_4.0 = Shader Model 4.