B)     ピクセルシェーダリファレンス

 

 

b-1 レジスタ

 

b-1-1カラー レジスタ(Vertex Color Register 1_X, 2_0, 2_x, 3_0)

名前

/書

説明

1_1

1_2

1_3

1_4

2_0

2_x

3_0

ポート数

v0,v1

2

10

頂点シェーダの色出力がピクセルごと補間されて入力されます。ポート数は、バージョン1_Xでは2つになります。

バージョン2_0以降では、頂点色レジスタは、使う前に宣言する必要があります。

dcl v0.rgba

宣言をするときの指定は、rbga でもxyzwでもかまいません。

 

b-1-2 テクスチャ座標レジスタ(Texture Coordinate Register 1_X, 2_0, 2_x)

名前

/書

説明

1_1

1_2

1_3

1_4

2_0

2_x

ポート数

t0〜t7

/書

テクスチャ座標

4

6

8

頂点シェーダのテクスチャ座標出力がピクセルごと補間されて入力されます。バージョン1_Xでは固定小数点、それ以降では浮動小数点数で処理されます。ポート数は、バージョン1_1では2つ、バージョン1_2,1_3では3つです。バージョン1_Xでは値の範囲に制限が設けられていて、バージョン1_3までは±D3DCAPS9.PixelShader1xMaxValue、バージョン1_4では±D3DCAPS9.MaxTextureRepeatの間の値しか設定できません。

バージョン2_0以降では、使う前に宣言する必要があります。

dcl t0

 

b-1-3 一時レジスタ(Temporary Register:1_X, 2_0, 2_x, 3_0)

 

名前

/書

説明

1_1

1_2

1_3

1_4

2_0

2_x

3_0

ポート数

r0〜r11

/書

一時的に使う

2

6

12

32

一時レジスタは、計算の途中の値を保存するために使われます。バージョン1_Xでは固定小数点、それ以降では浮動小数点数で処理されます。ポート数は、バージョン1_3以下では2つになります。バージョン1_Xでは、値の範囲は±D3DCAPS9.PixelShader1xMaxValueに制限されます。

 

b-1-4浮動小数点型定数レジスタ(Constant Register:1_X, 2_0, 2_x, 3_0)

名前

/書

説明

1_1

1_2

1_3

1_4

2_0

2_x

3_0

ポート数

c0〜c31

定数

8

32

224

1(sincos命令では2つ)

def命令によって値を代入することが出来ます。

def c0, 1.0, 1.0, 1.0, 1.0

もしくは IDirect3DDevice9::SetPixelShaderConstantF を使って設定します。def命令のほうが優先度は高くなります。

値は順に赤、緑、青、αの成分に入れられます。0.0が黒になり、1.0が一番強い色になります。バージョン1_Xでは、1つの命令に2つの定数レジスタを使うことができます。ただし、値は-1〜1の間しか使えません。バージョン2_0以降では、基本的には1つの命令に1つのレジスタしか使えませんが、sincos命令だけは例外で、sincos命令を使うときだけは、2つの定数レジスタが使えます。

 

b-1-5 サンプリングステージレジスタ(Sampling Stage Register:2_0, 2_x, 3_0)

名前

/書

説明

ポート数

s0〜s15

テスクチャ読み込み

16

このレジスタは、texldとtexldpで使用されます。それぞれのレジスタは、IDirect3DDevice9::SetTextureによって設定されたテクスチャと関連付けられます。使う前に宣言する必要があります。

dcl _2d s0      ;2次元テクスチャ

dcl _cube s0    ;キューブマップ

dcl _volume s0  ;ボリュームテクスチャ

宣言は、テクスチャ命令よりも先におく必要があります。

 

b-1-6整数型定数レジスタ(2_x, 3_0)

名前

/書

説明

ポート数

i0〜i15

整数型定数

16

このレジスタは、loop と rep命令で使います。defi または IDirect3DDevice9::SetPixelShaderConstantI を使って設定します。defi命令のほうが優先度は高くなります。

 

b-1-7ブール型定数レジスタ(2_x, 3_0)

名前

/書

説明

ポート数

b0〜b15

ブール型定数

16

このレジスタは、if文などのフロー制御の条件判定に使われます。defb または IDirect3DDevice9::SetPixelShaderConstantB を使って設定します。defb命令のほうが優先度は高くなります。

 

b-1-8ループ カウンタ レジスタ(2_x, 3_0)

名前

/書

説明

ポート数

aL

-

ループ中のカウンタ

1

-

loopブロック内で、動的な相対アドレスの指定をするために使います。

 

b-1-9プレディケーション(2_x, 3_0)

名前

/書

説明

ポート数

p0

/書

動的フロー制御

1

レジスタに値を代入するには、setp命令による比較演算を使用します。

プレディケーションレジスタを使って、成分単位に命令の実行の制御を行うことができます。たとえば、次のように使います。

(p0) add r1, r2, r3

 この結果、r1レジスタには、プレディケーションレジスタがTRUEになっている成分だけにr2+r3の結果が保存されます。

 

b-1-10面レジスタ(3_0)

名前

/書

説明

ポート数

vFace

背面チェック

1

描画したポリゴンが裏を向いているときに、値は負になります。面レジスタは、setp 命令と if comp 命令でだけ使えます。このレジスタを使うときには、宣言「dcl vFace」が必要です。

 

b-1-10位置座標レジスタ(3_0)

名前

/書

説明

ポート数

vPos

テスクチャ読み込み

1

現在のピクセル位置座標 (x, y) が入ります。このレジスタを使うときには、宣言「dcl vPos.xy」が必要です。

 

b-1-6出力レジスタ(Putput Register)

 

名前

説明

oC0〜oC3

ピクセル色の出力

oDepth

深度の出力

それぞれの出力レジスタに対して1度しか書き込むことはできません。バージョン1_Xでは、r0レジスタが唯一の出力色レジスタとして使われます。

 

b-2 修飾子

 

 

b-2-1入力引数修飾子(Register Modifiers)

引数として算術命令にレジスタを指定するときに、値を補正するために使います。レジスタの内容は変化しません。

命令

機能

構文

バージョン

 

 

1_0

1_1

1_2

1_3

1_4

2_0, 2_x

3_0

バイアス

値を 0.5下にシフトする。y = x-0.5。

r0.bias

×

×

補数

補数を計算する (y = 1.0 - x)。符号なし x が必要。

1-r0

×

×

正負の反転

値の正負を反転する (y = -x)。符号付き x が必要。

-r0

2倍スケーリング

データを 2 倍にスケーリングする。y = 2*x。

r0_x2

×

×

×

×

×

×

符号化スケーリング

値を下にシフトし、データを 2 倍にスケーリングする。y = 2*(x-0.5)。

r0_bx2

×

×

絶対値

レジスタの値の絶対値を使う。

abs

×

×

×

×

×

×

定数レジスタには使えません。符号の反転は、他の命令のバイアス、2倍スケーリング、符号化スケーリングと一緒に使うことができます。

バージョン 1_1 では、符号化スケーリングは、任意の texm* 命令の入力引数で使うことができます。バージョン 1_2 または 1_3 では、符号化スケーリングは、任意のテクスチャ アドレシング命令の入力引数で使うことができます。

 

b-2-2転送先の入れ換え(Source Register Selectors)

この修飾子は、ひとつの色成分を全ての成分に出力します。この修飾子は、入力引数修飾子と一緒に使えます。

 

構文

バージョン

 

1_1

1_2

1_3

1_4

2_0〜

赤色の成分

r0.r

×

×

×

×

緑色の成分

r0.g

×

×

×

×

青色の成分

r0.b

α成分

r0.a

2_x以降では、任意の成分の入れ替えを行うことができます。

 

b-2-3命令修飾子(Instruction Modifiers)

命令修飾子はシェーダの算術命令を終わって、レジスタに書き込まれる前に修正が行われます。

修飾子

機能

構文

バージョン

 

 

1_1

1_2

1_3

1_4

2_0,2_x

3_0

_x2

結果を2倍する

r0_x2

×

×

_x4

結果を4倍する

r0_x4

×

×

_x8

結果を8倍する

r0_x8

×

×

×

×

×

_d2

結果を2で割る

r0_d2

×

×

_d4

結果を4で割る

r0_d4

×

×

×

×

×

_d8

結果を8で割る

r0_d8

×

×

×

×

×

_sat

0から1の範囲に収める

r0_sat

_pp

低い演算精度で格納する

r0_pp

×

×

×

×

_centroid

マルチサンプリングにおいて重心がプリミティブ外にあるときの補正

t0_centroid

×

×

×

×

×

命令修飾子は、_sat命令とそれ以外を組み合わせて使うことができます。

_sat 命令修飾子は、frc 命令および sincos 命令、 texld* および texkill では使えません。また、出力レジスタo#に書き込む命令でも使えません。

_centroid修飾子は、texld* 命令、dsx および dsy で設定されます。

 

b-2-4書き込みマスク(Register Write Masks)

書き込みマスクは、命令の結果を書き出す成分を選べます。

 

機能

構文

バージョン

 

1_1

1_2

1_3

1_4

2_0, 2_x

赤緑青α

赤緑青αの全てを出力します

r0.rgba

なし

赤緑青αの全てを出力します

r0

色成分

色の成分(赤緑青)を出力します

r0.rgb

α成分

α成分だけを出力します

r0.a

赤色の成分

赤色成分だけを出力します

r0.r

×

×

×

緑色の成分

緑色成分だけを出力します

r0.g

×

×

×

青色の成分

青色成分だけを出力します

r0.b

×

×

×

任意の出力

好きな成分に出力します

r0.rb等

×

×

×

任意の出力をするときも、並び方は、r、g、b、α、の順になっていなくてはなりません。

色成分と、α成分の出力マスクに関して、特別な修飾子が使えます。内部的には、色の成分とα成分は別々に計算されています。それらの計算に関して特別に2命令を並列に計算することができます。すなわち、

mov r0.rgb c0

+mov r0.a c1

のように色成分と、α成分への出力を「+」の記号でつないで、1命令のように使うことができます。

この方法は、命令数が減らせますが、それ同時に高速化も図られます。

 

b-2-5テクスチャレジスタ修飾子(Texture Register Modifiers)

ピクセルシェーダ1.4で導入された「texld」や「texcrd」命令のための修飾子が、テクスチャレジスタ修飾子です。

 

入力引数修飾子は、透視変換前の座標がテクスチャレジスタに入力されたときにテクスチャ座標に変換するために使います。

修飾子

機能

構文

 

 

_dz

x、y成分をz成分で割る

t0_dz

_db

t0_db

_dw

x、y成分をw成分で割る

t0_dw

_da

t0_dz

 

転送先の入れ替えもサポートされています。

修飾子

機能

構文

 

 

xyz

x、y、z、の値を、x、y、z、wの成分にx、y、z、zと振り分ける。

t0.xyz

rgb

t0.rgb

xyw

x、y、z、の値を、x、y、z、wの成分にx、y、w、wと振り分ける。

t0.xyw

rga

t0.rga

texld」や「texcrd」では、x、y、zの3成分をテクスチャ座標に使います。この修飾子はz成分をzにするかwにするか選択するための修飾子です。

 

書き込みマスクも存在しますが、命令によって使える修飾子が違います。

修飾子

機能

構文

命令

 

texld

texcrd

xyzw

赤緑青αの全てを出力します

r0.xyzw

×

rgba

r0.rgba

×

なし

r0

×

xyz

色成分(赤緑青)だけを出力します

 

r0.xyz

×

rgb

r0.rgb

×

xy

xy成分だけを出力します

 

r0.xy

×

rg

r0.rg

×

任意の出力をするときも、並び方は、r、g、b、α、の順になっていなくてはなりません

 

b-3 命令

 

b-3-1 セットアップ命令 (Setup Instructions)

セットアップ命令は、シェーダプログラムの先頭に置かれて(phase命令だけは中間に入りますが)、色々な宣言や初期化をします。

 

      ps (バージョン情報: 1_X, 2_0, 2_x, 3_0)

ピクセルシェーダプログラムのバージョンを指定するのに使います。バージョンが違えば、使える命令やレジスタが違うので、やりたいことができるバージョンを指定しなくてはなりません。

この命令はシェーダプログラムの先頭に置きます。

バージョン番号は、メインバージョン番号と、サブバージョン番号の2つの数字があります。具体的な使い方は、

ps_3_0

にのように「_」で区切ります。指定できるバージョンには、「ps_1_1」、「ps_1_2」、「ps_1_3」、「ps_1_4」、「ps_2_0」、「ps_2_x」、「ps_3_0」及び「ps_2_sw」と「ps_3_sw」です。「ps_X_sw」は、ソフトウェア シェーダと呼ばれるもので、2_xや3_0の開発をハードウェアなしで行うためのもので、パフォーマンスは悪いです。

 

      def (浮動小数点型定数の定義: 1_X, 2_0, 2_x, 3_0)

ピクセルシェーダ内で使用する浮動小数点型定数の定数レジスタの値を設定します。

定数の定義は、バージョン情報の次の列に書きます。算術命令やテクスチャアドレッシング命令の前にかかなくてはいけません。

def c0, 1, 1, 1, 1

のように使います。

定数レジスタは、バージョン1_X ではIDirect3DDevice9::SetPixelShaderConstant、バージョン2_0以降のときにはIDirect3DDevice9::SetPixelShaderConstantFでも定義することができます。ただし、def命令がシェーダプログラム内にあるときは、def命令の定数値で上書きされてしまいます。プログラム内で、同じ定数に何度も定数を定義したときには、最後の命令の設定が有効になります。

 

      defb (整数型定数の定義: 2_x, 3_0)

ピクセルシェーダ内で使用する整数型定数レジスタを指定します。

defb b0, True

のように使います。

定数レジスタは、IDirect3DDevice9::SetPixelShaderConstantB (レジスタ番号, 浮動小数点数配列へのポインタ, レジスタ数)でも定義することができます。ただし、defb命令の方が優先されます。

 

      defi (ブール型定数の定義: 2_x, 3_0)

ピクセルシェーダ内で使用するブール型定数レジスタを指定します。

defi i0, 1, 1, 1, 1

のように使います。

定数レジスタは、IDirect3DDevice9::SetPixelShaderConstantIでも定義することができます。ただし、defb命令の方が優先されます。

 

      dcl (定数の宣言と初期化: 2_0, 2_x, 3_0)

頂点色レジスタやテクスチャレジスタの宣言をします。宣言をしないと、これらのレジスタは使えません。

宣言は、それぞれのレジスタに関して一度だけできます。

dcl    v#[.mask] 頂点色の宣言

dcl[_pp] t#[.mask] テクスチャ座標の宣言

ここで、[]で囲まれた_ppと、.maskはオプション的な指定で、必要なときにつけます。それぞれの意味は、

_pp:部分精度。高速化のために16ビットの精度で読み込む。

.mask:書き込みマスク。レジスタに使う成分だけを読み込む。省略された時は4成分読み込む。

テクスチャレジスタでは、「.r」、「.rg」、「.rgb」、「.rgba」のマスクが使えます。頂点色に関しては、このような制限は無く、自由に使う色の成分を指定することができます。

バージョン3_0では、

dcl_normal      v0.xyz

のように、使い道を明示的に示す必要があります。

 

      dcl_textureType (サンプリングステージレジスタの宣言: 2_0, 2_x, 3_0)

サンプリングステージの宣言をします。サンプリングステージレジスタの宣言では、使用するテクスチャの種類を宣言します。

dcl_種類    s#

種類には、次のものがあります。

dcl_2d     :2次元のテクスチャ

dcl_cube   :キューブマップ

dcl_volume :ボリュームテクスチャ

書き込みマスクはありません。

 

      phase (シェーダを区切る: 1_4)

phaseは、シェーダプログラムを区切ります。Phase命令が置かれる前の部分をフェーズ1、後の部分をフェーズ2といいます。phase命令がないシェーダプログラムは、フェーズしかないプログラムと考えられます。この命令を追加したことによって、バージョン1_4は、シェーダあたりの最大命令数を増加することができました。

phaseを使ったプログラムは次の形式をしています。

ps 1.4

// フェーズ1の命令

phase

// フェーズ2の命令

どうしてこの命令が必要なのかというと、テクスチャの読み込みはプログラムの先頭で行なうので、計算結果を使ってテクスチャを読み込むときができないからです。フェーズ1でテクスチャ座標を計算して、フェーズ2でテクスチャを読み込む使い方をします。

 

b-3-2算術命令 (Arithmatic Instructions)

 

      nop (何もしない:1_X, 2_0, 2_x, 3_0)

この命令は何もしません。バージョン1_Xではスロット数に含まれませんが、バージョン2_0以降では、スロット数を1消費します。

nop

のように使います。

 

      mov (値をコピーする:1_1, 1_2, 1_3, 2_0, 2_x, 3_0)

この命令は、あるレジスタの値を別のレジスタにコピーします。例えば、次のように定数をそのまま出力する時に使います。

mov oC0, c0     // 定数レジスタc0の値を出力レジスタであるoC0に出力する

それぞれの成分に関して、振る舞いを擬似コードとして書けば、

oC0.r = c0.r

oC0.g = c0.g

oC0.b = c0.b

oC0.a = c0.a

のように別々に代入されます。

 

      add (足し算:1_X, 2_0, 2_x, 3_0)

2つのレジスタの値を足して、結果レジスタに出力します。

add oC0, v0, t0     // 頂点色v0とテクスチャの色t0を足してoC0に出力する

それぞれの成分については、

oC0.r = v0.r + t0.r

oC0.g = v0.g + t0.g

oC0.b = v0.b + t0.b

oC0.a = v0.a + t0.a

のように成分別に足し算が行われます。

 

      sub (引き算:1_X, 2_0, 2_x, 3_0)

2つのレジスタの値を引いて、結果レジスタに出力します。

sub oC0, v0, t0     // 頂点色v0とテクスチャの色t0を引いてoC0に出力する

で、代用できます。

中身の計算は、

oC0.r = v0.r - t0.r

oC0.g = v0.g - t0.g

oC0.b = v0.b - t0.b

oC0.a = v0.a - t0.a

が行われます。

 

      mul (掛け算:1_X, 2_0, 2_x, 3_0)

2つのレジスタの値を掛けて、結果レジスタに出力します。

mul oC0, v0, t0     // 頂点色v0とテクスチャの色t0を掛けてoC0に出力する

それぞれの成分については、

oC0.r = v0.r * t0.r

oC0.g = v0.g * t0.g

oC0.b = v0.b * t0.b

oC0.a = v0.a * t0.a

のように成分別に掛け算が行われます。

 

      mad (積和計算:1_X, 2_0, 2_x, 3_0)

2つのレジスタの値を掛けた後に別のレジスタの値を足して、結果レジスタに出力します。

mad oC0, c0, t0, v0     // 頂点色v0とテクスチャの色t0を掛けてoC0に出力する

やっている計算は、

mul t0, c0, t0

add oC0, t0, v0

と同じです。論理的にはmul命令とadd命令があれば計算できるのですが、実装が簡単なので、ついでに付けられています(というか、mad命令が1つ合って、mulとaddはその特別な場合として回路は組まれていたりします)。また、スロット数が少ないので、mad命令を使うほうがmul命令とadd命令を組み合わせるより2倍の速さで動くことになります。

それぞれの成分については、

oC0.r = c0.r * t0.r + v0.r

oC0.g = c0.g * t0.g + v0.g

oC0.b = c0.b * t0.b + v0.b

oC0.a = c0.a * t0.a + v0.a

のように成分別に計算が行われます。

 

      bem (擬似バンプ環境マップ変換:1_4)

テクスチャステージステートの値D3DTSS_BUMPENVMAT00〜D3DTSS_BUMPENVMAT11を使って、2次元の行列計算をします。擬似バンプ環境マップを実装するために用意されました。この命令は2命令スロット使います。命令の結果は、

t0.r = r0.r + D3DTSS_BUMPENVMAT00 * c0.r + D3DTSS_BUMPENVMAT01 * c0.g

t0.g = r0.g + D3DTSS_BUMPENVMAT10 * c0.r + D3DTSS_BUMPENVMAT11 * c0.g

のように、2次元の行列計算が行われます。例えば、

ps.1.4

 

texld r1, t1      // バンプマップをテクスチャ座標t1で読み込む

texcld r2.rgb, t2 // テクスチャ座標t2をテクスチャ座標としてr2に代入する

bem r2.rg, r2, r1 // r2=r2+ D3DTSS_BUMPENVMAT*r1の摂動計算をする

 

phase             // フェーズの切り替え

 

texld r0, t0      // デカールのテクスチャを読み込む

texld r2, r2      // bem命令の後のずれたテクスチャ座標で環境マップを読み込む

add r0, r0, r2    // 加算して環境マップを貼り付ける

のように使います。

brm命令は、最初のフェーズで使わなくてはなりません。また、1回しか使えません。書き込みマスクは.rg(.xy)にする必要があります。

D3DTSS_BUMPENVMAT00は、テクスチャステージステートなので、IDirect3DDevice9::SetTextureStageState(ステージ番号, D3DTSS_BUMPENVMAT**, 値)で設定します。つまり、ステージ番号を指定する必要があります。設定するステージ番号は、結果レジスタの番号(今回の例ではr2.rgの「2」)に設定します。

 

      dp2add (加算付き2要素ベクトルの内積: 2_0, 2_x, 3_0)

この命令はbem命令を一般化したものです。

dp2add[_sat], 結果レジスタ[.書き込みマスク], 引数レジスタ0[.成分入れ替え]

                                           , 引数レジスタ1[.成分入れ替え]

                                           , 引数レジスタ2[.1つの成分]

やっている計算は、

結果レジスタ[.書き込みマスク] =  引数レジスタ0.r * 引数レジスタ1.r

                               + 引数レジスタ0.g * 引数レジスタ1.g

                               + 引数レジスタ2.成分

になります。_sat修飾子をつけると、計算結果を0から1の範囲に制限して出力します。

 

      dp3 (3要素ベクトルの内積:1_X, 2_0, 2_x, 3_0)

レジスタの色成分を3次元ベクトルとみなして、内積の計算をします。

dp3 r0, c0, v0

この命令では、計算結果を全ての成分に出力します。

r0.w = c0.x * v0.x + c0.y * v0.y + c0.z * v0.z

r0.x = r0.y = r0.z =使われない

したがって、書き込みたくない成分があるときは、書き込みマスクを使って書き込まないようにする必要があります。

dp3命令は、ピクセルシェーダのベクトルパイプラインで計算されるので、dp3命令をα成分だけに出力する場合でも、色成分での並列な計算はできません。

add r0.rgb, c0, v0    両方ともベクトルパイプラインを使うので、この計算は同時にはできない

+dp3 r0.a, c0, v0

 

      dp4 (4要素ベクトルの内積: 1_2, 1_3, 1_4, 2_0, 2_x, 3_0)

レジスタの色成分を4次元ベクトルとみなして、内積の計算をします。

dp4 r0, c0, v0

この命令では、計算結果を全ての成分に出力します。

r0.x = r0.y = r0.z = r0.w = c0.x * v0.x + c0.y * v0.y + c0.z * v0.z + c0.w * v0.w

したがって、書き込みたくない成分があるときは、書き込みマスクを使って書き込まないようにする必要があります。dp4命令では、ベクトルパイプラインとαパイプラインの両方のパイプラインを使うので、他の命令を同時に実行することはできません。

シェーダ1.2及び1.3では、命令に関してスロットを2つ消費したり、最大4つのdp4命令しか使えないなどの制限があります。

 

      dsx (x 方向の変化割合: 2_x, 3_0)

入力されるあるレジスタに関して、横隣にあるピクセルではどのくらい値が変わっているのか調べます。異方性フィルタをシェーダでプログラムするときなどに使えます。

dsx 結果レジスタ, 引数レジスタ

 

      dsy (y 方向の変化割合: 2_x, 3_0)

入力されるあるレジスタに関して、下隣にあるピクセルではどのくらい値が変わっているのか調べます。

dsy 結果レジスタ, 引数レジスタ

 

      cmp (正値の判定: 1_2, 1_3, 1_4, 2_0, 2_x, 3_0)

引数レジスタ0の値が0以上か未満かによって、結果レジスタに引数レジスタ1、引数レジスタ2の内容を代入します。

cmp 結果レジスタ, 引数レジスタ0, 引数レジスタ1, 引数レジスタ2

この判定は、成分ごとに行われます。

結果レジスタ.r = (0.0 <= 引数レジスタ0.r) ? 引数レジスタ1.r : 引数レジスタ2.r

結果レジスタ.g = (0.0 <= 引数レジスタ0.g) ? 引数レジスタ1.g : 引数レジスタ2.g

結果レジスタ.b = (0.0 <= 引数レジスタ0.b) ? 引数レジスタ1.b : 引数レジスタ2.b

結果レジスタ.a = (0.0 <= 引数レジスタ0.a) ? 引数レジスタ1.a : 引数レジスタ2.a

シェーダ1.2、1.3では、幾つかの制限があります。

・スロットを2つ消費する。

・最大4つのcmp命令しか使えない。

・結果レジスタには、引数レジスタのどれとも同じ物は使えない。

 

      cnd (0.5以下の値の判定:1_X)

引数レジスタ0の値が0.5超過か以下かによって、結果レジスタに引数レジスタ1、引数レジスタ2の内容を代入します。

cnd 結果レジスタ, 引数レジスタ0, 引数レジスタ1, 引数レジスタ2

この命令は、バージョンが1_3までか、1_4かで振る舞いが違います。

バージョン1.3まででは、アルファ成分を見て、結果を判定します。

結果レジスタ.r = (0.5 < 引数レジスタ0.a) ? 引数レジスタ1.r : 引数レジスタ2.r

結果レジスタ.g = (0.5 < 引数レジスタ0.a) ? 引数レジスタ1.g : 引数レジスタ2.g

結果レジスタ.b = (0.5 < 引数レジスタ0.a) ? 引数レジスタ1.b : 引数レジスタ2.b

結果レジスタ.a = (0.5 < 引数レジスタ0.a) ? 引数レジスタ1.a : 引数レジスタ2.a

バージョン1.4以降では、成分ごとに判定します。

結果レジスタ.r = (0.5 < 引数レジスタ0.r) ? 引数レジスタ1.r : 引数レジスタ2.r

結果レジスタ.g = (0.5 < 引数レジスタ0.g) ? 引数レジスタ1.g : 引数レジスタ2.g

結果レジスタ.b = (0.5 < 引数レジスタ0.b) ? 引数レジスタ1.b : 引数レジスタ2.b

結果レジスタ.a = (0.5 < 引数レジスタ0.a) ? 引数レジスタ1.a : 引数レジスタ2.a

 

      rcp (逆数: 2_0, 2_x, 3_0)

引数の逆数を計算します。引数のレジスタには、どれか1つの成分を指定します。

rcp r0, c0.w

引数レジスタの値が1.0の時は、結果は1.0になります。引数レジスタの値が0.0の時は、正の無限大の値が返ってきます。

r0.x = r0.y = r0.z = r0.w = 1.0f        : c0.w = 1.0f の時

                            正の無限大  : c0.w = 0.0f の時

                            1.0f / c0.w : それ以外

 

      rsq (逆数平方根: 2_0, 2_x, 3_0)

引数の値に関して、逆数の平方根を計算します。引数のレジスタには、どれか1つの成分を指定します。

rsq r0, c0.w

引数レジスタの値が1.0の時は、結果は1.0になります。引数レジスタの値が0.0の時は、正の無限大の値が返ってきます。

r0.x = r0.y = r0.z = r0.w = 1.0f            : c0.w = 1.0f の時

                            正の無限大      : c0.w = 0.0f の時

                            1.0f / √|c0.w| : それ以外

より正確には、引数レジスタの値の絶対値の逆数を計算します。

 

b-3-3マクロ命令 (Macro-ops)

 

      lrp (線形補間:1_X, 2_0, 2_x, 3_0)

2つめのレジスタの値を係数にして、線形にレジスタの値を合成します。この命令はバージョン1_Xでは、1スロット、それ以上では2命令スロットを消費します。

lrp, r0, c0, t0, v0

この命令の結果は、

r0.x = c0.x * t0.x + (1-c0.x) * v0.x

r0.y= c0.y * t0.y + (1-c0.y) * v0.y

r0.z = c0.z * t0.z + (1-c0.z) * v0.z

r0.w = c0.w * t0.w + (1-c0.w) * v0.w

になります。

 

      abs (絶対値:2_0, 2_x, 3_0)

それぞれの成分の絶対値を計算します。この命令は1命令スロットを消費します。

abs r0, v0

この命令の結果は、

r0.x = (0<v0.x) ? v0.x : -v0.x

r0.y = (0<v0.y) ? v0.y : -v0.y

r0.z = (0<v0.z) ? v0.z : -v0.z

r0.xw= (0<v0.w) ? v0.w : -v0.w

になります

 

      crs (外積:2_0, 2_x, 3_0)

外積を計算します。この命令は2命令スロットを消費します。

crs r0, v0, t0

この命令の結果は、

r0.x = v0.y * t0.z – v0.z * t0.y

r0.y = v0.z * t0.x – v0.x * t0.z

r0.z = v0.x * t0.y – v0.y * t0.x

になります。

書き込みマスクには、.x、.y、.z、.xy、.xz、.yz、.xyzを指定しなくてはなりません。引数と結果のレジスタは全て別のレジスタにしないといけません。結果を格納するレジスタは一時レジスタr#でなくてはいけません(つまり、出力レジスタを指定してはいけないということです)。

 

      m3x2 (3 × 2 ベクトル行列の乗算:2_0, 2_x, 3_0)

2行3列の行列と、3次元ベクトルの計算をします。この命令は2命令スロットを消費します。

m3x2 r0, v0, c0

書き込みマスクにr, gの成分を指定する必要があります。この命令は、

dp3 r0.r, v0, c0

dp3 r0.g, v0, c1

を1つの命令にでしたもので、結果は

r0.r = v0.r * c0.r + v0.g * c0.g + v0.b * c0.b

r0.g = v0.r * c1.r + v0.g * c1.g + v0.b * c1.b

になります

行列を示す最後のレジスタには、成分入れ替えや符号の入れ替えの修飾子は使えません。また、最後のレジスタは、それ以外の結果レジスタや引数レジスタを指定することができません。

 

      m3x3 (3 × 3 ベクトル行列の乗算:2_0, 2_x, 3_0)

3行3列の行列と、3次元ベクトルの計算をします。この命令は3命令スロットを消費します。

m3x3 r0, v0, c0

書き込みマスクにr, g, bの成分を指定する必要があります。この命令は、

dp3 r0.r, v0, c0

dp3 r0.g, v0, c1

dp3 r0.b, v0, c2

を1つの命令にでしたもので、結果は

r0.r = v0.r * c0.r + v0.g * c0.g + v0.b * c0.b

r0.g = v0.r * c1.r + v0.g * c1.g + v0.b * c1.b

r0.b = v0.r * c2.r + v0.g * c2.g + v0.b * c2.b

になります

行列を示す最後のレジスタには、成分入れ替えや符号の入れ替えの修飾子は使えません。また、最後のレジスタは、それ以外の結果レジスタや引数レジスタを指定することができません。

 

      m3x4 (3 × 4 ベクトル行列の乗算:2_0, 2_x, 3_0)

4行3列の行列と、3次元ベクトルの計算をします。この命令は4命令スロットを消費します。

m3x4 r0, v0, c0

書き込みマスクにr, g, b, aの成分を指定する必要があります。この命令は、

dp3 r0.r, v0, c0

dp3 r0.g, v0, c1

dp3 r0.b, v0, c2

dp3 r0.b, v0, c3

を1つの命令にでしたもので、結果は

r0.r = v0.r * c0.r + v0.g * c0.g + v0.b * c0.b

r0.g = v0.r * c1.r + v0.g * c1.g + v0.b * c1.b

r0.b = v0.r * c2.r + v0.g * c2.g + v0.b * c2.b

r0.a = v0.r * c3.r + v0.g * c3.g + v0.b * c3.b

になります

行列を示す最後のレジスタには、成分入れ替えや符号の入れ替えの修飾子は使えません。また、最後のレジスタは、それ以外の結果レジスタや引数レジスタを指定することができません。

 

      m4x3 (4 × 3 ベクトル行列の乗算:2_0, 2_x, 3_0)

3行4列の行列と、4次元ベクトルの計算をします。この命令は3命令スロットを消費します。

m4x2 r0, v0, c0

書き込みマスクにr, g, bの成分を指定する必要があります。この命令は、

dp4 r0.r, v0, c0

dp4 r0.g, v0, c1

dp4 r0.b, v0, c2

を1つの命令にでしたもので、結果は

r0.r = v0.r * c0.r + v0.g * c0.g + v0.b * c0.b + v0.a * c0.a

r0.g = v0.r * c1.r + v0.g * c1.g + v0.b * c1.b + v0.a * c1.a

r0.b = v0.r * c2.r + v0.g * c2.g + v0.b * c2.b + v0.a * c2.a

になります

行列を示す最後のレジスタには、成分入れ替えや符号の入れ替えの修飾子は使えません。また、最後のレジスタは、それ以外の結果レジスタや引数レジスタを指定することができません。

 

      m4x4 (4 × 4 ベクトル行列の乗算:2_0, 2_x, 3_0)

4行4列の行列と、4次元ベクトルの計算をします。この命令は4命令スロットを消費します。

m4x4 r0, v0, c0

書き込みマスクにr, g, b, aの成分を指定する必要があります。この命令は、

dp4 r0.r, v0, c0

dp4 r0.g, v0, c1

dp4 r0.b, v0, c2

dp4 r0.b, v0, c3

を1つの命令にでしたもので、結果は

r0.r = v0.r * c0.r + v0.g * c0.g + v0.b * c0.b + v0.a * c0.a

r0.g = v0.r * c1.r + v0.g * c1.g + v0.b * c1.b + v0.a * c1.a

r0.b = v0.r * c2.r + v0.g * c2.g + v0.b * c2.b + v0.a * c2.a

r0.a = v0.r * c3.r + v0.g * c3.g + v0.b * c3.b + v0.a * c3.a

になります

行列を示す最後のレジスタには、成分入れ替えや符号の入れ替えの修飾子は使えません。また、最後のレジスタは、それ以外の結果レジスタや引数レジスタを指定することができません。

 

      max (最大値:2_0, 2_x, 3_0)

2つのレジスタの値を比較して、大きいほうの値を結果レジスタに出力します。この命令は1命令スロットを消費します。

max r0, c0, t0

2つのレジスタの比較はそれぞれの成分に関して行われます。

r0.r = (c0.r < t0.r) ? t0.r : c0.r

r0.g = (c0.g < t0.g) ? t0.g : c0.g

r0.b = (c0.b < t0.b) ? t0.b : c0.b

r0.a = (c0.a < t0.a) ? t0.a : c0.a

 

      min (最小値:2_0, 2_x, 3_0)

2つのレジスタの値を比較して、小さいほうの値を結果レジスタに出力します。この命令は1命令スロットを消費します。

min r0, c0, t0

2つのレジスタの比較はそれぞれの成分に関して行われます。

r0.r = (c0.r < t0.r) ? c0.r : t0.r

r0.g = (c0.g < t0.g) ? c0.g : t0.g

r0.b = (c0.b < t0.b) ? c0.b : t0.b

r0.a = (c0.a < t0.a) ? c0.a : t0.a

 

      frc (小数部:2_0, 2_x, 3_0)

引数レジスタの小数部を計算します。結果は必ず0.0から1.0の間に収まります。この命令は1命令スロットを消費します。

 

frc r0, c0

 

      exp (2を底とする指数: 2_0, 2_x, 3_0)

2のべき乗の計算をします。この命令は1命令スロットを消費します。

exp r0, c0.a

どの成分を使うのか、引数レジスタに指定しなくてはなりません。

r0.x = r0.y = r0.z = r0.w = 2 c0.a

 

      log (2を底とする対数: 2_0, 2_x, 3_0)

2を底とする対数の計算をします。どの成分を使うのか、引数レジスタに指定しなくてはなりません。この命令は1命令スロットを消費します。

log r0, c0.a

より正確には、引数レジスタの値の絶対値の対数を計算します。

r0.x = r0.y = r0.z = r0.w = log(|c0.a|)/log(2)

引数レジスタの値が0の時は、結果レジスタに負の無限大の値が入ってきます。

 

      nrm (正規化:2_0, 2_x, 3_0)

レジスタの色成分を3次元のベクトルと見なして、ベクトルを正規化します。入力レジスタは結果のレジスタと違うものでなければなりません。この命令は3命令スロットを消費します。

nrm r0, v0

nrm命令が無い時は、キューブマップを使ってベクトルを規格化していましたが、この命令のおかげで、鏡面反射のフォンシェーディングが簡単になりました。

 

      pow (べき乗:2_0, 2_x, 3_0)

完全精度の指数計算をします。この命令は3命令スロットを消費します。

pow r0, v0.a, c0.a

それぞれの引数レジスタに、どの成分を使うのか、明示的に指定しなくてはなりません。また、結果レジスタと指数を代入するレジスタは同じレジスタに出来ません。

r0.r = r0. g = r0. b = r0.a = |v0.a| c0.a

計算結果はすべての結果レジスタに入れられますので、不必要な部分には書き込みマスクをしてください。

 

      sincos (サイン、コサイン:2_0, 2_x, 3_0)

サインとコサインを計算します。この命令は8命令スロットを消費します。

sincos r1, r0.w, c0, c1

角度を示す引数レジスタr0.wの値は、−π≦r0.w≦πの範囲に抑える必要があります。

引数レジスタのc0とc1には次のマクロで定義されている定数を入力しておく必要があります。

#define D3DSINCOSCONST1 -1.5500992e-006f, -2.1701389e-005f,  0.0026041667f, 0.00026041668f

#define D3DSINCOSCONST2 -0.020833334f, -0.12500000f, 1.0f, 0.50000000f

具体的には、

float sincos_const[][4] = {

   { D3DSINCOSCONST1 },

   { D3DSINCOSCONST2 },

};

IDirect3DDevice9::SetPixelShaderConstant ( 0, &sincos_const[0][0], 2);

の方法で、定数を代入します。ただし、バージョン3_0では、これらの定数は勝手に設定されるので、自分で指定しなくてもかまいません。

計算した結果は、x成分にコサイン、y成分にサインが入ります。

  r1.x = cos(r0.w)

  r1.y = sin(r0.w)

 

b-3-4テクスチャアドレッシング命令 (Texture Address Instructions)

 

      texld (変更なし:1_4, 2_0, 2_x, 3_0)

この命令は、テクスチャ座標からテクスチャを読み込みます。この命令は1(キューブマップでは4)テクスチャ命令スロットを消費します。例えば、次のように使います。

texld r0, t0, s0  ; サンプラs0からテクスチャ座標t0でr0にテクスチャを読み込む

出力レジスタは一時レジスタr#が使えます。書き込みマスクはrgbaの4成分を指定する必要があります。_sat修飾子は使えません。出力レジスタに関する部分精度の修飾子_ppをつけることもできます。

サンプリングステージレジスタs#は、成分の入れ替えや値を負にすることはできません。サンプリングステージレジスタs#の宣言時のフォーマットで、テクスチャ座標の次元が決定します。

テクスチャ座標には、テクスチャ座標レジスタt#か一時レジスタr#が使えます。成分の入れ替えや符号反転の修飾子を使うことはできません。

RGBテクスチャを読み込むときは、読みこまれた値は-1.0〜1.0の範囲で返ってきます。浮動小数点テクスチャをサンプリングする場合、読み込むレジスタのビット数での最大範囲の値が許されます。例えば、16ビット浮動小数点数をサポートする場合は、D3DX_16F_MAX(=6.5519996e+4f)の範囲まで読み込むことができます。

texld命令などで読み込んだテクスチャの値をふたたびテクスチャ座標として使って再度テクスチャを読み込むことを順序従属テクスチャといいます。順序従属テクスチャは3段階まで可能です。ただし、D3DPS20CAPS_NODEPENDENTREADLIMITがたっている場合には、順序従属テクスチャの制限はありません。ピクセルシェーダ2_0では、一時レジスタの数が少ないので、レジスタを使いまわしていると、結構この制限にひっかかります。経験的に、ピクセルシェーダ2_0では、テクスチャを10個以上読み込むシェーダを書くのは大変です。

ピクセルシェーダ1_4では、最初のフェーズで一時レジスタをテクスチャ座標として使えないなどのいくつかの違いがあります。

 

      texldb (LODバイアス:2_0, 2_x, 3_0)

テクスチャ座標のアルファ成分をミップマップのLODレベルに加算します。この命令は1テクスチャ命令スロットを消費します。値の範囲は、ピクセルシェーダ2_Xなら[-3.0, +3.0]、3_0なら[-16.0, +15.0]の範囲になります。サンプリングステージのD3DSAMP_MIPMAPLODBIASも有効で、LODレベルには、texldbによるLODレベルの変更に加えて、D3DSAMP_MIPMAPLODBIASの値を足した値がミップマップレベルとしてテクスチャが読み込まれます。それ以外は、texldと同じです。

 

      texldp (透視変換:2_0, 2_x, 3_0)

テクスチャ座標をw成分で割った値でテクスチャを読み込みます。すなわち、(t0.x/t0.w, t0.y/t0.w, t0.z/t0.w)がテクスチャの読み込みの座標として使われます。この命令は1テクスチャ命令スロットを消費します。それ以外は、texldと同じです。

 

      texldd (ユーザー指定の勾配を使ったテクスチャ サンプリング:2_x, 3_0)

x方向の勾配dsxと、y方向の勾配dsyを使ってテクスチャをサンプリングします。例えば、次のようになります。

texldd t0, s0, r0, r1

ここで、r0やr1が勾配dsx, dsyです。。この命令は3テクスチャ命令スロットを消費します。

 

      texldl (w 要素の LOD を使ったテクスチャ サンプリング: 3_0)

w成分をLODレベルとしてテクスチャを読み込みます。この命令は2(キューブマップでは5)テクスチャ命令スロットを消費します。それ以外は、ほぼtexldと同じです。

 

      texkill (ピクセルのマスクアウト:1_X, 2_0, 2_x, 3_0)

テクスチャ座標のRGBのどれかの成分の値が0未満の時に、このピクセルの描画を取りやめます。この命令は2_0では1テクスチャ命令スロット、2_xでは2テクスチャ命令スロット、3_0では2命令スロットを消費します。

この命令を使えば、クリッピングをピクセルシェーダで行うことができます。texkill命令の使い方は、次のようになります。

texkill t0

 

      texcrd (テクスチャ座標:1_4)

この命令は、テクスチャ座標を色のデータとみなします。使い方は、

texcrd r0, t0

です。ここで、テクスチャ座標の値は、[-D3DCAPS9.MaxTextureRepeat, D3DCAPS9.MaxTextureRepeat]の範囲に抑えられますが、結果を収めるレジスタのほうは、[-D3DCAPS9.PixelShader1xMaxValue, D3DCAPS9.PixelShader1xMaxValue](ピクセルシェーダ1.4では、[-8,8])の範囲に無ければいけないことに気をつけなければなりません。普通は、ピクセルシェーダのレジスタの範囲の方が小さいです。はみ出たときの結果は、グラフィックチップに依存するので、はみ出ないようにプログラムしたほうがよいです。

また、次の命令の場合には、(t0.x/t0.w, t0.y/t0.w)の結果が、r0レジスタの赤、緑成分に入ります。

texcrd r0.rg, t0_dw.xyw

 

      texdepth (深度書き込み:1.4)

深度計算に使う深度値を計算します。次のように使います。

texdepth r5

r5.r/r5.gが深度値に使われます。他の成分は使われません。r5レジスタだけが、入力レジスタとして適切なレジスタです。r5.g=0のときは、結果は1になります。

 

      tex (変更なし:1_1, 1_2, 1_3)

テクスチャ座標レジスタt#の値をテクスチャ座標として、テクスチャデータをサンプリングします。サンプリングしたテクスチャのピクセルの色はt#レジスタに入ります。

tex t0

サンプリングするテクスチャのステージは、何も設定しない状態ではテクスチャ座標レジスタの番号が使われます。この例なら、0番のサンプリングステージからテクスチャを読み込みます。ただし、読み込むサンプリングステージの変更もできます。それは、IDirect3DDevice9::SetTextureStageState のTSS_TEXCOORDINDEX を使うか、固定機能のシェーダを使うことです。

 

      texbem (擬似バンプ環境マップ:1_1, 1_2, 1_3)

テクスチャ座標を2次元の行列で動かしてから、テクスチャをサンプリングします。バンプマップを実現するために用意されました。次の命令が実際のシェーダプログラムです。

ps 1.1

tex t0         // バンプマップを読み込む

texbem t1, t0  // バンプマップの色の強さでテクスチャ座標t1をずらして読み込む

mov r0, t1     // 読み込んだテクスチャを色に出力する

この時、バンプマップで読み込むテクスチャのステージは擬似バンプ環境マップのテクスチャステージよりも小さいものを指定しなくてはなりません。

内部的に行われる計算は、テクスチャサンプリングステートのD3DTSS_BUMPENVMAT00〜D3DTSS_BUMPENVMAT11を使って、2次元の行列計算が行われた後に、テクスチャを読み込みます。

t1.x = t1.x + D3DTSS_BUMPENVMAT00 * t0.r + D3DTSS_BUMPENVMAT01 * t0.g

t1.y = t1.y + D3DTSS_BUMPENVMAT10 * t0.r + D3DTSS_BUMPENVMAT11 * t0.g

t1 = テクスチャ座標(t1.x, t1.y)を使って、テクスチャの読み込み

D3DTSS_BUMPENVMAT00〜D3DTSS_BUMPENVMAT11のサンプリングステージは、texbemのサンプリングステージと同じ番号(この場合は1)に入れてください。

 

      texbeml (輝度補正つき擬似バンプ環境マップ:1_1, 1_2, 1_3)

バンプマップを使って、環境マップをずらして読み込んだ後に、テクスチャに埋め込まれたデータから色を補正します。この命令は、1テクスチャ命令スロットと1算術スロットを消費します。使い方自体は、擬似バンプ環境マップと同じです。

ps 1.1

tex t0         // バンプマップを読み込む

texbeml t1, t0 // バンプマップの色の強さでテクスチャ座標t1をずらして読み込む

mov r0, t1     // 読み込んだテクスチャを色に出力する

texbemlの結果は、テクスチャ座標をずらすのに加えて、さらにD3DTSS_BUMPENVLSCALE、D3DTSS_BUMPENVLOFFSETを使った補正が入ります。

t1.x = t1.x + D3DTSS_BUMPENVMAT00 * t0.r + D3DTSS_BUMPENVMAT01 * t0.g

t1.y = t1.y + D3DTSS_BUMPENVMAT10 * t0.r + D3DTSS_BUMPENVMAT11 * t0.g

t1 = テクスチャ座標(t1.x, t1.y)を使って、テクスチャの読み込み

t1 = t1 * (t0.rb * 3DTSS_BUMPENVLSCALE + D3DTSS_BUMPENVLOFFSET)

D3DTSS_BUMPENVMAT00〜D3DTSS_BUMPENVMAT11及びD3DTSS_BUMPENVLSCALE、D3DTSS_BUMPENVLOFFSETのサンプリングステージは、texbemlのサンプリングステージと同じ番号(この場合は1)に入れてください。

 

      texcoord (テクスチャ座標: 1_1, 1_2, 1_3)

この命令は、テクスチャ座標を色のデータとみなします。使い方は、

texcoord t0

です。値は0から1の間に自動的に抑えられます。頂点シェーダプログラムで値を入れていないテクスチャ座標の成分は、0が入ります。ただし、α成分には常に1が入ります。この命令は、テクスチャを設定する必要がないので、テクスチャを読み込まない分、高速にレンダリングします。

 

      texdp3 (3次元内積:1_2, 1_3)

テクスチャの値と、テクスチャ座標の3次元内積を計算して、出力レジスタのすべての成分に代入します。例えば、次のように使います。

tex t0              ; 3次元ベクトルとしてt0にテクスチャをサンプリングする

texdp3   t1, t0     ; t1.rgba = t1.r * t0.r + t1.g * t0.g + t1.b * t0.b

だし

 

      texdp3tex (3次元内積読み込み:1_2, 1_3)

テクスチャの値と、テクスチャ座標の3次元内積を計算して、計算結果とテクスチャ座標として、1次元テクスチャからデータを読み込みます。例えば、次のように使います。

tex t0              ; 3次元ベクトルとしてt0にテクスチャをサンプリングする

texdp3tex   t1, t0  ; u = t1.r * t0.r + t1.g * t0.g + t1.b * t0.b

                    ; (u)をテクスチャ座標として、テクスチャの読み込み

 

      texm3x2depth (3次元内積深度書き込み:1_3)

深度計算に使う深度値を計算します。例えば、次のように使います。

tex t0              ; 3次元ベクトルとしてt0にテクスチャをサンプリングする

texm3x2pad   t1, t0 ; z = t1.r * t0.r + t1.g * t0.g + t1.b * t0.b

texm3x2depth t2, t0 ; w = t2.r * t0.r + t2.g * t0.g + t2.b * t0.b

                    ; z/wが深度値として、t2に代入されます。

ただし、w=0になったときは、深度の値は、1.0になります。また、計算結果は、その後のシェーダ命令では使うことはできません。

計算結果は、必ず0から1の範囲に収めなければなりません。はみ出したときの結果はどうなるかわかりません。

 

      texm3x2pad (3 × 2 行列乗算への入力: 1_1, 1_2, 1_3)

texm3x2texやtexm3x2depthの、他のテクスチャアドレッシングと組み合わせて、2×3の行列演算をします。例えば、次のように使います。

tex t0            ; 3次元ベクトルとしてt0にテクスチャをサンプリングする

texm3x2pad t1, t0 ; u = t1.r * t0.r + t1.g * t0.g + t1.b * t0.b

texm3x2tex t2, t0 ; v = t2.r * t0.r + t2.g * t0.g + t2.b * t0.b

                  ; (u,v) をテクスチャ座標としてサンプリングステージ2から

; テクスチャを読みとる

この命令自体では、テクスチャのサンプリングを行いません。テクスチャを設定しても無視されます。

 

      texm3x2tex (3 × 2 行列乗算の結果:1_1, 1_2, 1_3)

texm3x2padと組み合わせて使用して、2×3の行列演算をします。例えば、サンプリングステージ0に法線マップ、サンプリングステージ2に横軸が(L・N)、縦軸が(H・N)の関数にしたライトの強さをテクスチャに埋めこんだテクスチャを用意しておきます。ここで、Lはライトの方向、Hは視線とライトの方向のハーフベクトルです。この時、

tex t0                ; 3次元ベクトルとしてt0に法線マップを読み取る

texm3x2pad t1, t0_bx2 ; u = t1.r * (2*t0.r-1) + t1.g * (2*t0.g-1) + t1.b * (2*t0.b-1)

texm3x2tex t2, t0_bx2 ; v = t2.r * (2*t0.r-1) + t2.g * (2*t0.g-1) + t2.b * (2*t0.b-1)

                      ; (u,v) をテクスチャ座標としてサンプリングステージ2から

; テクスチャを読みとる

のシェーダプログラムを組んでおき、t1にライトの方向ベクトル、t2半ベクトルを入れておけば、法線バンプマッピングができます。

 

      texm3x3 (3 × 3 行列乗算:1_2, 1_3)

この命令は、texm3x3padと組み合わせて、3×3の行列演算をします。この命令は、texm3x3texと違って、テクスチャの読み込みをしません。例えば、次のように使います。

tex t0            ; 3次元ベクトルとしてt0にテクスチャをサンプリングする

texm3x3pad t1, t0 ; s = t1.r * t0.r + t1.g * t0.g + t1.b * t0.b

texm3x3pad t2, t0 ; t = t2.r * t0.r + t2.g * t0.g + t2.b * t0.b

texm3x2tex t3, t0 ; r = t3.r * t0.r + t3.g * t0.g + t3.b * t0.b

                  ; (s,t,r,1) がt2レジスタに出力される。

texm3x3は行列命令の最後のキーワードとして使われます。

 

      texm3x3pad (3 × 3 行列乗算への入力: 1_1, 1_2, 1_3)

texm3x3texやtexm3x3spec、texm3x3vspec等の、他のテクスチャアドレッシングと組み合わせて、3×3の行列演算をします。例えば、次のように使います。

tex t0            ; 3次元ベクトルとしてt0にテクスチャをサンプリングする

texm3x3pad t1, t0 ; s = t1.r * t0.r + t1.g * t0.g + t1.b * t0.b

texm3x3pad t2, t0 ; t = t2.r * t0.r + t2.g * t0.g + t2.b * t0.b

texm3x2tex t3, t0 ; r = t3.r * t0.r + t3.g * t0.g + t3.b * t0.b

                  ; (s,t,r) をテクスチャ座標としてサンプリングステージ3から

; (キューブもしくはボリューム)テクスチャを読みとる

この命令自体では、テクスチャのサンプリングを行いません。テクスチャを設定しても無視されます。

 

      texm3x3spec (鏡面反射と環境マップ:1_1, 1_2, 1_3)

この処理は、結果として生成される行列計算後のベクトルを取得し、反射ベクトル

を内部で自動的に計算します。視線ベクトルeは、定数レジスタc0 が用いられます。その後、反射ベクトルの結果を、そのステージで設定されているキューブ テクスチャを参照するためのアドレスとして使用します。

tex t0                  ; 3次元ベクトルとしてt0にテクスチャをサンプリングする

texm3x3pad t1, t0       ; s = t1.r * t0.r + t1.g * t0.g + t1.b * t0.b

texm3x3pad t2, t0       ; t = t2.r * t0.r + t2.g * t0.g + t2.b * t0.b

texm3x3spec t3, t0, c0  ; r = t3.r * t0.r + t3.g * t0.g + t3.b * t0.b

                        ; 反射計算を行い、テクスチャ 3 をサンプルする

mov r0, t3              ; 最終結果を出力色としてコピー

バンプ (通常の) マップはステージ 0 で設定される必要があり、キューブ テクスチャはステージ 3 で設定される必要があります。ステージ 1 または 2 で設定されるテクスチャはいずれも無視されます。

設定 0 のテクスチャ座標はバンプ マップに位置する。1、2、および 3 を設定するテクスチャ座標は 3 × 3 行列の行になります。

 

      texm3x3tex (3 × 3 行列乗算の結果:1_1, 1_2, 1_3)

この命令は、texm3x3padと組み合わせて、3×3の行列演算をします。例えば、次のように使います。

tex t0            ; 3次元ベクトルとしてt0にテクスチャをサンプリングする

texm3x3pad t1, t0 ; s = t1.r * t0.r + t1.g * t0.g + t1.b * t0.b

texm3x3pad t2, t0 ; t = t2.r * t0.r + t2.g * t0.g + t2.b * t0.b

texm3x2tex t3, t0 ; r = t3.r * t0.r + t3.g * t0.g + t3.b * t0.b

                  ; (s,t,r) をテクスチャ座標としてサンプリングステージ3から

; (キューブもしくはボリューム)テクスチャを読みとる

texm3x3texは行列命令の最後のキーワードとして使われます。

 

      texm3x3vspec (固定視点ベクトルを含まない鏡面反射/環境マップ: 1_1, 1_2, 1_3)

視点ベクトルが固定していないときのスペキュラ反射および環境マッピングを行います。この命令は、行列の行として使われる 3 つのテクスチャ座標の w 要素から視線が取得される点を除き、この命令の動作は texm3x3spec とまったく同じです。使い方は、

tex t0                  ; 3次元ベクトルとしてt0にテクスチャをサンプリングする

texm3x3pad t1, t0       ; s = t1.r * t0.r + t1.g * t0.g + t1.b * t0.b

texm3x3pad t2, t0       ; t = t2.r * t0.r + t2.g * t0.g + t2.b * t0.b

texm3x3vspec t3, t0     ; r = t3.r * t0.r + t3.g * t0.g + t3.b * t0.b

                        ; 反射計算を行い、テクスチャ 3 をサンプルする

mov r0, t3              ; 最終結果を出力色としてコピー

になります。

 

      texreq2ar (アルファ成分および赤成分の再マッピング:1_1, 1_2, 1_3)

指定された入力色ベクトルのアルファ成分と赤成分で指定される 2D 座標で、このステージのテクスチャをサンプリングします。例えば、次のように使います。

tex t0               ; 2次元ベクトルとしてt0にテクスチャをサンプリングする

texreq2ar t1, t0       ; (t0.a, t0.r)をテクスチャ座標として、

; t1レジスタにテクスチャのデータをサンプリングする

texreg2ar と texreg2gb 命令では、_bx2 修飾子を使うことができません。

 

      texreq2gb (緑成分および青成分の再マッピング: 1_1, 1_2, 1_3)

指定された入力色ベクトルの緑成分と青成分で指定される 2D 座標で、このステージのテクスチャをサンプリングします。例えば、次のように使います。

tex t0               ; 2次元ベクトルとしてt0にテクスチャをサンプリングする

texreq2gb t1, t0       ; (t0.g, t0.b)をテクスチャ座標として、

; t1レジスタにテクスチャのデータをサンプリングする

texreg2ar と texreg2gb 命令では、_bx2 修飾子を使うことができません。

 

      texreq2rgb (色成分の再マッピング: 1_2, 1_3)

指定された入力色ベクトルの色成分で指定される 3次元座標で、このステージのテクスチャをサンプリングします。例えば、次のように使います。

tex t0                ; 2次元ベクトルとしてt0にテクスチャをサンプリングする

texreq2rgb t1, t0       ; (t0.g, t0.b)をテクスチャ座標として、

; t1レジスタにテクスチャのデータをサンプリングする

読み込むテクスチャには、キューブマップもしくは、ボリュームテクスチャを使います。

 

 

b-3-5フロー制御

条件分岐による制御を行います。ピクセルシェーダ2_xから使えるようになりました。ただし、2_xでは、サブルーチン呼び出しの再帰呼び出しが出来ないなどの制限があります。

 

      ifelseendif (分岐: 2_x, 3_0)

 

分岐レジスタの値に応じて、2つの処理を切り替えます。if命令は3スロット、elseは1スロット、endif命令は1スロット消費します。

if b0

なんかの処理

else

べつの処理

endif

b0が1(TRUE)の時は、if〜elseの間にある命令が実行されます。b0が0(FALSE)の時は、else〜endifの間の命令が実行されます。if ブロックはネストすることができますが、loop ブロックをまたぐことはできません。

 

      if_comp (比較に伴う分岐: 2_x, 3_0)

 

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 (プレディケーションに基く分岐条件: 2_x, 3_0)

 

レディケーション レジスタの内容に基づいて命令を使い分けます。if pred命令は3スロット消費します。

if p0.適当な成分

なんかの処理

else

べつの処理

endif

否定演算子!を使うことによって、p0がFALSEの時の分岐が実現できます。

if !p0.適当な成分

if predは、if_compと一緒に24階層までネストできます。

 

 

      callret, label (サブルーチン呼び出し: 2_x, 3_0)

 

サブルーチンは、labelとretでくくられた命令を呼び出して実行します。call命令は2スロット、retは1スロット、label命令は0スロット消費します。

call 1

なんかの処理

 

label 1

サブルーチン命令

ret

labelとして使える数字は2_xでは0〜15、3_0では0〜2047です。Labelの位置は、call命令の後ろに置かなければなりません。

2_xでは再帰はできません。3_0では、再帰することができます。

 

      callnz (条件付きサブルーチン呼び出し: 2_x, 3_0)

 

条件付きサブルーチンは、分岐レジスタの値がTRUEの場合にサブルーチンを実行します。callnz命令は3スロット消費します。

callnz ラベル番号, b#

 

      callnz pred (プレディケーションに基くサブルーチン呼び出し: 2_x, 3_0)

 

プレディケーションに基くサブルーチン呼び出しは、プレディケーション レジスタの値がTRUE(!がついている場合はFALSE)の場合にサブルーチンを実行します。callnz pred命令は3スロット消費します。

callnz ラベル番号, [!] p0. 適当な成分

 

      rependret, label (反復: 2_x, 3_0)

 

反復は、反復レジスタを見て処理を繰り返します。rep命令は3スロット、endret命令は2スロット消費します。

rep i0

ループ内処理

endrep

整数レジスタのx成分は繰り返し回数になります。ループの最大回数は255回です。反復は2_xではネストできません3_0では、4階層のネストができます。反復のループの中にジャンプして入ってきたり、飛び出たりすることはできません。また、ifブロックをまたぐこともできません。break命令や、break_comp、break pred 命令でループを抜けることができます。

 

      loopendloop (反復ループ: 2_x, 3_0)

 

反復ループは、整数レジスタi#を見て処理を繰り返すと共に、ループカウンタaLを使って、定数レジスタの番号をずらしながら読み込めます。loop命令は3スロット、endloop 命令は2スロット消費します。

loop aL, i0

ループ内処理 (aLが定数レジスタの指定に使える)

endloop

i0.xにループ回数、i0.yにaLレジスタの初期値、i0.zにaLレジスタの増加数を入れます。ループは2_xではネストできません3_0では、4階層のネストができます。if文をまたげません。break命令や、break_comp、break pred 命令でループを抜けることができます。ループの初期値およびループの繰り返し数は負にできません。

 

      break, break_comp, break pred (反復ループ: 2_x, 3_0)

 

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 (プレディケーションレジスタの設定: 2_x, 3_0)

 

レジスタの比較によって、プレディケーションレジスタを設定します。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を指定することができます。