シェーダー

シェーダー（英: shader）はグラフィックスパイプラインを構成する各ステージの挙動を記述したプログラムである。 また狭義にはグラフィックスパイプライン中のシェーディング（陰影処理）に関する挙動を記述したプログラムを指す。 3DCGは様々な要素技術の集まりである。物体を三角形の集合で表現するモデリング、動きを計算するアニメーション・物理演算、見た目を生成するレンダリングなどである。レンダリングは複数の段階からなるパイプライン（レンダリングパイプライン）で成っており、現代のレンダリングパイプラインはプログラム可能なステージを多数含んでいる。これにより柔軟なグラフィックスが実現可能になっている。 このプログラム可能なステージの挙動を記述したスクリプトがシェーダーである。実現したいグラフィックスに合わせて各ステージの挙動を専用のシェーディング言語で記述し、このプログラムを実行時にGPU等のハードウェアへ引き渡すことで、レンダリングパイプラインが頂点群やフラグメント群に対してこれら指示を実行し3DCGの見た目が生成される。 シェーダーで可能な処理はハードウェアあるいはそれを抽象化したグラフィックスAPIに規定される。基本的には各ステージで扱う対象が定められており（#分類）、またステージに応じて典型的な処理が様々存在する（例: カメラを起点とした座標変換、テクスチャマッピング、ライティング）。他方で現代のシェーダーはかなり自由度が高く、例えばピクセルシェーダーにおいて入力に含まれている色情報をすべて捨て去って真っ黒なピクセルを出力することも可能であるし、最新の研究に基づいた新しいライティングアルゴリズムを記述することもできる。 現代のグラフィックスパイプラインはプログラム可能なステージが多く柔軟性が高い反面、基本的な処理含めてシェーダーに記述する必要があり手間がかかる。ゲームエンジン等のミドルウェアがこれを簡略化する役割を担うことがある。その場合、エンジンがレンダリングパイプラインの一部のみをプログラマに公開する。すなわちエンジンがパイプラインを内部的に持ちエンジン側で典型的な処理を用意する。これにより簡略化しつつ、各ステージ内でプログラマがよく関与する部分に関してのみ追加でシェーダーを差し込めるようにする。これにより典型的な処理の記述を避けつつ柔軟性を確保できる。差し込み可能な領域がシェーディング（陰影処理）である場合が多いため、「シェーダー」という語を「陰影処理に関する挙動を記述したプログラム」という意味で扱う場合もある。 「shade」とは「次第に変化させる」「陰影・グラデーションを付ける」という意味で、「shader」は頂点色やピクセル色などを次々に変化させるもの（より具体的に、狭義の意味で言えば関数）を意味する。 シェーダーは膨大な要素の集合に対して変換処理を同時に適用するように記述される。例えばモデル内の全ての頂点を一様に平行移動・回転・拡大縮小したり、スクリーン（2次元画像バッファ）の特定の範囲内の各ピクセルに対して一様にフィルタリング・輝度変換などを実行したりする、などである。これらの処理は対象となる全要素に等しく適用される。これは並列処理に非常に適しており、しばしばGPUを用いて処理される。例えばBlenderのCyclesエンジンやV-Ray RTはCUDAやOpenCLを経由してプロダクションレンダリングにGPUを活用する。 シェーダー内で実装されるグラフィックスアルゴリズムは用途に応じて使い分けられる。 映画などのプロダクション用途のシェーダーでは、時間はかかるが高品質でリアリティの高い結果を生成する。レンダリング方程式（英語版）に基づくレイトレーシングやラジオシティ、フォトンマッピングなど、より厳密な大域照明（グローバルイルミネーション）ベース・物理ベースの陰影計算モデルが用いられる。例えば、PIXARのRenderManはグローバルイルミネーションをサポートしている。 ゲームなどのリアルタイム用途のシェーダーは、例えば60FPSの場合1フレームの描画にかけられる時間は最大でもわずか16ミリ秒程度であり、また頂点情報やテクスチャデータの格納・参照に使用できるビデオメモリの容量といった制約条件が多い。そのため、リアルタイム用途のシェーダーでは品質と速度のトレードオフが重視される。相互反射などを考慮しない簡素で高速な局所照明（ローカルイルミネーション）ベースの陰影計算モデルやZバッファ技法が用いられることが大多数である。GPUの進化とリアルタイム用プログラマブルシェーダーの発展を受けて、アルゴリズムやデータ構造を工夫してグローバルイルミネーションをリアルタイム実装している例（PRT、ライトフィールド、ISPM、SVO-GI法やNVIDIA GI WorksのCLIPMAP法など）も出てきているが、高性能なハードウェアを要求するなど、2018年時点でも未だ発展途上の技術である。シャドウや多光源環境のライティングに関しても、CSM/PSSMといった種々のシャドウマップ派生技術、および遅延シェーディング・遅延ライティングなどが考案され、制約内で品質を高めるアルゴリズムが追求されている。 リアルタイム用途のシェーダーはCGプロダクションソフトウェアのプレビューにも用いられる。プロダクション用シェーダーの代わりにリアルタイム用シェーダーを用いることで素早いプレビューが可能になる。例えばAutodesk 3ds Max、Autodesk Maya、Autodesk Softimage、およびNewTek LightWave 3Dがプレビュー機能を提供している。 2DCGソフトウェアにもアクセラレータとしてしばしば導入される（例: Adobe PhotoshopやAdobe Flash）。GUIベースオペレーティングシステム (OS) のデスクトップ合成エンジンや標準2DグラフィックスAPI、具体的にはWindows Aero/Direct2D (Windows) やQuartz Extreme/Core Image (macOS) がその一例である。 シェーダーは対応するステージによって入出力や利用可能な機能が異なる。これに基づいてシェーダーは以下のように分類できる。なお、各シェーダーの具体的な仕様や制約はグラフィックスAPI/ハードウェアごとに異なるため、ここで紹介するのは Direct3D / OpenGL / Vulkan におおよそ共通する振る舞いに留まる（詳細は各仕様の記事を参照）。 多くのリアルタイム用途グラフィックスパイプラインは複数段のプログラマブルシェーダーと固定処理からなっている。プログラム可能な1つの段階（シェーダー）はシェーダーステージと呼ばれる。以下は典型的なシェーダーステージである。 OpenGL 3.2以降とDirect3D 10以降では3種類のシェーダーを使用できる。シェーダー間の入出力関係はグラフィックスパイプライン#ステージを参照。 頂点シェーダー（英: Vertex Shader）は各頂点を処理するシェーダーである。バーテックスシェーダーとも。 頂点シェーダーはオブジェクトを構成する頂点を入力とし、様々な処理おこない、頂点を出力する。例えば3次元空間座標・法線ベクトル・色・テクスチャマッピング座標を入力として受け付ける。グラフィックスAPIによってはテクスチャへの副次的アクセスが用意されている。処理として典型的にはモデル変換・ビュー変換・投影変換をおこない、古典的には頂点単位のライティングもおこなう。 ジオメトリシェーダー（英: Geometry Shader, GS）はピクセルシェーダーに渡されるオブジェクト内の頂点の集合を加工するために使用される。ジオメトリシェーダーにより、実行時に頂点数を増減させたり、プリミティブの種類を変更したりすることが可能となる。OpenGLではプリミティブシェーダーとも呼ばれる。 ジオメトリシェーダーはポイント、ライン、トライアングルといった既存のプリミティブから新しいプリミティブを生成できる。 ジオメトリシェーダーは頂点シェーダーの後に実行され、プリミティブ全体または隣接したプリミティブの情報を持つプリミティブを入力する。例えばトライアングルを処理するとき、3つの頂点がジオメトリシェーダーの入力となる。ジオメトリシェーダーはラスタライズされるプリミティブを出力でき、そのフラグメントは最終的にピクセルシェーダーに渡される。またプリミティブを出力せずにキャンセルすることもできる。 ジオメトリシェーダーのよくある使い方としては、ポイントスプライトの生成、ジオメトリテセレーション、シャドウボリュームの切り出し、キューブマップあるいはテクスチャ配列へのシングルパスレンダリングなどがある。 ピクセルシェーダー（英: Pixel Shader, PS）はピクセル単位のライティングやポストプロセス（後処理）を行なうための機能である。ピクセルシェーダーはラスタライズされるプリミティブの各ピクセルに影響する。また、ピクセルシェーダーにてテクスチャを参照することでバンプマッピングやフォグ、シャドウ、ブルームといったエフェクトを最終レンダリング結果に適用することもできる。OpenGLではフラグメントシェーダー（英: Fragment Shader, FS）と呼ばれる（Fragment: 断片）。 ピクセルシェーダーはピクセルを操作する機能であり、頂点シェーダーもしくはジオメトリシェーダーから入力された情報を元にテクスチャを合成したり表面色を適用したりする。ピクセルを操作する処理にかかる時間は入力プリミティブのラスタライズ後のピクセル数や出力解像度に左右されるため、通例は頂点単位の処理と比較して高負荷である。これをピクセルシェーダープログラムとしてプログラミングし、高い並列処理性能を持つGPUで実行することにより、バンプマッピング等のより高度なエフェクトをCPUですべて実行するよりもはるかに高いパフォーマンスで実現できる。なお、通常のレンダーターゲットを使ったピクセルシェーダーでは、アルファブレンド（アルファ合成）処理の詳細をプログラムすることはできない。 ピクセルシェーダーは深度（奥行き）も操作できる。深度の操作はレンダリングパイプラインの最適化へ影響する（例: 深度テストの実行タイミングを左右する）ため、シェーディング言語/グラフィックスAPIによってはフラグの明示が求められる（例: SPIR-V/Vulkan）。 OpenGL 4.0以降とDirect3D 11以降ではさらにテッセレーションシェーダーをオプションとして使用できる。 コンピュートシェーダー（英: Compute shader）はコンピュートパイプラインを構成する各ステージの挙動を記述したプログラムである。 コンピュートシェーダーは汎用並列処理（GPGPU）を目的としており、計算の入出力をグラフィックスパイプラインと共有する場合もある。あくまでシェーダーの一種でありシェーディング言語で記述される。APIとしては OpenGL 4.3以降、OpenGL ES 3.1以降、およびDirect3D 11以降で提供される。Direct3DではDirect3D APIを含めた総称としてDirectComputeと呼ばれている。 GPGPU専用のAPI・言語としてはCUDAとOpenCLがよく知られている。 RenderMan Shading Languageに代表されるように、プロダクション向けの3次元コンピュータグラフィックスのレンダリングでは古くからシェーディング処理をプログラムで記述してカスタマイズし、高品質な映像を作り出すといったことは当たり前のように行なわれてきた。一方でCADソフトやゲームなどのリアルタイム 2D/3Dグラフィックス アプリケーション開発者は、ソフトウェア（CPU）による定形の簡易シェーディングあるいはグラフィックスハードウェア（グラフィックスカードにおけるGPU）に固定機能として実装されていた頂点変換・シェーディング機能（ハードウェアT&L）すなわち「定形のパイプライン」（固定機能パイプライン）を使用してグラフィック表示を行なっていた。 しかし、多数のグラフィック表現技術が次々と開発されていく中で、それらの技術をGPUメーカーが逐一ハードウェアに機能として実装していく形態は非効率であり、またユーザープログラマーが新しい技術を試すにはメーカーの対応を待たねばならなかった。この問題を解決するアイディアとして、GPUのパイプラインをソフトウェアプログラムにより組み立てる「プログラマブル パイプライン」と呼ばれるアーキテクチャが構築されることになる。以前は完全にブラックボックスだったグラフィックスパイプラインがユーザープログラマーに対して開放されることで、新たな陰影処理技法や各種エフェクト（画面効果）を試験的に実装してGPU上で走らせることが容易になり、先進的なGPUの機能を利用する優れた柔軟性と、表現力の爆発的な向上がもたらされた。 当時のOpenGL・DirectX (Direct3D) のAPIによってブラックボックスとして提供されていたシェーダーは固定機能シェーダーと呼ばれ、プログラマブルシェーダーと区別される。OpenGLにおいてはバージョン1.5からプログラマブルシェーダーが拡張として導入され、バージョン2.0からは標準化された。Direct3Dにおいてはバージョン8からプログラマブルシェーダーが導入された。OpenGL 3.1、OpenGL ES 2.0、およびDirect3D 10以降は固定機能シェーダーが廃止され、グラフィックスパイプラインはプログラマブルシェーダーによって記述される。現在ではリアルタイム処理系において「シェーダー」といえばプログラマブルシェーダーを指す 。また、Direct3D 9世代までは、頂点シェーダーとピクセルシェーダーの処理を担当するGPU内のハードウェア演算ユニット（演算器）は完全に分かれており、それぞれの演算ユニットのことを「シェーダー」と呼んでいた。そのため、かつてはグラフィックスカードのハードウェア性能指標として演算ユニット数を表すために「シェーダー数」という言葉が使われていたが、統合型シェーダーアーキテクチャを採用したDirect3D 10世代以降は「ストリームプロセッサ数（SP数）」あるいは「CUDAコア数」という言葉が用いられるようになっている 。 各シェーダーステージが扱えるリソースの範囲も時代とともに拡大している。シェーダーモデル3.0（DirectX 9.0c、OpenGL 2.x世代）で導入されたVertex Texture Fetch (VTF) により、頂点シェーダーステージでテクスチャデータを参照できるようになった。シェーダーモデル4.0（DirectX 10世代）以降では、VTFはバッファデータの参照とともに標準化された（OpenGLは3.1でVTFを標準化し、頂点シェーダーで少なくとも16個のTIUを使えるようになった）。さらに、OpenGL 4.2ではすべてのシェーダーステージにおいてイメージオブジェクトに対するロード／ストアを可能にする機能が標準化された。DirectXにおいても、バージョン11.1にて、ピクセルシェーダーやコンピュートシェーダーだけでなく、すべてのシェーダーステージにおいて各種リソースに対する書き込みが可能になった。 シェーディング言語 HLSL GLSL グラフィックスパイプライン シェーディング 物理ベースシェーディング (PBS) Direct3D OpenGL 3次元コンピュータグラフィックス レンダリング (コンピュータ) 非写実的レンダリング (NPR) [脚注の使い方] ^ a b c d "A shader specifies programmable operations that execute for each vertex, control point, tessellated vertex, primitive, fragment, or workgroup in the corresponding stage(s) of the graphics and compute pipelines." 以下より引用。Khronos. Vulkan Specification - Shaders. Vulkan Documentation. 2024-08-11閲覧. ^ "A shader program, commonly referred to as a shader, is a program that runs on a GPU." 以下より引用。Unity. Graphics - Shaders - Shaders core concepts - Shaders introduction. Unity Documentation, version 2022.3. 2024-08-11閲覧. ^ a b "shaders are divided into three broad categories. ... Shaders that are part of the graphics pipeline ... They perform calculations that determine the color of pixels on the screen." 以下より引用。Unity. Graphics - Shaders - Shaders core concepts - Shaders introduction. Unity Documentation, version 2022.3. 2024-08-11閲覧. ^ What is RenderMan? ^ 衝突判定など、ユーザーとのインタラクション処理に要する時間も加味すると、実際に描画処理に使える時間はさらに短くなる。そのため性能の低いモバイル機器などでは30FPSが目標値とされることもある。一方、VRの場合は通例3D酔いを避けるために最低フレームレート要件が引き上げられる。 ^ 3Dグラフィックス・マニアックス (65) 事前計算放射輝度伝搬(PRT)～PRTとは? | マイナビニュース ^ 西川善司の3Dゲームファンのための「ソニック・ワールド・アドベンチャー」グラフィックス講座 -GAME Watch ^ Hardware-Accelerated Global Illumination by Image Space Photon Mapping ^ 4Gamer.net ― NVIDIAとEpicが「Unreal Engine 4」で採用された新世代グローバルイルミネーション技法を解説。その威力を直撮りムービーでチェックする ^ ［SIGGRAPH 2014］NVIDIAがゲーム向けのリアルタイム大局照明，IntelはHaswell用DX12ドライバのデモを一般展示セクションで披露 - 4Gamer.net ^ カスケード シャドウ マップ ^ GPU Gems 3 - Chapter 10. Parallel-Split Shadow Maps on Programmable GPUs ^ A shader object corresponds to a stage in the rendering pipeline referred to as its shader stage or shader type OpenGL 4.6 specification ^ Tessellation is a process that reads a patch primitive and generates new primitives used by subsequent pipeline stages. OpenGL 4.6 specification ^ Geometry shaders operate on a single primitive at a time and emit one or more output primitives OpenGL 4.6 specification ^ シェーダー ステージ (Direct3D 10) ^ a b "Each vertex shader invocation operates on one vertex and its associated vertex attribute data, and outputs one vertex and associated data." 以下より引用。Khronos. Vulkan Specification - Shaders. Vulkan Documentation. 2024-08-11閲覧. ^ "頂点シェーダー は、3D モデルの各頂点で実行されるプログラムです。多くの場合、それは特に何もしません。ここでは、頂点の位置をオブジェクト空間からいわゆる「クリップスペース」に変換するだけです。... また、入力テクスチャ座標を変更しないで渡します。" 以下より引用。Unity. 頂点シェーダーとフラグメントシェーダーの例. Unity ユーザーマニュアル 2019.4 LTS. 2024-08-11閲覧. ^ " If the shader dynamically writes to FragDepth, the DepthReplacing Execution Mode must be declared (This is done in tools such as glslang)." 以下より引用。Khronos. Vulkan Guide - Using Vulkan - Depth. Vulkan Documentation. 2024-08-17閲覧. ^ DirectX 7 の Direct3D におけるライト ^ Shader Models vs Shader Profiles - MSDN ^ シェーダーの操作:「シェーダーとは、頂点の変換やピクセルの色付けなど、グラフィックス計算を実行するコンピューター プログラムで、通常 CPU の代わりにグラフィックス処理装置 (GPU) で実行されます。」 ^ 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." ^ 4Gamer.net ^ SAPPHIRE X1950 PRO ^ SAPPHIRE Ultimate HD 4670 512MB GDDR3 PCI-E ^ GeForce 8800 ^ GeForce GTX 680 | NVIDIA ^ Vertex Texture Fetch - OpenGL.org ^ Load (DirectX HLSL Texture Object) (Windows) ^ GL_ARB_shader_image_load_store ^ Direct3D 11.1 Features (Windows)