シェーダー

出典: フリー百科事典『ウィキペディア(Wikipedia)』

これはこのページの過去の版です。Lod-aiko (会話 | 投稿記録) による 2015年11月21日 (土) 15:12個人設定で未設定ならUTC)時点の版であり、現在の版とは大きく異なる場合があります。

シェーダー: shader)とは、3次元コンピュータグラフィックスにおいて、シェーディング(陰影処理)を行うコンピュータプログラムのこと。「shade」とは「次第に変化させる」「陰影・グラデーションを付ける」という意味で、「shader」は頂点色やピクセル色などを次々に変化させるもの(より具体的に、狭義の意味で言えば関数)を意味する。

解説

技術的な視点から見るとシェーダーは(物体の位置を計算・決定するモデリングシステムやレイアウト・アニメーションシステムとは違い)物体の色の計算を担当するレンダラの一部である。すなわち、CGレンダリングソフトはリアルタイム/非リアルタイムを問わず、ソフトウェアあるいはハードウェアによるシェーダーを必ず備えていることになる。

RenderMan Shading Languageに代表されるように、プロダクション向けの3次元コンピュータグラフィックスのレンダリングでは古くからシェーディング処理をプログラムで記述してカスタマイズし、高品質な映像を作り出すといったことは当たり前のように行なわれてきたが、ゲームやCADのようなリアルタイム用途では処理時間の制約があるため、ソフトウェア(CPU)による定形の簡易シェーディングもしくはハードウェア(GPU)に固定実装された頂点変換・シェーディング機能(ハードウェアT&L)を使った簡素なシェーディングにとどまっていた[1]。しかし、GPUがシェーダー機能や演算能力および柔軟性を強化し、プログラマビリティを獲得したことを受けて、OpenGLDirect3D (DirectX) といった主なリアルタイムグラフィックスライブラリはAPIに専用のプログラマブル(プログラム可能)なシェーディング機能(プログラマブルシェーダー)を備えるようになった。OpenGLはバージョン1.5で、またDirect3Dはバージョン8でプログラマブルシェーダーが導入された。

プロダクション用途のシェーダー

プロダクションレンダリングは、静止画あるいは動画の生成が最終目的であるが、動画の場合は複数枚の静止画をつなぎ合わせて最終的にコンポジットを行ない、動画を作り出す。

リアルタイム用途と比較すると、プロダクションレンダリングでは時間や資源の制約が少ない。例えば、映画作品の1シーンをレンダリングするために数時間から数日をかけ、高品質な映像を作り出してもかまわない。レンダリングのための膨大な一時情報(中間計算結果などのキャッシュデータ)がコンピュータの物理メモリに収まりきらない場合でも、ハードディスクなどの二次記憶領域に退避してレンダリングを続行することもできる。

プロダクション用途のシェーダーでは、時間はかかるが高品質でリアリティの高い結果を生成できる、レイトレーシングなどのより厳密な大域照明(グローバルイルミネーション)ベース・物理ベースの陰影計算モデルが用いられる。例えば、PIXARRenderManはグローバルイルミネーションをサポートしている[2]

また、物体同士の相互反射光の計算や、ある物体から別の物体へ投影されるシャドウ(影)の計算は、シーン内のライト(光源)の数に比例して時間がかかるようになるが、プロダクションレンダリングではデザイナーの望む数だけ自由に光源を配置することができる。

リアルタイム用途のシェーダー

ゲームなどのリアルタイムレンダリングでは、例えば60FPSの場合1フレームの描画にかけられる時間は最大でもわずか16ミリ秒程度であり、また頂点情報やテクスチャデータの格納・参照に使用できるビデオメモリ(グラフィックスカードに直結実装されたVRAM)の容量といった制約条件が多い。そのため、リアルタイム用途のシェーダーでは、相互反射などを考慮しない、低品質だが簡潔で高速な局所照明(ローカルイルミネーション)ベースの陰影計算モデルやZバッファ技法が用いられることが大多数である。GPUの進化とリアルタイム用プログラマブルシェーダーの発展を受けて、アルゴリズムやデータ構造を工夫してグローバルイルミネーションをリアルタイム実装している例(PRT[3]、ライトフィールド[4]、ISPM[5]、SVO-GI法[6]NVIDIA GI WorksのCLIPMAP法[7]など)も出てきているが、高性能なハードウェアを要求するなど、2015年時点でも未だ発展途上の技術である。シャドウや多光源環境のライティングに関しても、CSM[8]/PSSM[9]といった種々のシャドウマップ派生技術、および遅延シェーディング・遅延ライティングなどが考案されているが、有限資源という制約が足かせとなり、品質や柔軟性はプロダクションレンダリングに及ばない。

リアルタイム処理系におけるプログラマブルシェーダーの隆盛

従来、CADソフトやゲームなどのリアルタイム 2D/3Dグラフィックス アプリケーション開発者は、グラフィックスハードウェア(グラフィックスカードにおけるGPU)に固定機能として実装されていた「定形のパイプライン」(固定機能パイプライン)を使用してグラフィック表示を行なっていた。

しかし、多数のグラフィック表現技術が次々と開発されていく中で、それらの技術をGPUメーカーが逐一ハードウェアに機能として実装していく形態は非効率であり、またユーザープログラマーが新しい技術を試すにはメーカーの対応を待たねばならなかった。この問題を解決するアイディアとして、GPUのパイプラインをソフトウェアプログラムにより組み立てる「プログラマブル パイプライン」と呼ばれるアーキテクチャが構築されることになる。以前は完全にブラックボックスだったグラフィックスパイプラインがユーザープログラマーに対して開放されることで、新たな陰影処理技法や各種エフェクト(画面効果)を試験的に実装してGPU上で走らせることが容易になり、先進的なGPUの機能を利用する優れた柔軟性と、表現力の爆発的な向上がもたらされた。

なお、従来のOpenGLあるいはDirectX (Direct3D) のAPIによってブラックボックスとして提供されていたシェーダーは、固定機能シェーダーと呼ばれ、プログラマブルシェーダーと区別される。OpenGLにおいてはバージョン1.5からプログラマブルシェーダーが拡張として導入され、バージョン2.0からは標準化された。Direct3Dにおいてはバージョン8からプログラマブルシェーダーが導入された[10]。OpenGL 3.1、OpenGL ES 2.0、およびDirect3D 10以降はそれぞれ固定機能シェーダーを完全に廃止しており、グラフィックスパイプラインはプログラマブルシェーダーによって記述することが必須となっている。なおリアルタイム処理系において「シェーダー」といえば、通例プログラマブルシェーダーを指す[11] [12]。また、Direct3D 9世代までは、頂点シェーダーとピクセルシェーダーの処理を担当するGPU内の演算ユニット(演算器)は完全に分かれており、それぞれの演算ユニットのことを「シェーダー」と呼んでいた。そのため、かつてはグラフィックスカードの性能指標として演算ユニット数を表すために「シェーダー数」という言葉が使われていたが、統合型シェーダーアーキテクチャを採用したDirect3D 10世代以降は「ストリームプロセッサ数(SP数)」あるいは「CUDAコア数」という言葉が用いられるようになっている[13] [14] [15] [16] [17]

CGレンダリングソフトの多くは、最終的な出力結果を得るための高品質な計算モデルとして、レンダリング方程式英語版に基づく、光学的・物理学的により厳密なグローバルイルミネーションモデルを実現する各種計算手法(レイトレーシングラジオシティフォトンマッピングなど)を採用しているが、モデリングやパラメータ設定の作業中は、プレビューのために描画品質を落としてOpenGLあるいはDirect3Dによってリアルタイム表示する必要がある。GPUが固定機能シェーダーのみをサポートしていた頃は、プレビューは最終描画結果とはほど遠いものであったが、プログラマブルシェーダーをサポートするようになってからは、各CGソフトもプレビューにプログラマブルシェーダーを使用するようになり、プレビューの品質が飛躍的に向上した。2009年時点で、Autodesk 3ds MaxAutodesk MayaAutodesk Softimage、およびNewTek LightWave 3Dといった有名なソフトウェアの最新版はいずれもプログラマブルシェーダーによるプレビューを実装している。

また、リアルタイム用のプログラマブルシェーダーはAdobe PhotoshopAdobe Flashのように2DCGを主に扱うソフトウェアにもアクセラレータとして導入されることが多くなっている。GUIベースオペレーティングシステム (OS) のデスクトップ合成エンジンや標準2DグラフィックスAPIでも、Windows Aero/Direct2D (Windows) やQuartz Extreme/Core Image (OS X) などのように、GPUおよびプログラマブルシェーダーを活用したものが現れている。ハードウェア(グラフィックスカード)が一定のシェーダー機能を満たす場合、CPUの負荷が低減され、表示や応答が高速化されるなどのメリットがある。

シェーダーステージ

リアルタイム用途のプログラマブルシェーダーでは、グラフィックスパイプラインの中でもユーザープログラマーが制御できるステージがあらかじめ決められている。 OpenGL 3.2以降とDirect3D 10[18]以降では3種類のシェーダーを使用できる。

頂点シェーダー(バーテックスシェーダー)

頂点シェーダー: Vertex Shader, VS)は主に入力頂点を座標変換(トランスフォーム)するための機能である。頂点シェーダーはオブジェクトを構成する頂点の集合(頂点配列、頂点バッファ)に対してのみ作用し、例えば3次元空間におけるXYZ位置座標法線ベクトル、色、テクスチャマッピング座標(UV座標など)といった頂点の属性だけを参照・変換できる。3次元グラフィックスにおける主な座標変換にはワールド変換、ビュー変換、プロジェクション変換、およびビューポート変換が存在するが、頂点シェーダーが担当するのはワールド・ビュー・プロジェクション変換である。ワールド・ビュー変換はモデル・ビュー変換とも呼ばれる。なお頂点単位のライティングであれば、頂点シェーダーで座標変換のほかにライティング計算を行なうこともできる。頂点シェーダーで計算された頂点情報はジオメトリシェーダーに渡されるか、そのままピクセルシェーダーに渡される。

Direct3D 9では頂点シェーダーをソフトウェアエミュレーションすなわちCPUで実行することもできるが(D3DCREATE_SOFTWARE_VERTEXPROCESSING)、プログラマブルシェーダー機能に対応しているハードウェア(GPU)であれば多数のプロセッサコアを使用して並列に処理を行なうことができるので、CPUで頂点シェーダーを実行するよりもGPUを利用した方が高速になる。

なお、シェーダーモデル3.0(DirectX 9.0c、OpenGL 2.x世代)で導入されたVertex Texture Fetch (VTF) [19]を使用すると、頂点シェーダーステージでテクスチャデータを参照することも可能となる。 シェーダーモデル4.0(DirectX 10世代)以降では、VTFはバッファデータの参照とともに標準化されている[20](OpenGLは3.1でVTFを標準化し、バーテックスシェーダーで少なくとも16個のTIUを使えるようになっている)。 さらに、OpenGL 4.2ではすべてのシェーダーステージにおいてイメージオブジェクトに対するロード/ストアを可能にする機能が標準化された[21]。DirectXにおいても、バージョン11.1にて、ピクセルシェーダーやコンピュートシェーダーだけでなく、すべてのシェーダーステージにおいて各種リソースに対する書き込みが可能になっている[22]

ジオメトリシェーダー

ジオメトリシェーダー: Geometry Shader, GS)はピクセルシェーダーに渡されるオブジェクト内の頂点の集合を加工するために使用される。ジオメトリシェーダーにより、実行時に頂点数を増減させたり、プリミティブの種類を変更したりすることが可能となる。OpenGLではプリミティブシェーダーとも呼ばれる。

ジオメトリシェーダーはポイント、ライン、トライアングルといった既存のプリミティブから新しいプリミティブを生成できる。

ジオメトリシェーダーは頂点シェーダーの後に実行され、プリミティブ全体または隣接したプリミティブの情報を持つプリミティブを入力する。例えばトライアングルを処理するとき、3つの頂点がジオメトリシェーダーの入力となる。ジオメトリシェーダーはラスタライズされるプリミティブを出力でき、そのフラグメントは最終的にピクセルシェーダーに渡される。またプリミティブを出力せずにキャンセルすることもできる。

ジオメトリシェーダーのよくある使い方としては、ポイントスプライトの生成、ジオメトリテセレーション、シャドウボリュームの切り出し、キューブマップあるいはテクスチャ配列へのシングルパスレンダリングなどがある。

ピクセルシェーダー

ピクセルシェーダー: Pixel Shader, PS)はピクセル単位のライティングやポストプロセス(後処理)を行なうための機能である。ピクセルシェーダーはラスタライズされるプリミティブの各ピクセルに影響する。また、ピクセルシェーダーにてテクスチャを参照することでバンプマッピングフォグ、シャドウ、ブルームといったエフェクトを最終レンダリング結果に適用することもできる。OpenGLではフラグメントシェーダー(: Fragment Shader, FS)と呼ばれる(Fragment: 断片)。

ピクセルシェーダーはピクセルを操作する機能であり、頂点シェーダーもしくはジオメトリシェーダーから入力された情報を元にテクスチャを合成したり表面色を適用したりする。ピクセルを操作する処理にかかる時間は入力プリミティブのラスタライズ後のピクセル数や出力解像度に左右されるため、通例は頂点単位の処理と比較して高負荷である。これをピクセルシェーダープログラムとしてプログラミングし、高い並列処理性能を持つGPUで実行することにより、バンプマッピング等のより高度なエフェクトをCPUですべて実行するよりもはるかに高いパフォーマンスで実現できる。なお、通常のレンダーターゲットを使ったピクセルシェーダーでは、アルファブレンド(アルファ合成)処理の詳細をプログラムすることはできない。

GPUパイプラインの概略

Direct3D 9世代までのGPUでは、頂点シェーダーおよびピクセルシェーダーを担当するハードウェアユニットの数はそれぞれ製品ごとに固定されていたが、Direct3D 10世代の統合型シェーダーアーキテクチャ(Unified Shader Architecture)では各シェーダーユニットが統合され、複数の汎用シェーダーユニットを使って上記3つのシェーダーステージに動的に振り分ける形となる[23] [24] [25] [26]

これらのシェーダーはGPUのパイプライン内で実行される。下記はパイプライン内にどのように埋め込まれているのかを示す例である。

  • CPUは命令とジオメトリデータをGPU側に送信する。
  • 頂点シェーダー内でジオメトリを変換し、頂点単位ライティングの計算などを実行する。
  • ジオメトリシェーダーを使用する場合は、頂点シェーダーが出力したジオメトリに対してプリミティブ増減や変更を行なう。
  • これまでの処理で計算されたジオメトリをトライアングルセットアップに設定する。トライアングルはquadに変換される(1つのquadは2 × 2ピクセルのプリミティブである)。
  • ピクセルシェーダーを適用し、ピクセル単位ライティングなどを実行する。
  • 視界判定を実行する。もし視界内にある場合はフレームバッファにピクセルを書き込む。

頂点シェーダー/ジオメトリシェーダーの出力をラスタライザーおよびピクセルシェーダーに渡すのではなく、バッファやテクスチャなどのメモリリソースに書き出した後、インプットアセンブラーや頂点シェーダー/ジオメトリシェーダーに再入力する、ストリームアウトプットという機能も存在する[27](OpenGLにはトランスフォームフィードバックと呼ばれる類似機能が存在する)。ストリームアウトプットはこれまでのようにGPU側でデータを参照するだけでなく、GPU自身が書き換えたデータを(CPUを介することなく)再利用することができるため、GPUパーティクルなどに応用できる[28]

テッセレーションシェーダー

OpenGL 4.0以降とDirect3D 11以降ではさらにテッセレーションシェーダーをオプションとして使用できる。

並列処理

シェーダーは膨大な要素の集合に対して変換処理を同時に適用するように記述される。例えばモデル内の全ての頂点を一様に平行移動・回転・拡大縮小したり、スクリーン(2次元画像バッファ)の特定の範囲内の各ピクセルに対して一様にフィルタリング・輝度変換などを実行したりする、などである。これらの処理は対象となる全要素に等しく適用される。これは並列処理に非常に適している。多くの先進的なGPUでは並列処理効率を高めるべく、(一般的なCPUのマルチコアとは比較にならないほどの)超マルチコア設計となっている。

リアルタイム描画性能と柔軟性を向上させるべく発展してきたGPUだが、ハードウェアレベルでの柔軟性と汎用性を強化したDirect3D 10世代GPUの登場以後、この並列処理におけるGPUの優位性を汎用計算に利用しようという試み(GPGPU)が活発化している。GPGPU向けの汎用APIとして、2006年にはNVIDIAからCUDAが、また2008年にはKhronosグループからOpenCLが発表され、それぞれ機能拡張を続けている。

BlenderのCyclesエンジンやV-Ray RTなどのように、CUDAやOpenCLを経由してプロダクションレンダリングにもGPUを活用し、計算時間を短縮するソフトウェアも出現してきている。

コンピュートシェーダー

GPGPU向けの汎用APIとして代表的なものはCUDAOpenCLだが、OpenGL 4.3以降、OpenGL ES 3.1以降、およびDirect3D 11以降では、主にグラフィックス連携を重視したGPGPUのためのコンピュートシェーダー(Compute Shader、演算シェーダー)が搭載された。コンピュートシェーダーは前述のグラフィックスパイプラインとは独立して動作することのできるステージである。なお、コンピュートシェーダーは座標変換や陰影計算にとどまらない汎用計算が可能となっているため、「シェーダー」という命名はほかのシェーダーステージに合わせた便宜上のものである。Direct3Dのコンピュートシェーダーに関しては、Direct3D APIを含めた総称としてDirectComputeと呼ばれている。

コンピュートシェーダーがCUDAやOpenCLと比較して優れている点として、Direct3D(OpenGL)リアルタイムグラフィックスパイプラインとの連携がしやすい(シミュレーションの実行と可視化に向いている)、Direct3D/HLSL(OpenGL/GLSL)をすでに利用している場合は修得が容易である、などが挙げられる。

シェーディング言語

シェーダーを記述(プログラミング)するための種々の言語がプロダクションレンダリング(非リアルタイム)向けおよびリアルタイムレンダリング向けにそれぞれ開発されている。

多くの3DCGソフトウェアやオーサリングツール、ゲームエンジンにはノードエディタと呼ばれるGUIツールが搭載されており、ノードエディタを使うことでカスタムシェーダー開発を直感的に行なうことができるが、シェーディング言語を直接利用すると細やかな調整を行なうことができる。

関連項目

脚注

  1. ^ DirectX 7 の Direct3D におけるライト
  2. ^ What is RenderMan?
  3. ^ 3Dグラフィックス・マニアックス (65) 事前計算放射輝度伝搬(PRT)~PRTとは? | マイナビニュース
  4. ^ 西川善司の3Dゲームファンのための「ソニック・ワールド・アドベンチャー」グラフィックス講座 -GAME Watch
  5. ^ Hardware-Accelerated Global Illumination by Image Space Photon Mapping
  6. ^ 4Gamer.net ― NVIDIAとEpicが「Unreal Engine 4」で採用された新世代グローバルイルミネーション技法を解説。その威力を直撮りムービーでチェックする
  7. ^ [SIGGRAPH 2014]NVIDIAがゲーム向けのリアルタイム大局照明,IntelはHaswell用DX12ドライバのデモを一般展示セクションで披露 - 4Gamer.net
  8. ^ カスケード シャドウ マップ
  9. ^ GPU Gems 3 - Chapter 10. Parallel-Split Shadow Maps on Programmable GPUs
  10. ^ Shader Models vs Shader Profiles - MSDN
  11. ^ シェーダーの操作:「シェーダーとは、頂点の変換やピクセルの色付けなど、グラフィックス計算を実行するコンピューター プログラムで、通常 CPU の代わりにグラフィックス処理装置 (GPU) で実行されます。」
  12. ^ Working with Shaders: "A shader is a computer program that performs graphics calculations—for example, vertex transformations or pixel coloring—and typically runs on a graphics processing unit (GPU) instead of the CPU."
  13. ^ 4Gamer.net
  14. ^ SAPPHIRE X1950 PRO
  15. ^ SAPPHIRE Ultimate HD 4670 512MB GDDR3 PCI-E
  16. ^ GeForce 8800
  17. ^ GeForce GTX 680 | NVIDIA
  18. ^ シェーダー ステージ (Direct3D 10)
  19. ^ Vertex Texture Fetch - OpenGL.org
  20. ^ Load (DirectX HLSL Texture Object) (Windows)
  21. ^ GL_ARB_shader_image_load_store
  22. ^ Direct3D 11.1 Features (Windows)
  23. ^ GeForce 8600 FAQ | NVIDIA
  24. ^ [連載][西川善司の3Dゲームエクスタシー]「ATI Radeon HD 2000」シリーズのGPUアーキテクチャ徹底解説
  25. ^ “共有するシェーダ”でGPUの新しい時代を──G80の革新性に迫る (1/3) - ITmedia PC USER
  26. ^ 後藤弘茂のWeekly海外ニュース
  27. ^ ストリーム出力ステージ (Direct3D 10)
  28. ^ ParticlesGS サンプル