▼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 worldViewProj : WORLDVIEWPROJECTION;
float4x4」は4x4の行列であることを示すデータ型。

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つの成分を持つ特殊なデータ構造。データ型の末尾にある数は、ベクトルの成分数を示す。
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型を使用して宣言することも可能。「<>」を使用して成分の型と数を指定。
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;
これは、次のコードと同じ。
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;
内積を計算するときはdot(a,b)とする。

コンストラクタ
データ型の初期化を行う。
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列」を示す。
float2x2 fmatrix = {0.1f. 0.1f, //行1
                    0.1f, 0.1f, //行2
                   };
vector型を使用して宣言することも可能。「<>」を使用して成分の型と数を指定。
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データ型。アセンブリ言語のシェーダをアセンブルする時に使う。
vertxShader vs=
    asm {
        vs_2_0
        dcl_position v0
        mov oPos. v0
    };
HLSLの頂点シェーダをコンパイルする時にも使える。
pixelShader =compile ps_2_0 PS_TextureTech();


ピクセルシェーダオブジェクト
pixelShaderデータ型。アセンブリ言語のシェーダをアセンブルする時に使う。
pixelShader ps=
    asm {
        ps_2_0
        mov oC0. c0
    };
HLSLの頂点シェーダをコンパイルする時にも使える。
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(テクスチャシェーダ)




−戻る−