名前 |
表記 |
読み/書き |
説明 |
1_1 |
2_0 |
2_x |
3_0 |
ポート数 |
レジスタの名前 |
シェーダプログラムでの表記法 |
どのようなことができるか |
|
各バージョンでの最大数 |
1つの命令で同時に使える数 |
名前 |
表記 |
読み/書き |
説明 |
1_1 |
2_0 |
2_x |
3_0 |
ポート数 |
入力レジスタ |
v0〜v15 |
読 |
頂点入力 |
16 |
16 |
16 |
16 |
1 |
入力レジスタは、バージョン1_1では、位置座標レジスタ(Position Register)と呼ばれます。ポリゴンの頂点データが与えられます。
入力レジスタは、使う前に宣言する必要があります(命令のdcl_usage項目も見てください)。
dcl_position0 v0
この宣言命令によって、入力されるデータと、頂点シェーダの入力レジスタが関連付きます。
名前 |
表記 |
読み/書き |
説明 |
1_1 |
2_0 |
2_x |
3_0 |
ポート数 |
一時レジスタ |
r0〜r11 |
読/書 |
一時的に使う |
12 |
12 |
12〜 |
12〜 |
3 |
一時レジスタは、12個あります。r0〜r11が使われます。このレジスタは読み書きできます。1つの命令に3つもの一時レジスタが使えます。バージョン2_x以降では、レジスタの数は最低12個で、実際に使える値はD3DCAPS9.VS20Caps.NumTempsに記録されています。
名前 |
表記 |
読み/書き |
説明 |
1_1 |
2_0 |
2_x |
3_0 |
ポート数 |
定数レジスタ |
c0〜c255 |
読 |
定数 |
96 |
256 |
256 |
256 |
1 |
定数レジスタは、頂点に共通な座標変換の行列を設定したりします。アドレスレジスタを通した読み込みもできます。
それぞれのバージョンでの最大数は、最低のシステム構成の場合で、実際に使える値はD3DCAPS9.MaxVertexShaderConstに記録されています。
IDirect3DDevice9::SetVertexShaderConstantF(レジスタ番号,ポインタ,個数)で、アプリケーションプログラムから値を設定できます。または、シェーダプログラム内でdef命令を使って値を設定します。
名前 |
表記 |
読み/書き |
説明 |
数 |
ポート数 |
反復レジスタ |
i0〜i15 |
読/書 |
ループ用の3要素 |
16 |
1 |
整数型定数レジスタは、ループの回数を設定するため等に使います。
IDirect3DDevice9::SetVertexShaderConstantI(レジスタ番号,ポインタ,個数)で、アプリケーションプログラムから値を設定できます。ポインタで指し示すアドレスは、整数型のデータ配列でないといけません。または、シェーダプログラム内でdefi命令を使って値を設定します。
名前 |
表記 |
読み/書き |
説明 |
数 |
ポート数 |
分岐レジスタ |
b0〜b15 |
読 |
ブール値 |
16 |
1 |
IDirect3DDevice9::SetVertexShaderConstantB(レジスタ番号,ポインタ,個数)で、アプリケーションプログラムから値を設定できます。ポインタで指し示すアドレスは、BOOL型のデータ配列でないといけません。配列の次元は設定したい個数だけ必要です。
実際にはレジスタは1つだけで、内部的には16ビットの符号無し整数のレジスタとして処理されています。
名前 |
表記 |
読み/書き |
説明 |
数 |
ポート数 |
アドレスレジスタ |
a0 |
読/書 |
4次元アドレス |
1 |
1 |
アドレスレジスタは、バージョン1_1では、a0.x だけ、バージョン2_0以降ではa0.x、a0.y、a0.z、a0.wの4つの値が使えます。このレジスタにはバージョン1_1では、「mov」命令で、それ以外のバージョンでは「mova」命令で値を書き込むことができます。
アドレスレジスタの使い道は、固定レジスタを読み込む時に、
c[a0.x+20] |
のような形式でアドレスレジスタを動かしながら読むことです。
名前 |
表記 |
読み/書き |
説明 |
数 |
ポート数 |
ループカウンタレジスタ |
aL |
使用 |
ループカウンタ |
1 |
1 |
ループ命令の中だけで使えます。相対アドレス指定のために使います。
名前 |
表記 |
読み/書き |
説明 |
数 |
ポート数 |
プレディケーション |
p0 |
書/使用 |
動的フロー制御のためのフラグ |
1 |
1 |
ループ命令の中だけで使えます。相対アドレス指定のために使います。setp命令を使って値を設定します。
名前 |
表記 |
読み/書き |
説明 |
数 |
ポート数 |
サンプラ レジスタ |
s0〜s3 |
読 |
テクスチャ読み込み |
4 |
1 |
テクスチャサーフェスの指定につかいます。サンプラ レジスタは、テクスチャ ロード命令 texldl の引数だけに使われます。
名前 |
表記 |
読み/書き |
説明 |
数 |
位置レジスタ |
oPos |
書 |
射影座標 |
1 |
射影空間の座標を出力します。この座標を元に走査線変換が行われます。全ての成分について必ず出力する必要があります。ピクセルシェーダのバージョン2_xまでは、ピクセルシェーダから参照することはできません。
名前 |
表記 |
読み/書き |
説明 |
数 |
ディフューズ レジスタとスペキュラ レジスタ |
oD0,oD1 |
書 |
頂点色 |
2 |
2種類の色をピクセルシェーダに受け渡すことができます。ピクセルシェーダでは、oD0、oD1はそれぞれ、v0, v1のレジスタとして入力されます。
名前 |
表記 |
読み/書き |
説明 |
数 |
テクスチャ座標レジスタ |
oT0〜oT7 |
書 |
テクスチャ座標 |
8 |
8つのテクスチャ座標をピクセルシェーダに受け渡すことができます。ピクセルシェーダでは、oT0〜oT7はそれぞれ、t0〜t7のレジスタとして入力されます。
名前 |
表記 |
読み/書き |
説明 |
数 |
フォグレジスタ |
oFog |
書 |
フォグ濃度 |
1 |
フォグ濃度はoFog.xだけが使われます。また、値の範囲は自動的に0〜1の間に制限されます。フォグ濃度は深度などのテストが終わった後にピクセルの色と合成されます。ピクセルシェーダでは値を見ることができません。
名前 |
表記 |
読み/書き |
説明 |
数 |
スプライトサイズレジスタ |
oPts |
書 |
スプライトサイズ |
1 |
スプライトサイズはoPts.xだけが使われます。パーティクルを表示する時にそのサイズとして使われます。
名前 |
表記 |
読み/書き |
説明 |
数 |
出力レジスタ |
o0〜o11 |
書 |
結果の書き出し |
12 |
バージョン3_0の出力レジスタは、12 個の o# (出力) レジスタにまとめらています(2 つが色、8 つがテクスチャ、1 つが位置、1 つがフォグとポイント サイズです)。出力レジスタを使うときには、出力レジスタの宣言dcl_usageをしなくてはなりません。例えば、次の構文になります。
dcl_positiont o0.xyzw
命令数を増やさずにバリエーションを広げるために、命令やレジスタにくっつけて補正を行う記号が修飾子です。
命令の引数レジスタに使います。「-r0」と書きます。引数レジスタを−1倍した値が引数に使われます。
m3x2, m3x3, m3x4, m4x3, m4x4の命令の最後の引数は符号の反転ができません。
引数レジスタの成分を入れ替えます。「r0.yzxw」のように書きます。
「r0.xxxx」の場合は、「r0.x」と、1つに省略することもできます。
出力するレジスタの成分を制限します。
「r0.xw」のように書きます。並び順はxyzwでなければいけません。
出力レジスタに対するマスクにはいくつかの制限があります。スカラー型のレジスタoFogとoPtsでは、書き込みマスクは使えません。 oPos には、oPos.xyzwしかつかえません。 oT# には、.x か .xy か .xyz か .xyzwを指定します。
レジスタの絶対値を取得します。
「abs(r0)」のように書きます。
飽和命令修飾子_satは、書き込むときに、値を0から1の間に制限します。「mov_sat r0, v0」のように使います。frc 命令、sincos 命令や、テクスチャアドレッシング命令texld*、texkillには使えません。出力レジスタo#に対する出力にも使えません。
演算をするためのコマンドが命令です。命令は、バージョン1_1では128個、それ以上では256個まで使えます。
これらの命令は頂点シェーダプログラムの一番先頭に置く必要があります。
vs命令は必ず必要な命令です。バージョン情報の値に応じて、使える命令が決まります。
例えば次のように使います。
vs.2.0
最初の「2」がメジャーバージョン、後ろの「0」はマイナーバージョンと呼ばれます。
バージョンとしては、「1_0」、「1_1」、「2_0」、「3_0」があります。また、デバッグのための強制ソフトウェア実行のためのバージョン「2_sw」、「3_sw」というものも定義されています。
バージョンの数が大きいほど、つかる命令も多くなりますが、ハードウェア的に対応するグラフィックチップも少なくなるので、機能的に必要でないならば、なるべく小さな値を使うほうがいいでしょう。
頂点シェーダの入力レジスタがどの入力に割り当てられるのか宣言します。
この命令によって外部のcソースファイルと頂点シェーダプログラムのデータが結びつきます。
dcl_position v0
dcl_normal v3
dcl_texcoord0 v7
dcl_texcoord1 v7
テクスチャ座標(dcl_texcoord)など、複数の座標値を持つ場合があるので、宣言の後に何番目の入力か判断するための番号がつきます。
宣言の種類としては、11個の宣言がありえます。
dcl_position 位置座標
dcl_blendweight 座標値の合成の割合
dcl_blendindices合成する座標値の番号
dcl_normal 法線
dcl_psize 点のサイズ
dcl_diffuse 拡散光
dcl_specular 鏡面反射光
dcl_texcoord テクスチャ座標
dcl_tangent 接ベクトル
dcl_binormal 従法線ベクトル
dcl_tessfactor 曲面分割用の係数
定数の値をシェーダ内で決めるために使います。例えば、
def c0, 0.0f, 0.0f, 0.0f, 0.0f
のように使います。
この命令で定義された定数は外部からの設定(IDirect3DDevice9:: SetVertexShaderConstantF)よりも優先されます。
ブール型のレジスタの値を設定します。
defb b0, TRUE
のように使います。代入できる値は、TRUE(真)かFALSE(偽)です。
この命令で定義された定数は外部からの設定(IDirect3DDevice9:: SetVertexShaderConstantB)よりも優先されます。
整数型のレジスタの値を設定します。
defi i0, 0,10,1,0
のように使います。代入できる値は、TRUE(真)かFALSE(偽)です。
この命令で定義された定数は外部からの設定(IDirect3DDevice9::
SetVertexShaderConstantI)よりも優先されます。
これらの命令は一般的な計算をするのに用いられます。
なにもしません。ほとんど使わない命令ですが、分岐命令などでの処理時間を調整するために使えそうです。
nop
ただし、バージョン1_1では、スロット数は0なので、全く何もしません。
値を一つのレジスタから別のレジスタにコピーします。
mov r0, c0
それぞれのレジスタの成分では次の処理がなされます。
r0.x = c0.x
r0.y = c0.y
r0.z = c0.z
r0.w = c0.w
mova 命令は浮動小数点数を扱うレジスタから、アドレスレジスタへ値をコピーします。与えられた浮動小数点数に一番近い整数に値を代入します(小数点以下切り捨てではありません)。
mova a0, c0
2つのレジスタの足し算をします。
add r1, r0, c0
r1.x = r0.x + c0.x
r1.y = r0.y + c0.y
r1.z = r0.z + c0.z
r1.w = r0.w + c0.w
引き算します。といっても足し算をする時に負数(-r0等)が使えるので、足し算で代用できます。まぁ、いらない命令といえばいらない命令です。
sub r1, r0, c0
r1.x = r0.x - c0.x
r1.y = r0.y - c0.y
r1.z = r0.z - c0.z
r1.w = r0.w - c0.w
各成分ごとの掛け算をします。
mul r1, r0, c0
r1.x = r0.x * c0.x
r1.y = r0.y * c0.y
r1.z = r0.z * c0.z
r1.w = r0.w * c0.w
掛け算と足し算を同時に行います。それぞれの命令を別々に計算するよりも命令数が減るので、mad命令を使うほうが高速化につながります。
mad r2, r0, r1, c0
r2.x = r0.x * r1.x + c0.x
r2.y = r0.y * r1.y + c0.y
r2.z = r0.z * r1.z + c0.z
r2.w = r0.w* r1.w + c0.w
積和計算を使って、転置行列の計算ができます。転置行列は、
mul r0,
c0, r1.x
mad r0,
c1, r1.y, r0
mad r0,
c2, r1.z, r0
mad r0, c3, r1.w, r0
を使えば計算できます。
3次元ベクトルの内積を計算します。
dp3 r1, r0, c0
r1.x = r1.y = r1.z = r1.w = r0.x*c0.x+ r0.y*c0.y+ r0.z*c0.z
4次元ベクトルの内積を計算します。
dp4 r1, r0, c0
r1.w = r0.x*c0.x+ r0.y*c0.y+ r0.z*c0.z+ r0.w*c0.w
r1.x = r1.y = r1.z :使われない
dp4命令を使えば、4次元行列と、4次元ベクトルの作用の計算ができます。例えば、
の計算は、
dp4 r1.x, r0, c0
dp4 r1.y, r0, c1
dp4 r1.z, r0, c2
dp4 r1.w, r0, c3
の命令で計算ができます(実は,この計算をまとめたものがマクロ命令のm4x4です)。
距離ベクトルを計算します。実際に行われる計算は、
crs r1, r0, c0
r1.x = 1
r1.y = r0.y *c0.y
r1.z = r0.z
r1.w = c0.w
です。この計算は、2つめの引数のレジスタに(使わない, d*d, d*d, 使わない)を用意しておき、3つめの引数のレジスタに(使わない, 1/d, 使わない, 1/d)を用意しておくと、べき乗(1, d, d*d, 1/d)が求まります。結果として、距離dのオイラーマクローリン展開の低次の項を求めるのに便利になります。
x成分の逆数を計算します。明示的に添え字がつけられているときは、添え字の成分の逆数を計算します。引数のレジスタには、どの成分を使うのか必ず1つだけ指定しなくてはなりません。
元になる数字が1.0fの時は、結果は1.0になります。元になる数字が0.0fの時は、正の無限大の値が返ります。
rcp r0, c0.w
r0.x = r0.y = r0.z = r0.w = 1.0f/c0.w
頂点シェーダの命令には、割り算が無いので、割り算は、
rcp r0.w, r0.w
mul r1, r1, r0.w ; r1 = r1÷r0.w
の方法で2命令使って、計算します。
x成分の絶対値の逆数の平方根を計算します。明示的に添え字がつけられているときは、添え字の成分を計算します。
元になる数字が1.0fの時は、結果は1.0になります。元になる数字が0.0fの時は、正の無限大の値が返ります。
rsq r0, c0.w
r0.x = r0.y = r0.z = r0.w = 1.0f / sqrt|c0.w|
頂点シェーダには平方根を計算する命令がありませんが、rsq命令を使えば、平方根を計算できます。
; r0.x = sqrt(r1.x)
rsq r0.x,
r1.x
; r0.x = 1/sqrt(r1.x)
mul r0.x, r1.x, r0.x ; r0.x = r1.x * (1/sqrt(r1.x)) = sqrt(r1.x)
2つの入力のうち、大きい方を返します。
max r1, r0, c0
r1.x = (r0.x<c0.x)?c0.x:r0.x
r1.y = (r0.x<c0.x)?c0.y:r0.y
r1.z = (r0.x<c0.x)?c0.z:r0.z
r1.w = (r0.x<c0.x)?c0.w:r0.w
例えば、値の下限値を0に制限したいときに、
def c0, 0.0f, 0.0f, 0.0f, 0.0f
max r0, r0, c0
と計算すれば、r0が負の時でも、0に抑えることができます。
2つの入力のうち、小さい方を返します。
min r1, r0, c0
r1.x = (r0.x<c0.x)?r0.x:c0.x
r1.y = (r0.y<c0.y)?r0.y:c0.y
r1.z = (r0.z<c0.y)?r0.z:c0.z
r1.w = (r0.w<c0.z)?r0.w:c0.w
例えば、値の上限値を1に制限したいときに、
def c0, 1.0f, 1.0f, 1.0f, 1.0f
max r0, r0, c0
と計算すれば、r0が1より大きい時でも、1に抑えることができます。
第2引数の値が第3引数の値以上の場合は、結果である第一引数のレジスタに 1.0 を設定します。それ以外の場合は、結果に 0.0 を返します。
sge r1, r0, c0
r1.x = (r0.x>=c0.x)?1:0
r1.y = (r0.y>=c0.y)? 1:0
r1.z = (r0.z>=c0.z)? 1:0
r1.w = (r0.w>=c0.w)? 1:0
1つめの引数のレジスタの値が2つめの引数のレジスタの値未満の場合は、結果のレジスタに 1.0 を設定します。それ以外の場合は、結果に 0.0 を返します。
sge r1, r0, c0
r1.x = (r0.x < c0.x)?1:0
r1.y = (r0.y < c0.y)? 1:0
r1.z = (r0.z < c0.z)? 1:0
r1.w = (r0.w < c0.w)? 1:0
この命令は光源計算の部分的な手助けをします。出力した値のy成分が平行光源の成分として、z成分がスペキュラの成分に使えます。x成分は、しいていえば環境光に使えます。バージョン1_1では、1スロットで処理しますが、バージョン2_0以降は3スロット消費します。
lit r1, r0
r1.x = 1
r1.y = max(N・L, 0)
r1.z = (N・H)r0.w (L・N, H・Nのどちらかが負の場合は0)
r1.w = 1
入力するレジスタの値は次の値を入れる必要があります。
r0.x = N ・ L (法線ベクトルと光源ベクトルの内積)
r0.y = N ・ H (法線ベクトルと半ベクトルの内積)
r0.w = スペキュラーの強さを示すべき乗 (+128 〜 -128じゃなきゃだめ)
ハーフベクトルは、頂点から視点の方向を示す視線ベクトルと光源ベクトルの方向の平均を取ったベクトルです。N,HおよびLベクトルは規格化したものに関して内積を計算していなくてはなりません。
これらの命令はより複雑な計算をするのに用いられます。ほとんどの命令が2つの命令以上の命令時間がかかります。
3x2行列と3次元ベクトルの計算をします。この命令は、2スロット消費します。結果のレジスタには、書き込みマスク.xyが必要です。
m3x2 r1.xy, r0, c0
r1.x = r0.x*c0.x + r0.y*c0.y + r0.z*c0.z
r1.y = r0.x*c1.x + r0.y*c1.y + r0.z*c1.z
最後の引数のレジスタは、行列の最初のレジスタを指定します。計算には、最初のレジスタ(c0)と次の数字のレジスタ(c1)が使われます。最後の引数のレジスタには、入れ換えおよび正負の反転の修飾子は使えません。
3x3行列と3次元ベクトルの計算をします。この命令は、3スロット消費します。結果のレジスタには、書き込みマスク.xyzが必要です。
m3x3 r1.xyz, r0, c0
r1.x = r0.x*c0.x + r0.y*c0.y + r0.z*c0.z
r1.y = r0.x*c1.x + r0.y*c1.y + r0.z*c1.z
r1.z = r0.x*c2.x + r0.y*c2.y + r0.z*c2.z
計算には、最初のレジスタ(c0)から3つのレジスタ(c2まで)が使われます。最後の引数のレジスタには、入れ換えおよび正負の反転の修飾子は使えません。
3x4行列と3次元ベクトルの計算をします。この命令は、4スロット消費します。結果のレジスタには、書き込みマスク.xyzwが必要です。
m3x4 r1.xyzw, r0, c0
r1.x = r0.x*c0.x + r0.y*c0.y + r0.z*c0.z
r1.y = r0.x*c1.x + r0.y*c1.y + r0.z*c1.z
r1.z = r0.x*c2.x + r0.y*c2.y + r0.z*c2.z
r1.w = r0.x*c3.x + r0.y*c3.y + r0.z*c3.z
計算には、最初のレジスタ(c0)から4つのレジスタ(c3まで)が使われます。最後の引数のレジスタには、入れ換えおよび正負の反転の修飾子は使えません。
4x3行列と4次元ベクトルの計算をします。この命令は、3スロット消費します。結果のレジスタには、書き込みマスク.xyzが必要です。
m4x3 r1.xyz, r0, c0
r1.x = r0.x*c0.x + r0.y*c0.y + r0.z*c0.z + r0.w*c0.w
r1.y = r0.x*c1.x + r0.y*c1.y + r0.z*c1.z + r0.w*c1.w
r1.z = r0.x*c2.x + r0.y*c2.y + r0.z*c2.z + r0.w*c2.w
計算には、最初のレジスタ(c0)から3つのレジスタ(c2まで)が使われます。最後の引数のレジスタには、入れ換えおよび正負の反転の修飾子は使えません。
4x4行列と4次元ベクトルの計算をします。この命令は、4スロット消費します。結果のレジスタには、書き込みマスク.xyzwが必要です。
m4x4 r1.xyzw, r0, c0
r1.x = r0.x*c0.x + r0.y*c0.y + r0.z*c0.z + r0.w*c0.w
r1.y = r0.x*c1.x + r0.y*c1.y + r0.z*c1.z + r0.w*c1.w
r1.z = r0.x*c2.x + r0.y*c2.y + r0.z*c2.z + r0.w*c2.w
r1.w = r0.x*c3.x + r0.y*c3.y + r0.z*c3.z + r0.w*c3.w
計算には、最初のレジスタ(c0)から4つのレジスタ(c3まで)が使われます。最後の引数のレジスタには、入れ換えおよび正負の反転の修飾子は使えません。
入力した値の絶対値を求めます。この命令は、1スロット消費します。
abs r0, c0
r0.x = |c0.x|
r0.y = |c0.y|
r0.z = |c0.z|
r0.w = |c0.w|
バージョン1_1では、abs命令は使えませんが、max命令を使えばabs命令を作ることができます。
max r0, r1, -r1 ; r0 = |r1|
入力した値が正か負かに応じて1か−1の値を返します。この命令は3スロット消費します。
abs r0, c0
r0.x = (c0.x<0)?-1:( (0<c0.x)?+1:0);
r0.y = (c0.y<0)?-1:( (0<c0.y)?+1:0);
r0.z = (c0.z<0)?-1:( (0<c0.z)?+1:0);
r0.w = (c0.w<0)?-1:( (0<c0.w)?+1:0);
入力するレジスタと出力するレジスタは違うものにする必要があります。
バージョン1_1では、sgn命令は使えませんが、slt命令を使えばsgn命令を作ることができます。
def c0, 0.0f, 0.0f, 0.0f, 0.0f
slt r1, r0, c0.x
slt r0, -r0, c0.x
add r0, r0, -r1
ベクトルの外積を計算します。この命令は2スロット消費します。
crs r1.xyz, r0, c0
r1.x = r0.y * c0.z – r0.z*c0.y
r1.y = r0.z * c0.x – r0.y*c0.z
r1.z = r0.x * c0.y – r0.x*c0.y
書き込みマスクには、.x、.y、.z、.xy、.xz、.yz、.xyzを指定しなくてはなりません。引数と結果のレジスタは全て別のレジスタにしないといけません。結果を格納するレジスタは一時レジスタr#でなくてはいけません(つまり、出力レジスタを指定してはいけないということです)。
バージョン1_1では、crs命令は使えませんが、成分の入れ替えを使えばcrs命令を作ることができます。
mul r1, r0.yzxw, c0.zxyw
mad r1, - c0.yzxw, r0.zxyw, r1
3次元ベクトルを正規化します。この命令は3スロット消費します。
nrm r1, r0
r1.x = r0.x / d
r1.y = r0.y / d
r1.z = r0.z / d
この命令は入力に使うレジスタと結果に使うレジスタを同じレジスタにすることは出来ません。
バージョン1_1では、nrm命令は使えませんが、rsq命令を使えばnrm命令を作ることができます。
dp3 r1.x, r0 ; r1.x = r0・r0
rsq r1.x, r1.x ; r1.x = 1/sqrt(r1.x)
mul r1.xyz, r1.x, r0 ; r1.xyz = r0.xyz * (1/sqrt(r1.x)) = r0.xyz/ sqrt(r0・r0)
3つめの引数のレジスタと、4つめの引数のレジスタを2つめの引数の重みで線形補間します。この命令は2スロット消費します。
lrp r2, c0, r0, r1
r2.x = c0.x*r0.x + (1-c0.x)*r1.x
r2.y = c0.y*r0.y + (1-c0.y)*r1.y
r2.z = c0.z*r0.z + (1-c0.z)*r1.z
r2.w = c0.w*r0.w + (1-c0.w)*r1.w
2を底とする10ビットの部分精度の指数を求めます。入力が負の値の場合の結果は定められていないので、正の値で入力しなくてはなりません。それぞれの成分には次の値が入力されます。z成分に指数の値が返ります。
out.x = 2 ^ (int)in.w
out.y = 小数部(in.w)
out.z = 2 ^ in.w (近似解)
out.w = 1.0
実際に使うときは、
expp r0, c0.w
のように、入力するレジスタの成分を書き下す必要があります。
最低でも仮数部が21ビットの精度を持った2を低とする指数を求めます。この命令は、バージョン1_1では10スロット消費しますが、2_0以上では1スロット消費します。
exp r0, c0.w
r0.x = r0.y = r0.z = r0.w = 2c0.w
2を底とする10ビットの部分精度の対数を求めます。入力した数の絶対値の対数が結果として返ります。入力した値が0の時は負の無限大が返ります。
logp r0, c0.w
r0.x=r0.y=r0.z=r0.w = log|c0.w|/log2
最低でも仮数部が21ビットの精度を持った2を低とする対数を求めます。この命令は、バージョン1_1では10スロット消費しますが、2_0以上では1スロット消費します。
log r0, c0.w
r0.x=r0.y=r0.z=r0.w = log|c0.w|/log2
入力した数の絶対値の対数が結果として返ります。入力した値が0の時は負の無限大が返ります。
15ビットの精度を持つべき乗の計算をします。この命令は3スロット消費します。入力に使うレジスタには、どの成分を使うかしてしなくてはなりません。結果は全ての成分に同じ値が入力されます。底となるレジスタの値は絶対値をとったものが使われます。
pow r1, c0.w, r0.w
r1.x=r1.y=r1.z=r1.w = |r0.w|c0.w
結果を入れるレジスタは、一時レジスタでなければいけません。さらに、最後の引数と同じレジスタもつかえません。
サインとコサインを計算します。この命令は8スロット消費します。
sincos r1, r0.w, c0, c1
−π≦r0.w≦πの範囲に収まる必要がある
c0 = (-1.f/(7!*128), -1.f/(6!*64), 1.f/(4!*16), 1.f/(5!*16))
c1 = (-1.f/(3!*8), -1.f/(2!*8), 1.f, 0.5f)
の定数レジスタでなければいけない。
r1.x = cos(r0.w)
r1.y = sin(r0.w)
誤差の最大値は0.02になります。
入力された数値の小数部を返します。この命令は、バージョン1_1では3スロット消費しますが、2_0以上では1スロット消費します。結果は必ず0.0から1.0の間に収まります。
frc r0, c0
バージョン1_1を使うときには、書き込みマスクを.xyもしくは.yのどちらかにしなくてはなりません。
条件分岐による制御を行います。頂点シェーダ2_0から使えるようになりました。ただし、計算結果を使って分岐を行う動的フロー制御は、2_xから導入されたプレディクションレジスタによる処理の切り替えとして実装されます。
分岐レジスタの値に応じて、2つの処理を切り替えます。if命令は3スロット、elseは1スロット、endif命令は1スロット消費します。
if b0
なんかの処理
else
べつの処理
endif
b0が1(TRUE)の時は、if〜elseの間にある命令が実行されます。b0が0(FALSE)の時は、else〜endifの間の命令が実行されます。if ブロックはネストすることができますが、loop ブロックをまたぐことはできません。
2つのレジスタを比較して、その結果に応じてそれぞれ別の命令を実行します。if_comp命令は3スロット消費します。
if_lt r3.x, r4.y
// r3.x < r4.y の時に実行する命令
else
// r3.x >= r4.y の時に実行する命令
endif
比較の内容には、次の種類があります。レジスタの成分は必ず指定しなくてはなりません。
構文 |
比較 |
(if_comp src0, src1でTRUEになる場合) |
_gt |
より大きい |
(src0 > src1) |
_lt |
より小さい |
(src0 < src1) |
_ge |
以上 |
(src0 >= src1) |
_le |
以下 |
(src0 <= src1) |
_eq |
等しい |
(src0 == src1) |
_ne |
等しくない |
(src0 != src1) |
if_compは、if predと一緒に24階層までネストできます。
レディケーション レジスタの内容に基づいて命令を使い分けます。if pred命令は3スロット消費します。
if p0.適当な成分
なんかの処理
else
べつの処理
endif
否定演算子!を使うことによって、p0がFALSEの時の分岐が実現できます。
if !p0.適当な成分
if predは、if_compと一緒に24階層までネストできます。
サブルーチンは、labelとretでくくられた命令を呼び出して実行します。call命令は2スロット、retは1スロット、label命令は0スロット消費します。
call 1
なんかの処理
label 1
サブルーチン命令
ret
labelとして使える数字は2_0、2_xでは0〜15、3_0では0〜2047です。Labelの位置は、call命令の後ろに置かなければなりません。
2_0では、再帰はできません。3_0では、4階層まで再帰できます。2_xでは、D3DCAPS9.VS20Caps.StaticFlowControlDepthの値によってネストの深さが決まります。
条件付きサブルーチンは、分岐レジスタの値がTRUEの場合にサブルーチンを実行します。callnz命令は3スロット消費します。
callnz ラベル番号, b# |
プレディケーションに基くサブルーチン呼び出しは、プレディケーション レジスタの値がTRUE(!がついている場合はFALSE)の場合にサブルーチンを実行します。callnz pred命令は3スロット消費します。
callnz ラベル番号, [!] p0. 適当な成分 |
反復は、反復レジスタを見て処理を繰り返します。rep命令は3スロット、endret命令は2スロット消費します。
rep i0 ループ内処理 endrep |
整数レジスタのx成分は繰り返し回数になります。ループの最大回数は255回です。反復はネストできません。反復のループの中にジャンプして入ってきたり、飛び出たりすることはできません。また、ifブロックをまたぐこともできません。break命令や、break_comp、break pred 命令でループを抜けることができます。
反復ループは、整数レジスタi#を見て処理を繰り返すと共に、ループカウンタaLを使って、定数レジスタの番号をずらしながら読み込めます。loop命令は3スロット、endloop 命令は2スロット消費します。
loop aL, i0 ループ内処理 (aLが定数レジスタの指定に使える) endloop |
i0.xにループ回数、i0.yにaLレジスタの初期値、i0.zにaLレジスタの増加数を入れます。ループはネストできません。if文をまたげません。break命令や、break_comp、break pred 命令でループを抜けることができます。ループの初期値およびループの繰り返し数は負にできません。
repまたはloopによるフロー制御を中断します。break命令は1スロット、break_comp, break pred 命令は3スロット消費します。break_compは、2つのレジスタの比較に伴うループの中断をします。
break_comp src0, src1 |
比較修飾子_compは、if_compと同じ修飾子が使えます。
break predは、プレディクションレジスタを比較してループの中断をします。
break [!]p0.成分 |
否定修飾子「!」をつけると、p0がFALSEの時にループを中断します。
レジスタの比較によって、プレディケーションレジスタを設定します。setp命令は1スロット消費します。
setp_comp p0, src0, src1 |
比較修飾子_compには、次の種類があります。
構文 |
比較 |
(setp_comp p0, src0, src1でTRUEになる場合) |
_gt |
より大きい |
(src0 > src1) |
_lt |
より小さい |
(src0 < src1) |
_ge |
以上 |
(src0 >= src1) |
_le |
以下 |
(src0 <= src1) |
_eq |
等しい |
(src0 == src1) |
_ne |
等しくない |
(src0 != src1) |
プレディケーションレジスタは、if pred、callnz pred、break pred以外に、次の構文を使って、任意の算術命令やテクスチャ命令の実行を制御できます。ただし、命令スロットを1消費します。
([!]p0[.成分]) 命令 dest, src0, ... |
プレディケーションレジスタの成分の指定には、.xyzw, もしくは1つだけの成分、.x, .y. .z, .wを指定することができます。