▼XNA Game Studioメモ▼
HLSL
HLSLとは
「HLSL(High Level Shader Language)」とは、シェーダを書くための言語。
日本語では「上位レベルシェーダ言語」と訳される。
シェーダとは
「シェーダ」とは、「シェーディング処理」をプログラム可能にする技術。
シェーディングとは
「シェーディング」とは、最終的にディスプレイに出力するRGBの明るさを計算する過程の処理。
日本語では「陰影付け」と訳される。
ただし、シェーディングの処理には、「明るさ」だけでなく、頂点移動などの「形状変化」も含まれる。
頂点シェーダとは
頂点データに対する処理をプログラム可能とするもの。
座標変換、証明計算などがある。
ピクセルシェーダとは
ピクセルデータに対する処理をプログラム可能とするもの。
テクスチャマッピングやテクスチャブレンディングなどがある。
エフェクトファイルとは
HLSLはエフェクトファイル(拡張子はfx)と呼ばれるテキストファイルにプログラムを記述する。
エフェクトファイル概要
ワールドビューの座標変換だけを行う「SimpleEffect.fx」を例に、エフェクトファイルの概要を解説する。
ソースコード
SimpleEffect.fx
float4x4 worldViewProj : WORLDVIEWPROJECTION; struct VS_INPUT { float4 pos : POSITION; float4 color : COLOR0; }; struct VS_OUTPUT { float4 pos : POSITION; float4 color : COLOR0; }; VS_OUTPUT VS_TransformTec(VS_INPUT In) { VS_OUTPUT Out=(VS_OUTPUT)0; Out.pos =mul(In.pos,worldViewProj); Out.color=In.color; return Out; } float4 PS_TransformTec(VS_OUTPUT Out) : COLOR { return Out.color; } technique TransformTec { pass P0 { vertexShader=compile vs_2_0 VS_TransformTec(); pixelShader =compile ps_1_1 PS_TransformTec(); } }
エフェクトファイルの構成
エフェクトファイルの構成は次の通り。
グローバル変数 頂点シェーダ出力などの入出力構造体 頂点シェーダの処理を行う関数 ピクセルシェーダの処理を行う関数 テクニック
グローバル変数
「頂点シェーダの座標変換に使う変換行列」や、「モデルの色などのアプリケーション側から設定する変数」は、グローバル変数として保持する。 今回は頂点シェーダの座標変換に使う変換行列「worldViewProj」を宣言している。
「float4x4」は4x4の行列であることを示すデータ型。
float4x4 worldViewProj : WORLDVIEWPROJECTION;
「worldViewProj」は今回宣言したグローバル変数の名前。
「WORLDVIEWPROJECTION」は、アプリケーションが初期化し、ワールド変換行列とビュー変換行列と射影変換行列の積を保持する変数であることを示す「セマンティクス」。「セマンティクス」とは、頂点出力レジスタと変数を関連付けるために記述する識別子。セマンティクス一覧は「FX Composerの資料」、もしくは「Masafumi's LABORATORY」さんのサイトが参考になる。
頂点シェーダの入力構造体
頂点シェーダの処理を行う関数では、「頂点座標」「ポリゴンの色」などの情報をまとめた構造体が引数として渡される。
struct VS_INPUT { float4 pos : POSITION; float4 color : COLOR0; };
「struct」は構造体であることを示すキーワード。
「VS_IN」は今回宣言した構造体の名前。
「float4」は1x4の行列であることを示すデータ型。
「pos」「color」は今回宣言した変数の名前。
「POSITION」は位置情報を保持する変数であることを示す「セマンティクス」。
(x,y,z,w)という4つの成分から成り立つ。
「COLOR0」は色情報を保持する変数であることを示す「セマンティクス」。
(r,g,b,a)という4つの成分から成り立つ。
頂点シェーダの入力構造体で利用する「セマンティクス」は次の通り。
POSITION[n] 位置座標 BLENDWIGHT[n] ブレンドの重み BLENDINDICES[n] ブレンドのインデックス NORMAL[n] 法線ベクトル PSIZE[n] ポイントサイズ COLOR[n] 色 TEXCORD[n] テクスチャ座標 TANGENT[n] 接ベクトル BINORMAL[n] 従法線ベクトル TESSFACTOR[n] テセレーション係数
頂点シェーダの出力構造体
頂点シェーダの処理を行う関数では、「頂点座標」「ポリゴンの色」などの情報をまとめた構造体として戻り値を返す。
struct VS_OUTPUT { float4 pos : POSITION; float4 color : COLOR0; };
「struct」は構造体であることを示すキーワード。
「VS_OUTPUT」は今回宣言した構造体の名前。
「float4」は1x4の行列であることを示すデータ型。
「pos」「color」は今回宣言した変数の名前。
「POSITION」は位置情報を保持する変数であることを示す「セマンティクス」。
(x,y,z,w)という4つの成分から成り立つ。
「COLOR0」は色情報を保持する変数であることを示す「セマンティクス」。
(r,g,b,a)という4つの成分から成り立つ。
頂点シェーダの出力構造体で利用する「セマンティクス」は次の通り。
POSITION 位置座標 COLOR[n] 色 TEXCOORD テクスチャ座標 PSIZE ポイントサイズ FOG 頂点フォグ
頂点シェーダの処理を行う関数
頂点シェーダの処理を行う関数は次の通り。この関数をコンパイルして利用する。
VS_OUTPUT VS_TransformTec(VS_INPUT In) { VS_OUTPUT Out=(VS_OUTPUT)0; Out.pos =mul(In.pos,worldViewProj); Out.color=In.color; return Out; }
「VS_OUTPUT」は関数の戻り値が「VS_OUTPUT」構造体であることを示す。
「VS_TransformTec」は今回宣言した関数の名前。
「(VS_OUTPUT)0」は0で構造体を初期化するの意味。
「mul()」はベクトルと行列の積算命令。今回は頂点1つ1つに対し、worldViewProjを掛けている。
ピクセルシェーダの処理を行う関数
頂点シェーダの処理を行う関数は次の通り。頂点シェーダ出力はピクセルシェーダの入力に渡されている。
float4 PS_TransformTec(VS_OUTPUT Out) : COLOR { return Out.color; }
ピクセルシェーダの出力の「セマンティクス」は次の通り。
COLOR[n] 色 DEPTH 深度
テクニック
「テクニック」はレンダリング方法を指示する関数。
エフェクトファイルには必ず1つ以上存在する。
C言語でいうところのmain()に相当する。
technique TransformTec { pass P0 { vertexShader=compile vs_2_0 VS_TransformTec(); pixelShader =compile ps_1_1 PS_TransformTec(); } }
「technique」はテクニック関数であることを示すキーワード。
「TransformTec」は今回宣言したテクニックの名前。
「pass」はパスであることを示すキーワード。
パスはパスで区切ってレンダリングを切り替えるために利用する。
passは必ずtechnique内に書かれる。
「P0」は今回宣言したパスの名前。
「vertexShader」は頂点シェーダの設定。
「compile」はコンパイルを行うことを示すキーワード。
「vs_2_0」が頂点シェーダのバージョン2.0でコンパイルすることを示すキーワード。
「VS_TransformTec()」は今回コンパイルしてシェーダに設定している関数。
スカラー型
スカラー型
bool trueまたはfalse int 32bit符号付整数 half 16bit浮動少数 float 32bit浮動少数 double 64bit浮動少数
変数の宣言
float val =1.1f; int array[3]={1,2,3};
型の修飾子
const 定数。宣言時に初期化必要。 const float val=1.1f; row_major 行優先。各行が1つの定数レジスタに格納。
HLSLのコードからのアクセス方法には影響を与えない。row_major float4x4 worldMatrix; col_major 列優先。各列が1つの定数レジスタに格納。
HLSLのコードからのアクセス方法には影響を与えない。col_major float4x4 transposedWorldMatrix;
記憶域の修飾子
static グローバル変数に使用するとアプリケーションに公開されなくなる。
ローカル変数に使用すると関数呼び出しの間だけ継続。static float val=1.1f; extern グローバル変数に使用するとアプリケーションに公開される。
staticもexternも付いてない時はexternとして扱う。extern float val=1.1f uniform APIメソッドによる描画呼び出しの間だけ変更可能。
全ての頂点・ピクセルが同じ初期値を参照。uniform float val=1.1f; shared エフェクト間で共有可能。 shared float val;
ベクトル型
ベクトル型
1〜4つの成分を持つ特殊なデータ構造。データ型の末尾にある数は、ベクトルの成分数を示す。
vector型を使用して宣言することも可能。「<>」を使用して成分の型と数を指定。
int1 ival={1}; half2 hval={0.0,0.1}; float3 fval={0.0f,0.1f,0.2f}; double4 dval={0.0,0.1,0.2,0.3};
vector <int, 1> ival={1}; vector <half, 2> hval={0.0,0.1}; vector <float, 3> fval={0.0f,0.1f,0.2f}; vector <double,4> dval={0.0,0.1,0.2,0.3};
ベクトル成分へのアクセス
以下のどちらかの命令セットを使ってアクセス。アクセス方法は次の通り。
位置セット:x,y,z,w
色セット:r,g,b,a
複数同時に指定することもできる。
float4 pos = float4(0,1,2,3);
float1 zval = pos.z;//zの値は2
float1 bval = pos.b;//bの値も2
float4 pos = float4(0,1,2,3);
float2 yzval = pos.yz;
float2 gbval = pos.gb;
float4 pos = float4(0,1,2,3); float4 val; val = pos; //4つの成分を書き込み val.xz = pos.xz;//2つの成分を書き込み val.zx = pos.xz;//2つの成分を順序変更して書き込み val.xzyw = pos.w; //1つの成分を複数の成分に書き込み val.wzyx = pos; //複数の成分を複数の成分に書き込み
ベクトルの計算
4成分の掛け算は次のように行う。これは、次のコードと同じ。
float4 val=a*b;
内積を計算するときはdot(a,b)とする。
float4 v;
v.x = a.x * b.x;
v.y = a.y * b.y;
v.z = a.z * b.z;
v.w = a.w * b.w;
コンストラクタ
データ型の初期化を行う。
float3 a = float3(0,1,0);//{0,1,0}の値で初期化
float4 b = float4(a,0);//{0,1,0,0}の値で初期化
float4 c = float4(a.xyz, 0);//{0,1,0,0}の値で初期化
行列型
行列型
行と列に1〜4つの成分を持つ特殊なデータ構造。データ型の末尾にある「数x数」は、行列の成分数「行x列」を示す。
vector型を使用して宣言することも可能。「<>」を使用して成分の型と数を指定。
float2x2 fmatrix = {0.1f. 0.1f, //行1 0.1f, 0.1f, //行2 };
matrix <float, 2, 2> fmatrix = {0.1f. 0.1f, //行1 0.1f, 0.1f, //行2 };
行列成分へのアクセス
以下のどちらかの命令セットを使ってアクセス。
0から数えた行列位置
_m00 _m01 _m02 _m03 _m10 _m11 _m12 _m13 _m20 _m21 _m22 _m23 _m30 _m31 _m32 _m33
1から数えた行列位置
_11 _12 _13 _14 _21 _22 _23 _24 _31 _32 _33 _34 _41 _42 _43 _44
float2x2 fmatrix = {0.1f. 0.1f, //行1 0.1f, 0.1f, //行2 }; float f; f = fmatrix._m00;//1つの成分を書き込み float2 f2; f2 = fmatrix._m00_m01;//2つの成分を書き込み
コンストラクタ
データ型の初期化を行う。
float4x4 d = float4x4({0,0,0,0},{1,1,1,1},{2,2,2,2},{3,3,3,3});
サンプラ
サンプラ
サンプリングするテクスチャを指定し、サンプリング時に実行するフィルタを制御。
テクスチャをサンプリングするには次の3つが必要。テクスチャのサンプリングに必要なコードは次の通り。
- テクスチャ
- サンプラ
- サンプリング命令
float4x4 worldViewProj : WORLDVIEWPROJECTION; texture cubeTexture; struct VS_INPUT { float4 pos : POSITION; float4 texcoord : TEXCOORD0; }; struct VS_OUTPUT { float4 pos : POSITION; float4 texcoord : TEXCOORD0; }; sampler textureSampler = sampler_state { Texture =<cubeTexture>; mipfilter=LINEAR; }; VS_OUTPUT VS_TextureTech(VS_INPUT In) { VS_OUTPUT Out=(VS_OUTPUT)0; Out.pos =mul(In.pos,worldViewProj); Out.texcoord=In.texcoord; return Out; } float4 PS_TextureTech(VS_OUTPUT Out) : COLOR { return tex2D(textureSampler,Out.texcoord).rgba; } technique TextureTech { pass P0 { vertexShader=compile vs_2_0 VS_TextureTech(); pixelShader =compile ps_2_0 PS_TextureTech(); } }
テクスチャはtexture型の変数cubeTextureを宣言。
サンプラはsampler型の変数textureSamplerを宣言。sampler_stateキーワードを使ってサンプラステートを指定。サンプラステートには、サンプリングするテクスチャと、オプションのフィルタステート(ラップモード、フィルタモード等)が含まれる。
ピクセルシェーダの処理を行う関数の中でサンプラ命令tex2D()を使用。サンプラ型として、sampler1D、sampler2D、sampler3D、sampleCubeの4つがあり、それに対応する組み込み関数tex1D、tex2D、tex3D、texCUBEを利用する。
float3 a = float3(0,1,0);//{0,1,0}の値で初期化
float4 b = float4(a,0);//{0,1,0,0}の値で初期化
float4 c = float4(a.xyz, 0);//{0,1,0,0}の値で初期化
float4x4 d = float4x4({0,0,0,0},{1,1,1,1},{2,2,2,2},{3,3,3,3});
その他のデータ型
構造体
stractキーワードで指定。
struct VS_OUTPUT { float4 pos : POSITION; float4 color : COLOR0; };
頂点シェーダオブジェクト
vertexShaderデータ型。アセンブリ言語のシェーダをアセンブルする時に使う。
HLSLの頂点シェーダをコンパイルする時にも使える。
vertxShader vs= asm { vs_2_0 dcl_position v0 mov oPos. v0 };
pixelShader =compile ps_2_0 PS_TextureTech();
ピクセルシェーダオブジェクト
pixelShaderデータ型。アセンブリ言語のシェーダをアセンブルする時に使う。
HLSLの頂点シェーダをコンパイルする時にも使える。
pixelShader ps= asm { ps_2_0 mov oC0. c0 };
pixelShader = compile ps_2_0 ApplyTexture();
テクスチャ
textureキーワードで指定。テクスチャを保持する。
uniform extern texture cubeTexture;
HLSLで使用可能な命令
演算子とフロー制御
演算子 +,-,*,/,&&,||,?,: if if (評価式) then 式1 [else 式2]
while while (評価式) 式 do〜while do 式 while (評価式); for for (評価式1;評価式2;評価式3) 式;
数学関数
vs_1_1 vs_2_0 ps_1_1 ps_1_4 ps_2_0 lerp,radians,saturate ○ ○ ○ ○○
abs,clamp,max,min,sign,step ○ ○ × ○ ○acos,asin,atan,atan2,ceil,cos,cosh,exp,degress,
exp2,floor,fmod,frac,frexp,isfinite,isinf,isnan,
ldexp,log,log2,log10,modf,pow,round,rsqrt,sin,
sincos,sinh,smoothstep,sqrt,step,tan,tanh ○ ○ × × ○ddx,ddy,fwidth ps_2_x以降
ベクトル関数
vs_1_1 vs_2_0 ps_1_1 ps_1_4 ps_2_0 dot,reflect ○ ○ ○ ○○
all,any,cross,faceforward ○ ○ × ○ ○distance,length,lit,normalize,refract ○ ○ × × ○
行列関数
vs_1_1 vs_2_0 ps_1_1 ps_1_4 ps_2_0 mul,transpose ○ ○ ○ ○○
determinant ○ ○ × ○ ○
テクスチャ関数
vs_1_1 vs_2_0 ps_1_1 ps_1_4 ps_2_0 tex1D,tex2D,tex3D,texCUBE × × ○ ○○
tex1Dproj,tex2Dproj,tex3Dproj,texCUBEproj
tex1Dbias,tex2Dbias,tex3Dbias,texCUBEbias × × × × ○clip × × ○ ○ ○
その他の関数
vs_1_1 vs_2_0 ps_1_1 ps_1_4 ps_2_0 D3DCOLORtoUBYTE4 ○ ○ × × ○noise tx_1_1(テクスチャシェーダ)