![]() |
||||||||||||||||||||||
![]() |
8/18 PixelShader事始め いつのまにやらこのサイトも6周年記念日が過ぎ去り、夏のイベントにも恙無く物見遊山…と 爆裂プログラマンさん、Ko-Taさんに感謝します。 いろいろと。ホントに。 ともかく、ネット社会復帰を宣言した以上は何かかまさないといけなくなってしまいました。困ったなぁ…いやいや、従来のテンションに戻れば良いだけ、何のためらいが、何の障碍があらんや。
さて、復活第一回はPixelShader(以下PS)特集です。というより、僕の学習用メモ そんな唐突に…と思われるやもしれませんが、実際のところ僕ぁPixelShaderの事を忘れちゃったというよりむしろあんまり理解せずにここをこんな風にいじればなんとかなるっぽという程度にやっていたもので全く応用の効かない状態でした。 実のところサンプル作って満足満足うむうむ、という状態だったもので。 しかし、そんなんじゃいけない。もっと高いところを目指さねばならない。ひょっとしたらシェーダ書いてメシの食えるステキ人物になれるかもしれないご時世、頑張らなきゃねぇ。 なに?うちじゃPSなんて積んでないからなんとかしろ? 邪魔する奴は指先一つでダウンです(゚∀゚) 繰り返しになりますが、以下は僕の学習用メモですので、間違いなどありましたらご指摘お願いします。インタラクティブ学習メモ、いいね。 …今回はまず初めという事で、PS1.1に則って話をすすめます。1.4や2.0での拡張については追々。また、HLSLには言及せず、PSアセンブラに論点を絞ります。 PixelShaderって、なんだまずは、PSの入力と出力が何なのかを明らかにする事で、PSについて捉えてみましょう。 一言で言うと、PSとはレンダリングパイプラインのうち、テクスチャ座標、頂点色などの入力情報からポリゴン(のうち1ピクセル)の色を決定する部分です。画面に表示されるポリゴンの1ピクセルごとにPSのルーチンが呼び出されるのです。 かつてはポリゴンの色というのはRenderStateで決定されていたわけですね。ポリゴンの頂点の色と、その線形補間、それに数枚のテクスチャの色をどうブレンドするか、と。 さて、PS1.1への入力・出力ともレジスタに割り当てられていて、特別に出力するための手続きとか、入力をゲットするための手続きとかは無く、簡単になっています。で、そんなレジスタの種類と役割について列挙します。
全てのレジスタは4つのSingle型で構成される、ベクトルを格納しています。 色を格納するレジスタはARGBそれぞれを-1.0〜+1.0のレンジで格納しています。但し、vレジスタには0.0〜1.0の範囲で色を格納されています(負数が無い) とりあえずやってみよう以上を踏まえてPSアセンブラでプログラミングしてみましょう。アセンブルの仕方とかはその都度説明するとして、PSアセンブラのソースを書いていきます。 わざわざPSでやるまでも無いんですが、ポリゴンの地の色と、テクスチャの色を乗算する、ごく普通のテクスチャ付きポリゴンを描画するためのソースを書いてみます。 ps_1_1 ;バージョンの宣言 tex t0 ;1ステージ目のテクスチャをt0レジスタに割り当てます mul r0,v0,t0 ;r0にディフューズ色とテクスチャの色を乗算したものを格納 add_sat r0,r0,v1 ;さらにスペキュラ色を飽和加算 ファイル名はshader.pshとでもして、保存しておきましょう。 アセンブルには、psa.exeを使います。DirectX9SDKをインストールしたディレクトリがc:\dxsdkと仮定すると、c:\dxsdk\bin\dxutils\psa.exe として入っているはずです。パスを通しておくと便利かもしれませんね。 して、コマンドプロンプトから psa shader.psa と打てば、shader.psoが生成されます。 あとは、これをDirect3DDeviceに読んで貰えばOK、以下、DGをTDGCaradオブジェクトとして説明します。 var
ms:TMemoryStream;
PS:IDirect3DPixelShader9;
begin
ms:=TMemoryStream.Create;
ms.LoadFromFile('shader.pso'); //psoファイルを読み込み
DG.D3DDevice.CreatePixelShader(ms.Memory, PS); //デバイス
こうして、PixelShaderオブジェクトを生成します。利用するときは DG.D3DDevice.SetPixelShader(PS); たったこれだけ。自前のピクセルシェーダの使用をやめて、固定機能ピクセルシェーダに戻したい時は、SetPixelShader(Nil) とすればOKです。 なお、現時点ではDG-CaradはD3DDeviceのロストに伴うPixelShaderの自動復元などは行わないので、自前で復元する手続きを用意しなければならないのが難点ですが、近いうちに対応したいですね。 InstractionFlowについてPS1.1を扱う上で考慮しなければならないのが、この概念です。 困った事に、PSではx86アセンブラと違って、いつでもどこでも好きな命令を使う、というわけには行きません。具体的には、
という順序でしか命令を実行できないようになっています。つまり、最初に定数から値を読み込んで、定数同士を加算や乗算などした結果からテクスチャアドレスを変更して…といった事は出来ないのです。テクスチャアドレスを変更するのはtexture instructionにカテゴリ分けされた命令群だけなのですが、これのリファレンスを見ると…まぁ、結構不便です(^^;) PS2.0からはこの制限はなくなっているので、結構ゴリゴリとプログラミングできてしまいます。 狙うなら2.0以降かッ…Ge4ユーザ全滅ですが 次回以上でPixelShaderが使えるようになりました。 ただ、見てお分かりの通り、固定機能VertexShaderをそのまま使っているとPixelShaderへの入力がかなり限られるので、折角のポテンシャルが活かしきれないと言えます。折角のアイディアもInstructionFlowの餌食になってしまうPS1.xではなおさらです。 そういうわけで、VertexShaderの習得はやはり不可欠。次回はVertexShaderに焦点をあててみたいと思います。
|
|||||||||||||||||||||
![]() |