仮眠プログラマーのつぶやき

自分がプログラムやっていて、思いついたことをつぶやいていきます。 2025年からzennに移行

自作ゲームやツール、ソースなどを公開しております。
①ポンコツ自動車シュライシュラー
DOWNLOAD
②流体力学ソース付き
汚いほうDOWNLOAD
綺麗なほうDOWNLOAD
③ミニスタヲズ
DOWNLOAD
④地下鉄でGO
DOWNLOAD
⑤ババドン
DOWNLOAD
⑥圧縮拳(ツール)
DOWNLOAD
⑦複写拳
DOWNLOAD
⑧布シミュレーション
DOWNLOAD
⑨minecraft巨大電卓地形データ
DOWNLOAD
⑩フリュードランダー
デジゲー博頒布α版
DOWNLOAD
⑪パズドラルート解析GPGPU版
DOWNLOAD
⑫ゲーム「流体de月面着陸」
DOWNLOAD

HLSL

HLSLでリアルタイムレイトレーシング

のんびりと更新を続けて、今回でやっとライブドアブログ移転2回目の記事


まずHSPコンテストのことだが、今年は作成時間がとても少なく、締め切り直前にあたふたした感が否めない。
この前の記事で構想を温めていると自慢したはずの流体力学は、10/31日時点で全く自分の思い描いていた形に仕上げられないままであった。
今年の投稿は諦めるかと悩んだが、ブログの方でHSPで高速な演算ができることに期待をしているコメントを頂いていたことか後押しして、投稿することにした。
実際、自分にとってこの大きな発見を、一年も後に発表を引き延ばすことは耐えられるか危うかった。

投稿直前の10分でとりあえず動く形にして、付属として入れるはずだったリアルタイムレイトレーシングの方が完成度が高かったので、仕方なくそっちをメインということにしてサムネも作成した。
本当は「HSPでGPGPU」という名前にしたかったのだが、パソコンの時計を見たらもう58分になっていて、焦ってシフトキーを押す手が震えてしまい全部小文字になってしまった・・・
それとHSPでGPGPUは実はHLSLでGPGPUだった件

結局UPしたのは0:00を30秒くらいオーバーしていた・・・がなんとか受け付けてもらえたようだ。


そのような経緯があって、内容説明文や何から何まで完成度が1%となった。
本当はリアルタイムで数値流体力学シミュして、ゲームみたいに遊べるようにしたかったのだが。


そして11/18正午・・・、一次審査通過が決定!落ちた人には申し訳ないが、嬉しいけどこれじゃ不甲斐ない・・まぁ言い訳してもみっともない

来年こそは、時間たっぷりかけて作品を仕上げてやる!



また、参加者の作品を何十個か遊んでみたのだが、こういうゲーム自分もいつか作りたいと思ってたんだよねーというものが多く、各々自分の創造力を大切にしながらゲームを作っているなと言った感じだった。

やっぱりHSPコンテストの意義と言うか、最終目標は『HSPでこんなことが出来るのか!すげぇ!』という感動を初見に、あわよくば既存のユーザーにも与えるという事だと思う。

今年はそんな「すげぇ」と言わせてくれるような作品が多かったように思えるし、「将来すげぇものに化けそうだな」というような作品を作ってくる人も多かった。

私も少しながら、評価コメントの方で「すごい」と言わせられたので当面の目標は達成したかなと思っている。





さて本題だ

HLSLのピクセルシェーダを使って、512×512ピクセルのスクリーンにリアルタイムレイトレーシングをする方法だが、その手順を書いていこうと思う。
 
 前提としてHSPがインストールされていることと、easy3Dのver5.2.3.3が入っていることが条件。(なぜeasy3Dの過去バージョンを使っているかは後述)

今回もいきなりLEVEL100のモンスターを倒すようなマネはしないで、しっかりLEVEL1から、一番敷居の低いアルゴリズムで基礎の基礎からはじめていこう~!


【導入・・・的な】

レイトレのアルゴリズムといえば、


(1)視線は、スクリーン上のある画素を通って物体方向に向かう。この視線と交差する別の物体があるかどうか調べる。
(2)交差する物体が存在するなら、視線と物体との交点を求める。交差する物体が複数ある場合には、すべての物体について交点を求める。交点がない場合には背景の色とする。
(3)視線と交点との距離を求め、最も視点に近い物体を抽出する(隠面消去したことになる)。
(4)可視物体の輝度の計算をする。このとき、光源と交点を結ぶ線分と交差する物体を調べ、影の有無を判定する。
(5)反射・屈折がある物体なら、反射方向、屈折方向を求め、これらの方向を視線とみなして②③の処理を行い、屈折・反射して見える物体を抽出する。
以上の処理をスクリーン上のすべての画素について行う。
(5)の処理では、視線(レイ)と交差する物体が不透明物体の場合には、陰影計算によって物体の色を計算し、画素に塗る。一方、鏡面のような反射面に視線が交差した場合には、さらに反射方向を追跡する。また透明物体の場合には、屈折方向も追跡する。反射と屈折方向の両方を求める必要がある場合が多い。光線の反射や屈折方向を求めるには、その面の向き(すなわち法線)を求める必要がある。また、屈折方向を求めるには、法線方向のみだけではなく、その物体の屈折率が必要である。視線が反射と屈折の2本の線に分岐することから、追跡経路は2分木表現される。


http://www.rsch.tuis.ac.jp/~naka/naka/scola/member/chapter5_html/chapter5.html
に解説してあるとおりで間違いない。

だがこれはいわば
LEVEL50くらい手強いモンスターである。

ここからLEVEL1に下げて考えるには徹底的に簡略化する必要がある。


まず(1)は削る所がない。
(2)は、物体の形で交点を求めるプログラムが変わってくるが、ここは一番簡単な「球」の1種類でいいだろう。
背景色は最後の視線の方向で色と明るさ決定。(単色はダメ)
(3)ここも削る所がない。
(4)影の有無は面倒なので消去。(全て影なしとして計算)
(5)反射はあってもよいが、屈折は屈折率とかで面倒。光の吸収率も面倒なので100%光が反射するという設定でいこう。これで不気味な2分木とかいう経路演算は必要なくなる。これで相当簡単になるはず。

さらにレイトレではなぜかチェック模様の地面があるのが普通とされているのだが、地面と視線との当たり判定がコレまた面倒なので地面も取っ払い、球だけの世界で良しとすればどうだろう・・LEVEL1近くなったんじゃなかろうか





この方法をフローチャートにまとめるとこうなる。

ritrhrtyt

うん。かなり簡素化したな

ここで視線ベクトルと視点(位置)ベクトルは、それぞれ以下のベクトルtV、Mのこととして考えて欲しい。
4b8b9221.png

【テクスチャの準備】
GPGPUをやるということは、テクスチャを変数に見立てるということに他ならない。
ここで、レイトレで必要な変数と要素数を全てあげると、

・球の位置座標(x、y、z)と球の半径r = 4×球の数
・視点ベクトルM(x、y、z成分) = 3×全画素数
・視線ベクトルtV(tx、ty、tz成分) = 3×全画素数
tは上の図で言うカメラの位置から交点までの距離。
・視線と交差した球の識別IDを格納する変数 = 1×全画素数
・レンダリング用のバッファのr、g、b成分 = 3×全画素数


だ。

E3DCreateRenderTargetTexture命令で、テクスチャフォーマットはA32B32G32R32Fにしてバッファを作ると、
1ピクセルにR,G,B,Aの4つの情報を格納できる。さらに一つ一つの精度は単精度floatでレイトレには十分といえる精度だ。

さて上の変数をテクスチャ数がなるべく少なくなるように格納すると


・球の数だけ画素があるテクスチャ  ×1枚 : 球の位置x、y、z、半径rを格納
・512×512ピクセルのテクスチャ    ×3枚 : tV(tx,ty,tz)とIDで1枚(①)。M(x,y,z)で1枚(②)。レンダリングバッファのr、g、bで1枚(③)

ということで4枚のGPUバッファを用意すればいいことになる。


百聞は一見にしかずだ


32個の球の情報を格納したテクスチャは
kyu
こんなこんじだ。(大きさは64×64ピクセル)(節約しようと思えば8×8のバッファで事足りるが・・)


【フローチャート】
また、下の図は2枚+レンダリング用バッファのテクスチャを、レイトレーシングが完結するまでの各タイムステップごとにキャプチャしたものである。


a0a1
a2
a3

縦を①~③で区切って、横を(A)~(I)で区切ったとして

(A)は初期視線ベクトルを代入した時点での画像で、(I)は完成時の画像

①の列の画像は ・・まぁ書いてあるが・・ 視線ベクトル(x、y、z)成分がこの画像のr、g、bに対応してある。4つめの成分であるaの情報は割愛してある(表現できないし)




(A)の①
a0
フローチャートで言うと一番上
「視点、視線ベクトルxyz成分決定」
最初に飛ばす視線ベクトルtVを決定する。初期視点ベクトルMは全画素同値。
最初のtVは無限遠の空に飛んでいく視線なので
ここではtをできるだけ大きい数にとるのが理想(実際は65536を格納)
青地に、左が赤、上が緑っぽいグラデーションがかかっているのが分かるであろうか

赤はrつまりxの値が高いということを表している。
緑はgつまりyの値が高いということを表している。

赤い部分は、視線ベクトルが左方向に傾いていることを表している。
緑色の部分は、視線ベクトルが上方向に傾いていることを表している。
青はz方向なので手前から奥に向かう視線であることを表している。

マイナスの値は0にクランプされて表示されているが、クランプされているのは表示の方だけである。


(A)の②
a1
ここではまだ、球との当たり判定をしていないので、位置ベクトル=カメラの位置=(0,0,-7)で真っ暗な画像になっている。



(B)の①
b0
フローチャートで言うと2番目
「球と視線の交点を求める」
全ての球について当たり判定を行なう。

まず、一つ目の球でt1V(t1x,t1y,t1z)を求める。
これをr,g,b成分に代入するのだが、t1Vの解が求まらない場合(つまり交点がない場合)は代入を無視。
次に二つ目の球でt2V(t2x,t2y,t2z)を求める。
t1>t2なら代入。t1の値はr,g,b成分から求めればいい。(  t1=sqrt(r*r+g*g+b*b)  )

これを全ての球で行ない、最終的に一番近い交点への視線ベクトルが代入されたことになる。

そしてこの画像は全ての球との当たり判定後の状態。
球のところが黒く抜けているが、これは黒い部分に代入されているベクトル情報が例えば12.1×(x,y,z)みたくなっているので、無限遠に飛ぶ65536×(x,y,z)と比べて値がとても小さい → 相対的に黒く見える、という状態だ。(ここで(x,y,z)は単位ベクトルである)


(C)の②
c1
フローチャートで言うと3番目
「一番近い交点を視点ベクトルに代入」
交点がない場合、それまでの値は保持されたまま。
という訳で、視点ベクトルに代入された結果が(C)


(C)の①
c0
フローチャート4番目の「反射ベクトルを視点ベクトルに代入」
反射ベクトルの求め方はココで解説したとおり。





以降フローチャートの2~4が3回ループして、反射回数が増えていく・・・



(I)の③
i3
フローチャートの5番
「最後の視線の方向で背景色決定」
3回反射処理した結果、全ての画素の視線の先に球はなく、無限遠の背景が残るのみとなったら、視線ベクトルから背景色を決定する。

ここで、ライト(光源)ベクトルがあると便利である。
光源ベクトルと視線ベクトルの内積で1.0~-1.0の値が得られ、1.0が明るい水色の空、-1.0が暗い灰水色の空としてrgbを決定すれば意外とリアルな空になるはずである。





最後に少し応用で、新たに変数を作り反射した回数を記憶させておけば、反射による光の半減も再現できる。
あいにく視点(位置) ベクトルを格納しているテクスチャにはa成分だけ空きがある。
③の列のレンダリング画像は、実はその光の半減を取り入れている。





ひと通りフローチャート説明がこれで終了
カスタムシェーダは自分でくんでもらうとして 、とりあえずHSPでeasy3Dを介したHLSLによるリアルタイムレイトレーシングはこんな感じで動いている。

カスタムシェーダのソースとHSPのソースは
http://loda.jp/babadom/?id=114 
 からダウンロードできる。





だがこのソースははっきり言ってまだまだ改良の余地がありまくる。
今回の方法では、全てのドットで同じ処理をしないといけない制約があるので
例えば1ループ目ですでに球との交点がないドットでも、3ループ目まで当たり判定の処理をし続けないといけない。

だから全体的に無駄な処理が多い。
逆にまだまだ高速化が期待できるというわけだ。

どこまで挑戦できるか分からないが、飽くなき高速化への道はまだまだ続きそうだ。




ところでもしグラフィックボードが32bit浮動小数点の計算に対応していないとどうなるのか・・・
一応起動して、16bit浮動小数点のテクスチャで計算されるらしい。
だが少し計算にズレが生じるらしく、完成画像が少し荒くなる↓
msafr





あと前半の方でeasy3Dのバージョンが 5.2.3.3 を使用しないといけないと書いてあるが、
始めに「hspでgpgpu」を知り合いのパソコンで起動してもらおうとしたらなぜか起動しなく、その時easy3D.dllの最新バージョンを使っていた。
逆にインストール不要形式のバージョン 5.2.3.3で試してみたら動いたので、こちらを推奨しているというわけ

ちなみにその人のパソコンはwindows7でかなり最新のノートパソコンなのでDirectxは10以上だった気がするから、起動しなかった原因はよくわからない・・おちゃっこさん究明お願いします。



次回:流体力学のプログラムを作りたい!その2


PS
なんかコンテストTVに「hspでgpgpu」が紹介されてました!!審査員の方々ありがとうございます!!
あと2日で最終選考の結果が発表ですね。楽しみです

HSPで高速並列演算

(※並列にできるのは整数型、float型の四則演算のみです。命令や関数の並列処理は難or不可です。)


 前にブログに書いたようにhgimg3やHSPDXfixなどのプラグインは標準命令と比べて描画がとても早い。
 標準命令ではスペックに限界があり、例えば自分の作りたいシューティングゲームなどがとても60FPS出せない場合はこれらのプラグインを使うと解決されることが多い。

 たいていこういうプラグインは、ハードウェアに処理をさせているため高速に描画できます、とか書いてある。

o0380008511359222298


 その「ハードウェア」ってのはつまるところGPU(広義のグラフィックボードやビデオカード)のことで、端的に言えばこいつもCPUみたく四則演算ができる演算装置だ。ただCPUみたく高度な処理はきなくて、全画面のピクセルの書き換えとか、同時に何万もの同じ処理をしたいときなどに向いているとされている。

 GPUは本来グラフィック関連の処理に特化されたチップなので、その用途以外で使われることは考えられていなかったようなのだが、GPGPUと言って最近このGPUがCPUにかわって様々な処理をするようになってきた。 動画変換や計算科学(流体力学やブラックホールシミュレーションなど)といった、グラフィックに関係ないところに使われるようになってきて、それもまたCPUで処理するより何十、何百倍も早いそうなのだ。

 http://dic.nicovideo.jp/a/gpgpu (ニコニコ大百科がまとまってて分かりやすい!)
 後にも書くが、流体力学の計算をCPUとGPUでやらせたときの処理時間比が私のパソコンでは最大180倍になるという結果になった!
これは2^n×2^nの計算領域でCPUとGPUで流体計算させたときの1ループの処理時間(秒)

o0703046311359223918



 あまりにもGPUの計算時間が早くて、いまいちすごさがパッとしないので処理時間の比をとってみた


o0725041611359223917


 横軸が若干省略されてしまっているが、
512^2と2048^2の間にある1024^2の計算格子領域で一番GPU/CPU比が高く181倍も高速化ができた。
大岡山に存在するとされている某スパコンは、主にこのGPUで計算させているのでCPUのみのスパコンと比べすごく演算が早いとのこと。(もしCPUだけで同じ性能にしようとすると莫大なお金がかかる)
周波数が高いわけではなく、何万もの計算を並列に行なえるから結果的に早いのだそうだ。


・・・さて長い前置きは置いておいて、 私はHSPコンテストで分子シミュレーター
o0640048011359227067


とか
重力シミュレーター
o0431032111359227068

とか


まぁ普通にくだらないクソソフトを毎年量産しては応募しているのだが・・・
何がクソかというと、なんといっても処理が重いのだ!

これはプログラムが非効率なのもあるが、多数の粒子や相互作用などを計算すること自体がそもそも物理的に膨大な計算量を必要とする。

非力な私のノーパソのCPUでは、一億桁×一億桁の計算に何日もかかるというのに、分子のシミュレーションをリアルタイムでやろうとするなんぞ分不相応というか背伸びのしすぎであった・・・

今よりもCPUの性能が上がればいいのだが、生憎CPUのクロック数はもう頭打ちと言われていてせいぜい3.6Ghzが一般CPUの限界だから、今の1.5倍にしかならない。
HSPはマルチスレッド対応ではないため、私のやりたいシミュレーション系のプログラムはもうCPUだけでは限界なのだ。 多重起動の擬似マルチスレッド化とかして工夫はしてきたものやはりCPUに頼っているだけでは根本解決にはならない
そこで、本格的にGPGPUプログラミングに手を出そうと考えていた。

調べていくうちにGPGPUプログラミングのためにはnVIDIA製のGPU搭載デスクトップPCを買い、CUDAを勉強するのが一番手っ取り早いということがわかったのだが・・・

1 買う金がない
2 デスクトップ置く場所がない
3 CUDAを勉強する時間がない

の理由から諦めかけていた。
HSPでGPGPUプログラムができれば全て解決んだけど・・と思って何気なくHSPのサンプルを眺めていたら・・ これはもしかしたら、 HSPでGPGPUぽいことができるんじゃないのかと、そんな確信に近いある予感がひらめいた!!

きっかけはeasy3Dのサンプルのe3dhsp3_CbCr.hspを見た時だった
実行してみると、左には普通の3Dモデルのサンプルがリアルタイムで動いていて、右にはそのモデルの色だけがセピア色に変換されて同じく動いている

o0230017311356902500


 そうセピア変換とは、昔私がブログに無駄に長いソースを貼っつけたアレである。

まず画面の全ドットのrgb成分をyuvに逐一変換してuvに一定値を代入してまたrgbに変換・・・というやつである。
これをeasy3Dの中で実現しているということは、GPUにrgbをyuvに変換する並列処理をさせているということに他ならない!(CPUでリアルタイムなんかまず無理であろうし)

ということはソースかdllのプログラムのどこかにこのrgb成分をyuv成分に変換する、掛け、割り、足し、引きの計算式が書かれているはずだ!
そこのソースを改変すれば、自分の好きな手順、順番で四則演算ができるということではないのか!? この仮説が正しければeasy3Dのプラグインを使って高速並列計算が可能ということになる!
高速シミュレーションの道を開くために、執念でdllを解析しようかとか考えていたら、思いのほかもっと近くにその四則演算部分のプログラムを発見した
e3dhsp3.dllのと同じフォルダにある「E3D_HLSL」だ!
o0480024011361295228


そのフォルダにposteffect.fxが入っていて、こいつがセピア変換の四則演算を記述してあるソースだった。
調べたらこの.fxという第二のソースはHLSLといってHigh Level Shader Languageというもうひとつの言語らしい
おや、fxファイルをメモ帳で開くとプログラムソースが見れる!
ということは編集もできるではないか!?

o0730063411361295227



このファイルに自分で式を打って正常に動けば、自分の思い通りの並列処理が可能ってこと!?
試しに計算式を消したり追加したり実験してみたところ、コンパイルが正常に行なわれた

驚くべきことに、HSPで並列処理ができることがこれでわかった!!(正確にはHLSLでだけど・・・)


さらに驚くべきことに、easy3Dのソースを調べていくと律儀にも、私みたいなユーザーがposteffect.fxを改変できるようにと、なんとすでにカスタム領域が備わっていたのだ!
あとからおちゃっこさんのブログを見てわかったのだが「カスタムHLSL機能の需要は?」という名目で2年以上も前にこの自由に定義できるカスタムHLSLの機能を作っていたらしい。
つまりHSP側で並列計算させたいデータをeasy3Dの命令でGPUに送り、GPU側の処理の操作はHLSL(posteffect.fx)のカスタム領域で自分の好きな処理をさせられ、処理結果をまたHSP側で取り出すといった一連の操作が、我々ユーザーのためにすでに可能にされていたということだ。

HLSLのカスタムを可能にしてくれたおちゃっこさんには本当に感謝しないといけない!!
おちゃっこさんは需要なさそうと気にしていらっしゃったようだけど、これぞまさに私の求めていたもの!
この機能に出会えて本当に良かった!




HSPで並列演算ができるとわかった今、シミュレーションプログラムの幅が大きく広がること間違いなしである!!
これでもう数値解析やシミュレーションのデバッグに何日もかけないで済む!
HSPコンテストに糞ソフトと呼ばれるような生半可なシミュレーションソフトは出さないぞ。(呼んでいるのは主に自分)
さらにさらに驚くべきことに自分の非力なノーパにもそれなりのGPU・・オンボードだが・・がそなわっていたらしい!
o0399042211361313932

今の今まで気づかなかった・・そもそもGPUなんて付いてないものかと・・
最大単精度浮動小数点バッファまで対応してるみたいだし、シェーダモデル4.0で、なんだか考えられる中で最高の環境が気づかぬ間に手元にそろっていたようだ。
で、 具体的な並列処理の方法だが、自分の手順をさかのぼってみて、例をおりまぜてまとめてみた。





まずHSP3.2は入っている前提で

・easy3dのサイトからEasy3DForHSP3_ver5233をダウンロードする
・解凍してreadme読む ・readmeの言われたとおりにする
・次に解凍した中のE3D_HLSLのフォルダもhsp3フォルダにコピー
・下のリンクからダウンロードしてきたposteffect.fxを、hsp3フォルダのE3D_HLSLの中にあるposteffect.fxに上書き

いきなりHLSLを自分でカスタムするのは難しいので、他人のカスタムしたものを参考に少しづつ変えて勉強していくのが一番いいだろう。またHLSLのサイトにいけば命令とか演算子が全部見られる。
サンプル 上のサンプルは、左の2枚の画像を加算、減算、割り算、掛け算しその結果を右に出力するというものだ。1~8のキー操作を受け付けて8種類の処理が見れるようになっている。

o0777040011361295229

話を戻して、例えば足し算の並列演算をしたい場合なら、

・#include "e3dhsp3.as"して、E3DCreateRenderTargetTextureで、足す方を格納する2枚のテクスチャと、足した結果を出力するためのテクスチャをひとつ、合計3つ、同じ大きさで作る。
 ようはc=a+bという計算をさせたい場合、aというテクスチャとbというテクスチャとcというテクスチャを作ってください、ということだ。
 テクスチャの大きさは、並列に処理したい要素数によって変わってくる。65536要素の計算を並列に処理したいときは256*256の大きさのテクスチャをつくればいい。
・E3DShaderConstUserTexで足す2枚のテクスチャをGPUに送る
・E3DCallUserShaderでshadernoを0、passnoを1にして、足し算実行。これでE3DCallUserShaderの描画先のスワップチェインID(テクスチャ)に足し算結果が出力される。(ここらへんはサンプルの中にソースあり)





といった流れが、足し算の並列処理の方法だ。
passnoを変えれば割り算などを指定できる。
当然posteffect.fxを書き換えれば3つ4つ連続の足し算や、割った余りを求めるものなど、無限の処理が可能となる。
出力された計算結果(テクスチャ)はE3DShaderConstUserTexで指定しE3DCallUserShaderでつぎの処理に使いまわしていく事ができる。

上のスクリーンショットにも書いたが、E3DCreateRenderTargetTextureで作成するテクスチャのbit数を16bitや32bitにすれば、浮動小数点同士の足し算掛け算を並列処理できることとなる。

問題は、並列処理するときのデータが全てテクスチャ形式で行なわれているという点である。

はっきりいってHSP側で作ったDOUBLE型の配列変数を浮動小数点テクスチャに変換するというのはかなり至難の業である。(整数テクスチャならば話は簡単で、bmp形式でデータのやりとりを行なえばよい。)
というのもE3DCreateRenderTargetTextureで作ったテクスチャに1ドットずつ特定の値を書き込む命令がない。(というかeasy3Dはおそらくこの使いかたは想定していなかった)。だから何らかの方法で工夫しないといけないのだ。
それに、作れるテクスチャの精度が最大32bitなので標準命令のdoble型(64bit)と比べ精度が落ちる。グラフィックチップによっては16bitが限界だったりするから、CPUでのdoble型の計算をGPUで精度を落とさずやるには、16bitを4回計算みたいな感じでやるなどさらなる工夫が必要となる。

そして浮動小数点テクスチャから配列変数に戻すのも同様に大変である。
そこらへんを考慮した設計でないと、予想と結果が大きく異なってしまう可能性がある。


ということは、HSP側で配列変数を作る必要は本当にあるのかという疑問がわく。
並列演算出力結果を例えば視覚的に見るだけで良い場合(流体解析や分子動力学など)なら、posteffect.fx内で可視化プログラムを作ってしまえば、easy3Dのテクスチャレンダリング命令でスクリーンにいっきに可視化できる。わざわざHSP側で作った配列変数に値を戻さなくても、だ。
理想はそのような形で、最初から最後までテクスチャとして数値を保存しておく方が楽で良いのだが、厳密な数値を文字列として出力しなければいけないなど、どうしてもHSP側の変数に数値を戻す作業が欠かせない場合がでてくるだろう。 浮動小数点バッファを小数のまま保存できたりHSPのメモリに転送できる命令があればいいが、ない以上、1枚の浮動小数点バッファを何枚ものbmpに情報を分解して保存するアルゴリズムを構築するしかないのかもしれない。少なくとも私のお思いつく方法は今のとこそれしかない・・・
それだけがHSPでの並列処理においての大きな問題である。逆にもし単精度浮動小数点テクスチャと標準命令のdouble変数が両方向に対して変換可能になれば、まぁ64→32bitで精度が悪くなるのは仕方ないとして、タイトル通りの「HSPで高速並列演算」が可能になるというわけだ。これからは浮動小数点の構造の勉強をしてなんとか数値の取り込み、取り出しの問題を解決していきたいと思う・・・。








最後に、標準命令だけで作った流体力学プログラムを、HLSLに移植して並列処理化してみた。 計算は32bit浮動小数点バッファを使用、格子数は256*256で、CPUの80倍以上高速に処理できた。

o0512025611361324083

(一応解説すると、上から流体が流れてきてて、画面上の方にあるみにくいけど黒い動かないのが障害物。画面右は圧力を可視化した物。緑=高圧、赤=低圧)

これは、出力がスクリーンのみなので、posteffect.fxのほうに可視化プログラムが記述されており、可視化したテクスチャをeasy3DのE3DRenderSpriteでスクリーンにコピーしている、といったところ。
また入力のほうは、障害物の場所情報とか、0(なし) 1(あり) の2進数で表せるような情報しかないため、HSP側でbmpの生成→easy3Dでbmpの読み込み、bmpをスプライト(整数)に貼りつけ→32bit浮動小数点テクスチャにスプライト貼りつけ、・・と、数値の劣化なくGPUに送ることが出来ている。
並列処理を利用した数値解析シミュレーション特に流体力学はHSPコンテスト2011に向けて温めているもののひとつなのでネタバレはこのくらいにしておくとしよう。


次回:流体力学のプログラムを作りたい!その1













追記
HSP→浮動小数点バッファ への32bit浮動小数のデータ転送は
userFL4_0 ~ userFL4_9 のユーザー定義定数を使って正確に 行なえることが分かった。

また32bit浮動小数点を、4つの8bit*3(r,g,b)バッファに分解して転送して、HLSL側で数値を復元する方法も試みたが、
仮数部の最小1bit部分でたまに誤差が生まれる模様・・・


また浮動小数データの分割&整数値化による GPUバッファ→HSP へのデータ転送は全くうまくいかず・・・orz
プロフィール

toropippi

記事検索
アクセスカウンター

    QRコード
    QRコード
    • ライブドアブログ