High Level Shading Language

High Level Shading Language（ハイレベル シェーディング ランゲージ、略称: HLSL）はマイクロソフトによって開発された、Direct3D (DirectX) で使われるプログラマブルシェーダーのためのプロプライエタリなシェーディング言語である。かつては High Level Shader Language という呼び方もされていた。ただしMSDNの日本語版では、Direct3D 11がリリースされた後でも上位レベル シェーダー言語（じょういれべるシェーダーげんご）という訳語を使用している 。
HLSLはOpenGLで使われるシェーディング言語であるGLSLと（機能的には）類似の物である。また、NVIDIAと協力して開発されたことから、言語文法がCg（C for Graphics）言語に非常によく似ている。

開発経緯

Direct3D 7まではグラフィックスカードに実装された固定パイプラインおよびハードウェア機能を駆使して3Dグラフィックスシーンを構築していたが、グラフィックス表現の柔軟性を向上させるべく、Direct3D 8ではプログラマブルシェーダーが搭載された。これによって、グラフィックスアプリケーション開発者がグラフィックス描画アルゴリズムをソフトウェアによってカスタマイズすることが可能となった。しかし、Direct3D 8で使用できるシェーダー言語はアセンブラ（低級言語）であったため、開発効率やプログラムコードの再利用性に限界があった。それを解消するべく、C言語風の宣言文や制御文などの記法を可能とした高級言語HLSLが開発されることとなった。HLSLはDirect3D 9で初めて導入され、その後もDirect3Dとともに機能拡張が続けられている。
GDC 2016ではDirectX 12の今後の発展、そして新たな次期DirectXとシェーダーモデル6の開発に関して言及があり、HLSL言語仕様にも大きな機能追加が予定されていることが発表された。シェーダーモデル6.0ではWaveと呼ばれるSIMTスレッドグループの概念と各グループ内でのデータ交換のための組み込み命令が導入され、NVIDIA GPUのWarpおよびAMD GPUのWavefrontを標準化することが予定されている。

言語機能

HLSLの基本的な文法はC/C++に準ずるが、グラフィックスプログラムを記述するのに適した専用のベクトル・行列型や関数を備えている。数学関数の中にはC/C++標準ライブラリと同様のものも含まれる。また、Direct3D 10ではAPIの大幅な設計変更が行なわれたこともあり、Direct3D 9用のHLSLと比較して、Direct3D 10以降用のHLSLではオブジェクト指向に基づいた言語仕様の再設計がなされ、多数の仕様変更が加えられている。
Direct3D 10以降ではHLSLにてクラスを定義し、C++のようにデータ（メンバー変数）と振る舞い（メンバー関数）を関連付けることが可能だが、アクセス指定子によるカプセル化や継承および仮想関数といった機能は備えていない。
Direct3D 11ではシェーダーの組み合わせ爆発問題を解消するべく、HLSLにてインターフェイスの定義と実装によるポリモーフィズムを疑似的に実現する「動的シェーダーリンク（Dynamic Shader Linkage）」と呼ばれる機能が追加された。

コード例

以下に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 (DirectCompute) ではコンピュートシェーダーを使って、GPUにグラフィックス用途以外の汎用計算を行なわせるGPGPUプログラムをHLSLで記述することも可能となる。
なお、HLSLソースファイルには通例.hlsl拡張子が付けられ、ヘッダーファイルには.hlsli拡張子が付けられる。

対応環境

HLSLプログラムは主にホストとなるC++アプリケーションプログラムコードからDirect3D APIを使って入力と出力を管理する必要があるので、単体で動作させることはできない。なお、単体のコンパイラはマイクロソフトから無償提供されているDirectX SDK（あるいはバージョン8.0以降のWindows SDK）に付属する。プロプライエタリなHLSLコンパイラfxc.exeによって出力されるのは、グラフィックスハードウェアのベンダーに依存しない共通バイトコードであるため、一度コンパイルしておけば異なるハードウェアであっても（コンパイル時に想定されていた機能を満たす限り）動作させることができる。HLSLプログラムをサポートするのはDirect3D 9以降をサポートするシステムに限られるため、2015年1月現在ではWindows OS、Xbox 360およびXbox Oneが主な動作環境である。
アプリケーションの実行時にHLSLソースコードをコンパイルしてバイトコードを生成する機能を組み込むためのD3DCompilerランタイムも提供されている。
他に、ゲームエンジンのUnityでは、Windows上でDirectComputeベース (DirectX 11ベース) のコンピュートシェーダーを使用することができるが、コンピュートシェーダーの記述にはCgではなくHLSLを用いる。UnityはCg/HLSLからGLSLへのトランスレーションが可能なため、OpenGL 4.3やOpenGL ES 3.1のコンピュートシェーダーを用いる場合でもGLSLではなくHLSLを使用することが推奨されている。
LLVM/ClangベースのHLSLコンパイラdxc.exeもGitHub上で開発が進められている。こちらはDirectX Intermediate Language (DXIL) と呼ばれる別の中間言語コードを生成するが、これまでのfxc.exeが生成するバイトコードとは互換性がない。

エフェクト

HLSL自体は、シェーダー関数および各シェーダーステージのエントリーポイント（いわゆるメイン関数）を記述するために使われるが、この複数のシェーダーステージをまとめて管理・適用する「エフェクト」と呼ばれる仕組みも存在する。つまり、例えば2つの頂点シェーダーエントリーポイントVS1(), VS2()と2つのピクセルシェーダーエントリーポイントPS1(), PS2()を単一のHLSLソースプログラムファイル（通例.fx拡張子が付けられ、エフェクトファイルと呼ばれる）に記述し、さらにVS1+PS1, VS2+PS2, VS1+PS2, VS2+PS1といったシェーダーステージの組み合わせ（パス）のほか、各種レンダリングステートの設定をエフェクトファイル中に記述して関連付けることができる。エフェクトを扱うAPIはDirect3D 10のコアライブラリもしくはDirect3D 9/11のエクステンションライブラリ（D3DX）に用意されており、レンダリングパイプラインの管理をC++コードから分離することができる。

WPFエフェクト

Windowsデスクトップアプリケーションフレームワークの1つであるWPFでは、グラフィックスのレンダリングにDirect3Dが使用されているが、GUIウィジェットにブラー（ぼかし）やドロップシャドウといったエフェクト（フィルター）を適用することが可能となっている。さらにWPFではユーザープログラマーがHLSLで作成したピクセルシェーダーを使用してカスタムエフェクトを適用することもできる。
WPF 3.5まではシェーダーモデル2.0のピクセルシェーダーのみがサポートされていたが、WPF 4ではシェーダーモデル3.0のピクセルシェーダーも使用できるようになった 。

Direct2Dエフェクト

DirectXファミリーの1つ、2次元コンピュータグラフィックスAPIであるDirect2Dでは、バージョン1.1にてエフェクト機能が実装されたが、HLSLによるカスタムエフェクトを作成・利用することも可能となっている。

シェーダーモデル

Direct3Dプログラマブルシェーダーを実行するには、Direct3D 8以降に対応したハードウェアが必要となる。ただし、Direct3D 9までの場合、頂点シェーダーだけはソフトウェアすなわちCPUでエミュレートすることもできる（D3DCREATE_SOFTWARE_VERTEXPROCESSING）ため、固定機能ピクセルシェーダーと組み合わせることによりDirect3D 7以前の古いハードウェアでプログラマブルシェーダーを実行することも可能である。また、Direct3D 10.1以降では比較的高速なソフトウェアレンダリングエンジンであるWARPデバイスも実装されているため、GPUが対応していなくてもCPUにDirect3Dレンダリングを実行させることもできる。
Direct3D対応ハードウェア（グラフィックスカード）の世代によって、GPU上にてハードウェアレベルで実行可能なシェーダープログラムの仕様（制約、機能など）が異なる。この仕様はシェーダーモデルと呼ばれ、新しい世代のシェーダーモデルをサポートするハードウェアは基本的に古い世代のシェーダーモデルもサポートするが、ベンダーごとに拡張された2.0a/2.0bなどの例外も存在する。
なおHLSLがDirect3Dに搭載されたのはバージョン9以降だが、シェーダーモデル2.0以降でないとHLSLを使えないというようなことはなく、HLSLを使用してシェーダーモデル1.xレベルのプログラムを記述することも可能である。また、Direct3D 10では、アセンブリ言語によるシェーダープログラム開発が廃止され、シェーダーの記述にはHLSLのみが使用できるようになった。
シェーダーモデル3.0には頂点テクスチャフェッチ（Vertex Texture Fetch, VTF）と呼ばれる機能が存在するが、DirectX 9.0c世代で対応したのはNVIDIAのハードウェアのみで、ATIのハードウェアではサポートされなかった。逆に、浮動小数点バッファにおけるアンチエイリアス機能は、NVIDIAハードウェアではサポートされず、ATIハードウェアのみでの対応となっていた 。他にも、（DirectX 11で標準化される前の）テッセレーション機能がATIハードウェア上のみでサポートされる  など、シェーダーモデル3.0までは（たとえDirectX 9.0c対応を謳っていても）機能面において各社の足並みがそろわない状態にあり、これらの機能を利用するアプリケーション開発者は使用したい機能が実際にハードウェアでサポートされているかどうかをあらかじめDirect3DのCaps (Capabilities) 取得APIを使って一つ一つ調べなければならなかった。このようにベンダーごとに各機能の対応レベルがバラバラとなっていた悲惨な状況は、次のバージョンのDirect3D 10以降で要求仕様が厳格化されたことで、ある程度解消されることになる。
なお、Direct3D 10.1 APIでは4.xプロファイルのシェーダープログラムに加えてダウンレベルの2.0プロファイルが使用可能であり、Direct3D 11/12 APIでは5.xおよび4.xプロファイルに加えてダウンレベルの2.0プロファイルが使用可能だが、いずれも3.0プロファイルに関しては使用できない   。