レンダリングパイプライン

■レンダリング

ポリゴンデータと、テクスチャデータを使用して
画面や画像として出力することをレンダリングと呼びます。
3Dモデルファイルはモデルの形を形成するポリゴンデータと
そのモデルで使用するテクスチャの情報が入っています。

shader_0020

■レンダリングパイプライン

レンダリングパイプラインとはモデルデータの入力から出力までの
レンダリングのための加工手順のことです。
	
shader_0021

●入力データ
	・モデルデータ
		入力時に使用するモデルデータはポリゴンの集合です。
		ポリゴンは3つ以上の頂点で形成される多角形のことで、
		基本的にモデルデータで使用するポリゴンの頂点数は3か4です。
		このポリゴンの頂点情報(座標や色など)を管理するための
		バッファが用意されており、そのバッファを頂点バッファと呼びます。

	shader_0022

		上の図のように最終的にモデルデータは頂点バッファに格納され、
		レンダリングパイプラインで使用されることになります。

	・画像データ
		画像データはbmpやpngなど、様々なフォーマットの画像を使用可能です。
		これらの画像をメモリ上に読み込んで使用します。
		また、レンダリングターゲットに描き込んでいる画像も
		画像データとして使用することができます。

●出力データ
	レンダリングパイプラインから出力された画像はメモリ上に保存されます。
	このメモリ領域のことは「レンダリングターゲット」「バックバッファ」
	「サーフェース」などと呼ばれています。
	このレンダリングターゲットの画像を画面に転送することで
	ディスプレイ上での描画が可能となっています。

	shader_0023

●加工の順番
	レンダリングパイプラインの加工は以下の順番で行われています。

	shader_0024

	頂点パイプラインとピクセルパイプラインの部分が
	現在プログラマブルに使用できる箇所です。
	これらのシェーダの種類は2種類あり、
	開発側がソースを書いて作成するシェーダをプログラマブルシェーダ、
	既存で用意されているシェーダを固定機能シェーダと呼んでいます。
	近年のシェーダはプログラマブルシェーダで記述することを必須としており、
	固定機能シェーダでシェーダを記述できるのはDirectX9以前、OpenGL2.0以前など、
	古いバージョンのグラフィックライブラリでしか扱えなくなっています。

■頂点シェーダ

●概要
	頂点シェーダはレンダリングパイプラインの最初に行うシェーダ処理です。
	主な処理は「座標変換」「テクスチャ座標の計算」「陰影処理」です。
	この処理は各ポリゴンの頂点1つ1つに対して行われます。

	shader_006

	上のイメージ図で注意してほしい点は頂点シェーダの変換後は
	テッセレーションやジオメトリシェーダ、
	ラスタライザやピクセルシェーダがあるので頂点シェーダ終了後、
	すぐにスクリーンに投影されません。
	あくまでイメージですので注意して下さい。

●座標変換
	3Dモデルはモデル独自の座標系である「ローカル座標」を持っています。
	このローカル座標はあくまで、各モデルを中心とした座標なので、
	以下の用に複数のモデルのローカル座標が(0, 0, 0)だったとしても
	モデルが重なっていることにはなりません。

	shader_0017

	そこで、3D空間用の座標を用意してモデルを配置します。
	そうすることで、3D空間を座標軸を指標としてモデルの座標を決めて
	配置することができます。
	この指標となる3D空間用の座標を「ワールド座標」と呼びます。
	そしてモデルの持つローカル座標をワールド座標のどこかの位置に配置する
	変換方法を「ワールド座標変換」と呼びます。
	ワールド座標変換が頂点シェーダの役割です。

	shader_0018

●テクスチャ座標の計算
	モデルにはテクスチャを貼り付けることができます。
	貼り付けの方法は各頂点に対して貼り付けるテクスチャの座標が決まっており、
	ピクセルシェーダにて座標を元にしてテクスチャの色情報を抽出して
	モデルに貼り付けているように見せています。
	頂点シェーダでは貼り付けるためのテクスチャの座標を求める計算を行います。

●陰影処理
	頂点は法線というポリゴンの向きを表すベクトルを持っています。
	この法線ベクトルと、光の向き表す光源ベクトルを使用して、
	頂点に対しての光の当たり具合、反射具合を計算することができます。
	これらの計算処理のことをまとめて陰影処理と呼んでいます。

	shader_0019

	上の図では光が左上から左下に対して降り注いでおり、
	その光を赤色の立方体が浴びている内容となっています。
	光をまともに浴びている左側は赤がはっきりと出ていますが、
	右側の面は光の当たりが少ないための暗い赤色になっています。
	これが陰影処理の効果です。

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

テッセレーションシェーダは頂点シェーダから送られてきたポリゴンを
分割することができるシェーダです。
テッセレーションシェーダを使用することにより、LOD用に複数の3Dモデルを
用意することなく、1体のモデルだけで動的にLODを実現することができます。
テッセレーションは「ハルシェーダ」「テッセレータ」「ドメインシェーダ」の
3つで構成されています。
shader_0013shader_0014

●ハルシェーダ
	ハルシェーダはどのように分割を行うかを決めるためのシェーダです。
	この後のテッセレータやドメインシェーダで行う分割処理を行うための
	分割計画のための設定を行うのがこのハルシェーダの役割になります。

	・パッチ
		テッセレーションを使用する場合、パイプライン入力のトポロジに変化が生じます。
		非テッセレーションの場合、ポリゴン(三角形)が入力情報として送られますが、
		テッセレーションではパッチと呼ばれるプリミティブが渡されます。
		このパッチにはコントロールポイントと呼ばれる分割用の制御点をもっており、
		1~32までポイントを設定することが可能で、複数のコントロールポイントを
		設定することでこの後のテッセレータでの分割をより詳細に制御することが可能です。

		トポロジ:
			ポリゴンの構成のこと
		
	・テッセレーション係数
		テッセレーション係数とはパッチ毎に指定する分割係数のことです。
		この係数を増やすことでより細かい分割を行うことができます。

●テッセレータ
	テッセレータはハルシェーダで設定を行ったパッチをもとに頂点分割を行うシェーダです。
	固定機能シェーダなのでプログラマーが処理を書くことはDirectX11の段階ではありません。
		
	・分割方法
		ポリゴンの分割は三角形や四角形などの分割単位や
		離散的分割、連続的分割などの分割アルゴリズムの選択などをすることが可能です。

●ドメインシェーダ
	ドメインシェーダではテッセレータで分割されたポリゴンに対して
	様々な変更を行うためのシェーダです。
	例えば曲線を描くように変更したり、凹凸ができるようにしたりと
	新規ポリゴンを使用して新しい表現を行うために用意されているシェーダです。

■ジオメトリシェーダ

ジオメトリシェーダはポリゴンに対して頂点の増減を行うことができるシェーダです。
テッセレーションはパッチ(ポリゴン)に対して分割を行い、
ポリゴンの増加を行いましたが、ジオメトリシェーダはポリゴンの増減が可能です。
ジオメトリシェーダを使用することでポイントをラインにしたり、
ラインをポリゴンにしたり、することが可能です。

shader_0015

■カメラ空間への展開

カメラ空間への展開はジオメトリシェーダまで終了したポリゴンを
ワールド座標からカメラ座標へ変換します。
この変換中~変換後にカリング処理を実行します。
カリングとはカメラの範囲に入っていないポリゴンや
カメラの視点ベクトルに向いていないポリゴンを描画しない手法です。

■ラスタライザ

ラスタライザは頂点シェーダとピクセルシェーダの間に存在する処理で、
頂点シェーダで決まった座標とポリゴン単位の色を元にして
フレームバッファにピクセル単位で描画情報を設定する処理です。

●ラスタライザの処理内容
	ラスタライザが行う処理は主に以下の内容となります。

	・線形の補間
		フレームバッファに対し、頂点シェーダで変換された
		頂点の座標を配置し、頂点同士を線で結びます。

		shader_008

	・頂点カラーの補間
		線で結ばれポリゴンが作成されたら、
		そのポリゴンの内部を走査し、頂点カラーの色で補間を行います。
		この補間が行われたポリゴン1つ1つがピクセルシェーダの対象となります。

		shader_007

■ピクセルシェーダ

ピクセルシェーダはラスタライザで設定された色情報を取得して
そこに何らかの対応を行い、その結果の色情報をGPUへ戻します。

shader_009

・ピクセルシェーダの注意点
	上でも書いていますが、ピクセルシェーダはラスタライザで処理された
	ピクセル1つ1つに対して処理を行います。
	そのため頂点シェーダと比較した場合、作業コストは大きいです。
	画面全体を表示するようなデータがラスタライザに存在した場合、
	その画面領域のピクセルに対してピクセルシェーダの処理を
	行わなければいけません。

	例:
		画面サイズ 800 * 600 の場合:
			800 * 600 => 480,000

		画面サイズ 1920 * 1080 の場合:
			1920 * 1080 => 2,073,600

	ゲームなど近年の画面解像度は大きくなっていく傾向にあります。
	画面の解像度が高くなるとその分だけピクセルシェーダにかかる負担が増えます。
	なので、ピクセルシェーダでは複雑な処理は行わないようにして、
	簡単な処理を行うように心がけてください。

■レンダーバックエンド

レンダーバックエンドはピクセルシェーダ決定したピクセル情報の
描き込みを判断する場所になります。
ここで描き込みに対して問題なしと判断されて始めて
レンダリングバッファに出力されます。
判断に使用するテストには「アルファテスト」「深度テスト」
「ステンシルテスト」などがあります。

●アルファテスト
	アルファテストはピクセルのアルファ値の値で出力するかどうかを判断します。
	判定は既に描き込まれているピクセルのアルファ値より大きいor小さいで判定します。

	shader_0016

●深度テスト
	深度テストは描画されたピクセルが現在描画されているピクセルよりも
	手前 or 奥かどうかを判断し、その結果が出力するかを決めます。

	・深度バッファ(Zバッファ)
		深度バッファ(Zバッファ)とはピクセルに出力された奥行きを保存する領域です。
		このバッファの値と新しく出力されるピクセルの奥行きを比較します。

		pg3d_0112	

●ステンシルテスト
	ステンシルテストとはステンシルバッファと呼ばれるバッファの値と
	ピクセルを描画する際に設定した参照値を比較してピクセルを描画するかどうかを
	判定します。

	pg3d_0118