!!!独り言日記 !!昔の作りかけ(2005/02/28) 昔作っていたパチもんゲー(ただし、ダンジョンを歩けるだけ)がHDDから出てきました。 {{ref_image dm_20050228.jpg}} リアルタイムで影とバンプ処理などしてます。 さて、何のゲームをぱくってるか分かるかな? さて、このようなリアルタイムでノドが渇いたり持ち物制限があったり、 ちょっと休んでいると後ろから敵にタコなぐりに合うゲームって、 よく考えると今のFPSですね。 当時、どきどきして遊んだものです。が、今のFPSではDOOMIII以外興味なかったりします。 もっとまったりとしたFPSだといいのですが・・・ (反射神経がいるのとかシューティング要素がいるのは苦手ですねぇ) !!前処理計算を速くした(2005/02/27) 以下のシーンで、オリジナルレンダラの場合、 空間分割(前処理)時間が551msで1秒もかかってないです。 {{ref_image myrenderer_20050227.png}} Athlon 1100MHz/Mem 512MBのWin2000マシンにて。全ポリゴン数 197190ポリゴン。 レンダリング全体で34sec(トラバース時のメイルボックスは今は未対応)640x480pixelです。 Shade7.5標準レイトレーサでは42secですが、前処理で15secかかってます。 このうちどれだけが空間分割処理かはわかりませんが、 前処理(空間分割処理)では余裕勝ちですね。 で、去年のレンダラだとこれが17secで終わってますのでまだまだ速くできるはず。 また、頂点法線を求めるための計算(スムージング角度による変化を求める)も ポリゴン数が増えると負荷がかかりますのでなんとかしたいところです。 と、リファクタリングするといろいろ見えて(目標は過去の自分のソース) すっきりしますね。ちなみに、前処理に関しては以前のレンダラよりも10倍近くは 速くなっているかと思います。次はトラバースを詰めねば。 !!「1:8:1」の法則(2005/02/26) レンダラを作る際にボトルネックを探ると、 主に重くなる部分として「トラバース」「交差判定」「シェーディング」などがあり、 だいたいどこに負荷がかかっているか傾向が出てきます。 UG/HUGの場合、どのようなシーンでも(これが影処理・反射・屈折などを含む場合、 ポリゴン数が多い場合でも)「トラバース:交差判定:その他」の全体に対するウェイトは 「1:8:1」に落ち着きます。あくまで私が実験した範囲内なので、トラバース手段や 輝度計算のタイプなどによっては変わるかもしれません。 でも、いくら反射を繰り返そうが屈折でレイが2手に分かれようがこの割合はあまり揺れませんでした。 では、トラバースと交差判定部分をハードウェア化して仮に「負荷0」になったとしましょう。 これを理想値としても、最大は(当社比)10倍速となります(「その他」の1が残る)。これ以上はいくらがんばっても速度アップできません。 Saarcorなどはリアルタイムレイトレできてますが、これの違いは「レイシューティングすべてをハードウェア化しているかどうか」が肝のように感じています。 実は、このようにしないといけないのは昨今のGPUでも同じで「ハードウェアとソフトウェアのI/O(DMA転送など)がボトルネックになりうるから」でもあります。 やるのなら、まとめてばっとハードに投げて結果はスクリーンに反映、でないと純粋なレイトレではリアルタイムには追いつかないのです(HevenSevenみたいな間引きでも使わない限りは)。 部分的に、例えば「交差判定」だけハードウェア化してもソフトウェアとハードウェアの やりとり(I/O)部分が見えてしまって逆に速度低下を起こす可能性があります。 また、レイの挙動をカスタマイズできるように(レイトレでもパストレでもフォトンでも自由に「プログラムできるように」)しないと、このあたりは普及は難しいでしょうね。 で、この手のレイトレ高速化の手段は「GPUを使用する方法」と「レイシューティングを並列化する方法」に大きく分かれるような気がします。 前者はすでに実現可能、後者は・・・実はこれがネットワークを使った分散処理に つながるものであるかもしれません(よくあるネットワークレンダリング。これを 1マシン上の演算器(と仮に呼びます)に分散させるとするとアクセラレータになる)。 後者はハードウェア化するにも規模(コスト含む)が大きすぎて難しい(というよりもラスタライズのほうがはるかに軽いですしね)ということで、なかなか微妙な分野ではありますね。 これが、リアルタイムレイトレがボード化しにくい現状のように思います。 Cell関連が話題に上がる昨今、既存マシンでも純粋なレイトレースの並列化はやりやすくなるかもしれません。 そうなると、オフラインレンダラとリアルタイムレンダラは時代の流れに任せていると いずれは交差するかも、と、そんな動きを見届けたいものですね。 CPUパワーとハード性能(PCIボードなどを使ったアクセラレータ)はいたちごっこですので、このあたりは将来明るいかというとグレイな面が 多いのかもしれません。が、夢はありそうです。そもそも、 基本概念を覆す使い方をされているのが昨今のGPUですので、レイトレース処理(もしかしたら それすら考えなくてもいいかもしれないですし)でも何かしら画期的な手法が 出てくれば面白いですね。 !!自分にうち勝つべし(2005/02/25) 数日風邪をひいていたのですが、睡眠パワーで回復。 やはり、薬よりも何よりも休息です。インフルエンザかどうかは 不明でしたが、寝れば直るもんです(が、風邪ひいたら普通は病院行きましょう(^_^;;。 過信は厳禁です・・と私が言っても説得力ないけど)。 さて、ひさびさにレンダラを根底からチェック。レンダリング速度が 従来の3倍ほど速くなりました。というよりも元から遅かったのね(^_^;;。 しかし、まだ去年作っていたレンダラよりは遅いのです(レンダラ何本 作ってるやら・・・いい加減に完成させないと)。 ということで、まずは自分に勝たなくては。 用途によってレンダラを作り替えたりはするのですが、 目的によっても最適化方法は異なったりします。 というわけで、空間分割はBSPから再びUG/HUGへ移行中。 手慣れた手法のほうが最適化しやすいっす。 HUGって、行き着く先はOctreeと同じですから実装次第で メモリにも優しく効率もよくできると思うのです(これは 前処理の時間も含めて)。という訳分からん理由で、ここは我が道を進もうと思います !!夢のしずく(2005/02/22) ドラクエのアイテムか?と思われますが、松たか子さんの曲です。 テレビでちらっとかかっていたことがあって「いいなぁ」と 思ってましたので(2/20のマンガ喫茶に行ったときの渋谷で) アルバム買ってきました。 エンドレスで聴きながらプログラム書いてます。 ちょっと気になったのですが、アーティストや有名人は 「さん」付けで書いたほうがいいのか迷いますね(^_^;;。 一応、不特定多数が見るのがWebですので「さん」付けか「氏」付けが 無難かな。 しかし風邪かな、のどがやばい状態だ・・・・咳も出るし。 ということで、しばらく安静状態です(悲しいかなどこでも 仕事できるんで、頭がもうろうとしない限り問題なしです)。 渋谷混んでましたからねぇ・・・・どっかから移されたかな。 !!マンガ喫茶に行って来た(2005/02/20) 知り合いとノリでマンガ喫茶に初めて行ってきました。 PS2やパソコンもできるんですね。想像していたマンガ喫茶像と 違ったのでとまどいました(^_^;; (想像してたマンガ喫茶像:カウンターみたいな横並びの席に座って、 前や後ろの棚にあるマンガを取って黙々と読みふける・・・)。 実際は個室の狭い部屋で戸を閉めて1人の空間で読む、でした。 カラオケボックスを1人用にした空間、って感じでしょうか。 で、「ジョジョを1巻から通して読みたい!」が目標だったんですが 1時間でコミック2巻ちょっとしか読めなかったです、読むのが遅い?(^_^;;。 ジャンプ全盛期に3部くらいまでは読んでいたのですが見事に内容を 忘れているので、それがよかったか悪かったか・・・ しかし、確実に元取れてないな・・・読解力を上げなければ。 ということで、以下のRRTエクスポータプラグインはもうちょっとかかりそうです。 !!Redqueen(2005/02/19) 先日URLを書いたMaxwellの教室みたいな画像は Redqueenで出るんではないか、という気も してきましたので腕試しがてらチャレンジ。 また、軌道から大きく外れてますがこれも息抜きです(^_^;;。 とりあえず、rrtファイルの作成はShadeからの自前エクスポータで 出してるんですが、この際まともなプラグインの形にしてしまおうと 整備中です。 (すでにsio29さんの作成されているのがあるのですが、Shade7.5対応と はたしてどれくらいの時間で形にできるか、という自身のリハビリもかねて。 いや、差し迫っている締め切りがあるのですが ちょっと脇道にそれてみたい、というのが本心です(苦笑)) エクスポータは2日もあれば完成できる、かな。これも腕試しです。 ・・・Shadeエクスポータ機能ではぶっちゃけ標準のコールバックは 使えない(使い勝手があまりよろしくない)ので、 地道にscene_interfaceから形状をたどるほうが確実ですね。 後、ダイアログはやはり独自のパラメータを出したいので・・・ (出せるんですが、do_export関数とかでdialog_interfaceを出すと キャンセルでもファイルが生成されてしまうんだわ) と、エクスポータプラグイン部を触ってみてもいろいろモノ申すことが 多いっす。 以下、Shade7.5にてRedqueen2.0 Freeでレンダリング。 {{ref_image rq_20050219.png}} Shade7.5のパストレはノイズがやはり気になります。 Redqueenはさすがにこなれているというか、絵としての完成度が 高い気がします。後エクスポータでは、マテリアルと背景のエクスポート部のみ。 ShadeとRedqueen双方のパラメータをいじって挙動を確認してみると、 いろいろ勉強になりますね。 だれかMaxwellの画像をパストレで再現しようという蒙者はいないものか・・・ 8割方(根拠はないけど)は再現できるんでないかなぁ。空気感は モデリングとかテクスチャの出来次第と思いますので・・・(Maxwell本家のサンプル もちょっとわかりにくいかも、と思います。後、α版のサンプルをアップしている 海外サイトを見ても、見せ方がいいのと悪いのとがありますね)。 !!いいなぁ、Maxwell・・・(2005/02/18) http://www.bisand.com/ の http://www.bisand.com/maxwell/slides/1.html http://www.bisand.com/maxwell/slides/2.html なんかは空気感がツボです。いいっ!! 今はα版で395ドル(約4.1万円ちょっと)。悩みどころです・・・ (実は仕事場にMAX7があるのですが、、、Maxwellいじってみたい・・・) なんかShadeにも対応するみたいですね、対応に苦労すると思いますが(^_^;;。 こんなのを見ちゃうとフォトンマップを掘るのがむなしくなります(^_^;;。 レンダリングとしては、指定時間を決めてその制限時間内でできる部分だけを (プログレッシブのように)計算していくみたいです。 粗いのがだんだん鮮明になっていく、みたいな。これだとトライアンドエラーが 楽になりそうですね。 Maxwellの御本家は以下です。日本語で説明してくれているので、英語の苦手な 私も安心です。 http://www.maxwellrender.com/indexjp.html 手元にあるRedqueenいじりたくなってきた・・・ちょっくら遊ぼうっと。 !!ワイヤーフレームレンダラ(2005/2/18) どんどん目的から遠ざかっているみたいですが気にしない(^_^;;!! ってことで、今までの内容を生かしてワイヤーフレームレンダラを作ってみました。 {{ref_image wire_20050218.png}} また、形が出来次第公開しようかな(Shadeのプラグインです)。 このポリゴン描画+ワイヤーフレーム描画方法だと、ソフトウェアレンダラでも ワイヤーフレームが途中で途切れたりしません。 またアルゴリズムについては、改めてTipsとして(ソース付きで)公開予定にしてます。 もはや、この程度でしたらリアルタイムで(ソフトウェアレンダラでもいいですし、 OpenGL/DirectX使ってもいいですし)できそうですね。 ただ、苦労した点として「クリッピング」があります。これによって境界部分の 挙動が変わりますので、結局スクリーン全体のレンダリングが必要でした。 (実は、上記画像はCarraraやMentalRayみたいにブロック単位でレンダリングしてます。 なので、メモリは食わないですが速度は犠牲になってます) Shade本体のワイヤーフレームレンダラでも、ぜひ この方法でソフトウェアで対応してほしいものです。 (そうすると、大きなサイズでも対応できるんで。後、ハードウェアでの 挙動不審を回避できるし) !!続・ポリゴン描画とワイヤーフレーム(2005/2/16) ようやく、ポリゴン描画の上にワイヤーフレームを 重ねる場合のブチ切れ解消ができました。 過去のもの。線が途切れている部分があります。 {{ref_image wire_20050216.png}} 改善後。途切れることがなくなりました。ちょっと直線がガタガタな部分があるのは bresenhamアルゴリズムにてテスト用の計算いれているからです。 もうちょっとすっきりできると思います。 {{ref_image wire_20050216_2.png}} ワイヤーフレーム描画時に手前に少し浮かしている、 ということはしてません。 厳密には、浮動小数点のエラーの問題がありますので (AthlonとPentiumでは挙動が微妙に異なります。実は、 同じ開始点・終了点を持つラインを 同じZ値で描画してもイコールにはならない場合があります) 気持ち程度の調整は入れてます。 DirectX/OpenGLを使ってポリゴン描画すると当たり前のことが、 ソフトウェアレンダラでは意外と難しい実装になる、という なかなか骨の折れる検証となりました。 ・・・・思いっきりレンダラからそれていってる内容ですが(^_^;;、 これはいろいろ役に立つことでして。 例えば自前のモデリングツール(オリジナルの3Dエンジンを使用する場合) を作る場合でもワイヤーフレーム描画が汚くならない、 Shade標準のワイヤーフレームレンダラはOpenGLに頼ってますが、 これを自前の描画に置き換えるとハードの制限に左右されない (かつ、環境依存する挙動の問題に対処できる)、などなどです。 これにトライしている人ってネット上で見かけませんね・・・。 というか、ソフトウェアの3Dエンジン作る人が少ないからかな(^_^;;。 理屈としては、直線描画時(ワイヤーフレーム描画時)に ポリゴンとして補間しつつエッジだけ描画する、ということになります。 こうすると、理論上は同じポリゴン描画の上にポリゴン(といいつつ実はエッジだけ描画) を重ねるのでZ値の微妙な前後関係は確保される(イコールになる)ことになります。 !!意外と難しいポリゴン描画(2005/2/15) ポリゴンをソフトウェアで独自描画する場合、よく使われるのが 左右の稜線に対し、スキャンライン方向に交わる交点を結ぶ直線を 引いていく方法です。 {{ref_image drawpoly_20050215_1.png}} Zバッファで処理する場合はZ情報も持ちます。左右稜線それぞれに 対して始点・終点を探し、このうちスキャンラインで交わる点を 求めます。(x1, y, z1) - (x2, y, z2)とします。 水平方向では、この交点2点を線形補間することで求めていきます。 これを垂直方向に最小から最大まで繰り返します。 普通にゲームなどで使う場合はこれで問題ないのですが(つか、ソフトウェアで 独自には実装しませんわな)、 この上にワイヤーフレームを重ね合わせたい場合、不都合が生じることが あります。線がとぎれたり汚くなったりする問題です。 なぜそうなるのかというと、最終的に2D描画するときのドットの厚みによるもの に感じます。 {{ref_image drawpoly_20050215_0.png}} の上面図をスクリーンに描画するとすると、稜線部分を拡大すると 以下のようになります。 {{ref_image drawpoly_20050215_3.png}} 横方向に4ピクセル分の厚みがあるのがわかりますでしょうか。 さて、ではこの4ピクセルのうちで、Z値が大きく変化するとすると 「ポリゴン描画(スキャンラインコンバージョン)」とエッジ部分を描画する 「直線描画」でZ値がぴったり一致するでしょうか? ポリゴン描画では、稜線はBresenhamを使っても1ピクセルごと地道に計算しても いいです。ただし、ポリゴン・直線の描画は同じアルゴリズム・同じ順番で 稜線・直線を追いかけるようにしてください(でないと、誤差が出るのが 明白ですしね)。 普通に考えると、ポリゴンのエッジをなぞっているだけなのでZ値が 一致すると思うかもしれないですが、これが一致しないのです。 ポリゴン描画でスキャンラインごとの描画をする、このときに横方向では 「ポリゴンとスキャンラインの交点の開始位置・終了位置」の直線を 描きます。Z値もそれで線形補間されます。 直線描画(ワイヤーフレーム部分の描画)を行う場合は、 直線の開始位置・終了位置でZが線形補間されます (X方向・Y方向のうち、変化量が大きいほうで分割)。 ここで、Z値の矛盾が出てきます。 2つめの画像の上面図を見ると、実際は横1ライン描画するにも(直線を構成する同一ライン上の3-4ピクセル間でも) Z値が変化するため、スキャンライン描画と直線描画(斜め)でZ値が ずれてしまうのがわかりますでしょうか(う〜む、説明が難しい・・・)。 解決策は、直線描画も(補助線を入れるなりして)ポリゴンと見なして 対象となる直線を描画するか、スキャンラインコンバージョンをやめるか、 です(バイアスかけて直線を少し手前に出す、はゴミが気になります)。 DirectX/OpenGLによるハードウェア描画ではこの問題も解決されているのですが、 複雑そうです。別の方法でポリゴン描画してるみたいだし。 「http://spin.s2c.ne.jp/」のArticlesの【第3回 ラスタライズアルゴリズム】参照。 このあたり、乗り越えたい問題ですのでいろいろあさってみることにします。 いやはや、単純に見えて奥が深いです。 !!ポリゴンエッジ部の微妙な誤差(2005/2/13) ハードウェアにてレンダリング時に陰線消去する場合など、 以下のようにきれいに線が出ています(以下、DirectX9のMeshView)。 {{ref_image teapot_20050213.png}} で、こちらで作ったポリゴンの描画ルーチンだと途中で線が消えたりして 汚いわけですが(^_^;;、これはどうもポリゴン描画にて Bresenhamの直線描画のアルゴリズムを、 ポリゴンの稜線をたどるのに使っているから(整数でエッジ部を たどっている)かなぁと想像しています。 DirectX/OpenGLなどでの陰線消去のやり方は、 Zバッファのみをレンダリングし(色は反映しない)、 その上に直線をZ値を考慮して描画します。 このときZ値が<=の直線のみを描きます。 ここでブチ切れ直線にならない、ってことはこのポリゴン描画と直線描画の Z値がぴったりフィットしているから、かな。 ちょっくら私のほうのポリゴン描画ルーチンを見直してみることにします。 これ、何に使っているのかというとセレクティブレイトレースで 使ってるんです。微妙に汚れが出るんですね(直線描画時にZ値を少し 手前に持ってくればいいのですが、奥行きがあるとつらいし)。 見直さねば。 あ、でも、これをやるとソフトウェアのリアルタイム3Dエンジンを 作りたくなる諸刃の剣・・・。 このへんは情報公開しても差し支えありませんので、またTipsとして まとめることにします。 !!レンダラをShadeに持っていった(2005/2/11) ということで、開発中のレンダラをShadeプラグインにしてみました。 ・・・遅いネッ(T_T)!!。ということで、思ったより 重かったようです。アンチエイリアス処理をするまでもなく、 トラバースでネックになってました。 で、空間分割としては実はBSPを実験的に取り入れているのですが どうもこれが最適化できてないようで (以前作ったUniformGridのトラバースのほうが速かったです)。 「BSPって空間を再帰的に二分してやればいいだけやん」で 独自実装したのがまずかったか・・・。 ということで、先人の知恵を頼ってみることにします (以前、教えていただいたソースを見てみようかと)。 まぁでも、ようやくいろいろなシーンをテストできますので このあたりで、プラグイン化するって意味は大きいですね。 いろいろバグが見つかりましたし(^_^;;。 (Shadeでのプラグインについては、いろいろ問題というか 壁があって、それは後々ネタにしていきます) 大垣さんのところのコラムで、アンチエイリアスについて書かれています。 これも取り入れてみようかな。 http://www.teamredqueen.com/ ネットでは知識を公開してくださる方も多々おり、感謝感謝です。 特に英語の苦手な私としても日本語での解説があると 非常に起爆剤になるとともに、英語理解せねばという 焦りが募ります(^_^;;。でも、なぜ外国の方のほうが 優れたアイデア・論文などが多いんでしょうね。 そこに日本がソフトウェアが何歩も遅れている、ってカギがあるのかなぁ。 そもそもデキが違うって以外に環境(社会体制)の問題も大きいかも。 しかし、日本で活躍しておられる方もちらほら目にしますので 盛り上がっていきたいものです。 !!過去の遺物発掘(2005/2/8) > 今は無き、工学社の「I/O」 ・・未だ健在でした・・・申し訳ないっす。しかし、 投稿プログラムってやってるんだろうか・・ !!過去の遺物発掘(2005/2/8) 私は昔「後10年後にこれを見たら自分自身どう思うだろう」ってことで、 記念に作ったモノを残したりしたのですが、あさっていて過去に書いた書物を 発見しました。 1993年製のPC-9801用のレイトレーシングプログラムの原稿 {{ref_image paper_20050208_1.jpg}} 日付から見て1995年ごろのキャラクタエディタ仕様書 {{ref_image paper_20050208_2.jpg}} 1つ目のを見て(文書生成ソフトとして)何を使って書いたか分かった方、 非常にマニアです。 罫線を見ると特徴あるのでピンと来る方もいるかもですが、 今争っているジャストシステム社の 「一太郎」「花子」のDOS版で書いてました。 DOS時代は結構お世話になったので、ぜひ裁判ではジャストシステムにがんばって いただきたいですね(ちなみに、当時はうちの親がジャストユーザだったんで 使ってました)。 今はATOKだけしか使ってないですが、JustSystemユーザです、私。 1枚目のは、PC-9801の4096色中16色の環境にて、ディザを使って レイトレースする(コプロを使わない)レイトレーサです。 当時は、数値演算コプロセッサをマシンにつけないと浮動小数点演算が ものすごく遅いって時代だったんですわ。なんで、ぶっちゃけ固定小数点の ほうがはるかに速かったです。で、その解説をしていた原稿っす。 今は無き、工学社の「I/O」に乗ったやつです。今は、この手のプログラム雑誌 なくなりましたねぇ。 GRCGとかQuickC Ver2.0とかが哀愁を誘いますなぁ(QuickC Ver2.0は DOS時代最強のCコンパイラでした。BCCと二分してたけど)。 2枚目のWinG・・・って今は分かる人のほうが少なくなりましたね。 DirectX Ver1.0と後付けで言われたものです。 今は、Windows APIの「DIBSection」がその名残です。 当時、Win3.1/95は使い物にならなくって「これってゲームできるの?」って そんなレベルでした。画期的でしたねぇ。Windowsの転換期で出てきた目玉APIがWinGでした。 ちなみに、これより先にDOS版の「MCE16」ってのを作ってました。1992年くらい? これもI/O関連ですな。 おまけ。チラシの裏に書いたいつの時代のか分からないBASICのプログラム。 {{ref_image paper_20050208_3.jpg}} たぶん、小学生〜中学生くらいだと思う・・・暗号化って・・・・。 ということで、昔の自虐ネタは(^_^;;なかなか面白いっすね。 なんか「無限の心臓」(PCゲーム。IBMのJXでやったと思う)の 攻略のためにマッピングしたもの出てきました。 ・・ってやってること昔から変わらんです(^_^;;。 !!セレクティブレイトレース(2005/2/7) とりあえず実装完了。以下、4x4サンプリング/pixelです。 {{ref_image sr_20050207.png}} 面光源の影が新聞の印刷みたいなノイズになっちゃいましたが・・・。 1x1サンプリングで25sec、2x2サンプリングで85sec、そして 上の4x4サンプリングで291secです。面光源1つと、球はすべて反射物体です(最大10追跡)。 でも、まじめに面光源の計算をしているので、現実的に 使えるようにするために シャドウマップ実装か以前の研究ネタを投与して高速化したいなぁ。 相対的には速度比較できてないので、 一度シーンを変えて試していかないといけないですね。 実際は、4x4サンプリングなら(はしょらずに行くと) 1x1の約16倍になるのですが、10倍ちょっとに抑えてます。 というのは、アンチエイリアス処理で最適化をかましているからですが、 アニメーション時にもしかしたらちらつきが目立つかもしれないですね。 古い日記にアルゴリズムを書いたことがあったのですが、再帰(1ピクセルを 深く再分割し、同じような色ならスキップする)を使わずにはしょる方法を実装してみました。 そろそろ負荷テストもかねてでかい形状で試さねば。 ということで、よく研究で使われる形状(ハッピーブッタとかバニーとかドラゴンとか) のファイルフォーマットは「ply」という形式のものがあります。 http://www-graphics.stanford.edu/data/3Dscanrep/ 高品質で、しかも2000万ポリゴンを超える形状もありますので コンバータ作ってレンダリングかけようと思ってます。 初心に戻ってレイトレースで実験してますが、SIMD対応ハイパースレッド対応 など一通りしたら再びGI参戦(<こう書くと格闘技みたいだ・・・)ですなぁ、 時間かかりそうですが一歩一歩やってこうかと。 !!デジタルな音の仕組み(2005/2/6) 先日からサウンドについてネタにしているのですが、DirectSoundの ストリーミング実装、思ったよりも簡単でした。 まずは、基本的な音のデジタル処理の仕組みです。 元々、アナログな音はPCで扱えるようなものではなく 途切れのない滑らかな波で構成されます。 これをPCに取り込むためにアナログ・デジタル変換(A/D変換)が 行われます。これの変換方式により、音質が良かったりざらついていたり します。しかし、自然な音以上の質は取り込めず、結局は劣化してしまいます。 CD音質であれば「44.1kHz/16bit/2ch」なんて表現されます。 順に、サンプリングレート(サンプル数/秒)/サンプリングサイズ/チャンネル数を表します。 {{ref_image wave_20050206.png}} ::チャンネル数 :::モノラル・ステレオの表現で使います。モノラルの場合は1、ステレオの場合は2です。この数分だけ、音の波を複数持つことになります。 ::サンプリングレート :::実際は「Hz/sec」という周波数単位で表現されています。samples/secです。1秒間に何回のサンプリングを行うか、というのを表します。44.1kHzの場合は44100回のサンプリングを行います。これが大きいほど、精度が高くなります。 ::サンプリングサイズ :::1サンプルにおける精度を表現するビット数(bits/sample)です。Wave形式では、8ビットと16ビットが一般的です。上記の図では-1.0〜+1.0ですが、これを1バイトまたは2バイトで「振幅」を表現することになります。 上記の図を考えると、「サンプリングサイズ x サンプリングレート x チャンネル数」が 1秒間に転送する情報となり、これをbps(bits/sec)で表します。このbpsを「ビットレート」と言います。 CD音質の場合は、「44100 x 16 x 2 = 1411200bps(約1400kbps)」となります。バイトに直すと176400 bytes/secとなります。 さて、DirectSoundの「WAVEFORMATEX」構造体にてこれの情報を設定することになりますが 関係としては以下のようになります。 ,構造体変数名,意味 ,wFormatTag,WAVE_FORMAT_PCM ,nChannels,チャンネル数 ,nSamplesPerSec,サンプリングレート(Hz/sec) ,wBitsPerSample,サンプリングサイズ(bits/sample) ,nBlockAlign,nCannels * (wBitsPerSample / 8) ,nAvgBytesPerSec,平均データ転送速度(bytes/sec)。nBlockAlign * nSamplesPerSec nBlockAlign/nAvgBytesPerSecは、バイト単位で扱っている点に注意です。 「nAvgBytesPerSec * 8」がビットレートを表します。 話変わってmp3では 標準で128kbpsのビットレートを持つのですが、 CD音質(約1400kbps)よりもはるかに少ないです。 逆算してサンプリングレートが4kHz/secくらいで表現できるのか(128kbps / 16bit / 2ch)、 と思われるかもしれないですが これではとてもでないけど音の再生は不可能です。 どうしているのかというと、あらかじめ圧縮した音をリアルタイムで解凍・再生してるんですね。 Wave形式はベタですので膨大な量となるわけです。 これで、mp3ではサンプリングレートやサンプリングサイズで表現しない 訳が理解できます。 (128kbpsの転送速度までだいたいで圧縮するようにしている、といった感じでしょうか) 考えてみると、ステレオ(2チャンネル)の場合は似通った部分が多いですので 圧縮は効くはず、また時間軸上で見て変化の少ない部分(振幅の少ない部分)は 最適化できるはずですので、 DirectSoundでのストリーミングでは(ベタWaveっぽいので)圧縮して転送するなどの 効率化は必要かもしれませんね。 !!DirectSound(2005/2/5) ちょっと新しいことにもチャレンジしよう、ということで 新プロジェクトのためにDirectSoundをいじりました。 ということで、ひさびさにDirectXを触ってます。 DirectXの中の一機能ですが、サウンド周りは 昔のDirectXからあまり仕様が変わってないですね。 (いかに3D(DirectX Graphics)が重宝されているかが分かります。 DirectSoundのサンプルってDX8から変わってないし(^_^;;) で、DirectSoundの機能としては 音を出す(相変わらずWaveの解析は自前で)、 ミキシング・エフェクト、そして録音のためのキャプチャに分かれます。 で、私のやりたいのはストリーミングだったりしますが、 ずばりに近いサンプル「fullduplexfilter」が有効そうです。 これをWinSockでつなぐと あっという間にIP電話ができ、 電話代の節約になるわけですねぇ、うんうん。 (すでに既存のメッセンジャーとかがあるやん、 とも思われる方があるかと思いますが、 そこを自前で開発するというのが醍醐味なわけで・・・もちろん、 ただ単にIP電話を実現するというのが目標ではないっす) とはいえ、DirectXはブラックボックス化された部分が 多いですので、例えばミキシングなどは自前で行ったほうが 効率がいい場合もあるかもしれません(ハードウェアが効いているのなら 別ですが、特にストリーミングの場合は送る前に独自圧縮したい場合があります)。 とりあえず、DirectSoundがネットワークのトラフィックなども加味した場合に ストリーミングに使えるのか、などなどいろいろ検証してみようと思います。 ちなみに、このためにマイク買いました (昔のSoundBlaster付属のマイクが壊れているようで使えなかったため)。 カラオケとか司会にも使えそうなダイナミックマイクです。 歌いながら実験するかぁ。 リアルタイムストリーミングでボイスチェンジとかできても楽しそうですし。 !!セレクティブレイトレース その2(2005/2/3) 先日、格段に速くなると豪語したセレクティブレイトレースですが、 29秒のが25秒に・・・ってあんまり変わらない・・・(2/2の日記にある平面に反射する球を敷き詰めたやつね)。 これは、全体的な反射と面光源(サンプリング数10)を 使っていたというのが影響してました。 GIだと全体に占める一次レイの走査の割合は少なくなるので セレクティブレイトレのインパクトは薄いですね。 で、別途面光源を高速化できないかということでいろいろ試してみたのですが、 シャドウマップが一番品質と速度共に確保しやすく感じました。 しかし、メモリを食うのと広大なシーンでは ボケボケになりますので別のアルゴリズムを考案中です。 理論は固まったのですが画質はまだいまいち。まだ研究の余地ありですが 手応えはありそうです。 実装すると、25秒のが11秒くらいに短縮できました。 面光源の影のエッジは緩やかになる傾向が強いため、補間が有効なはず。 というのを切り口にしてシャドウマップでないノイズのない面光源の影、 ぜひ実現したいところです。 !!セレクティブレイトレース(2005/2/2) 日記でちらっと話題にしていたのですが、改めて実装中ですので記載。 セレクティブレイトレースとは、レイトレースするときに一次レイを「はしょる」 ことにより高速化を図る手段です。 この一次レイを求めるときに、スキャンラインまたはZバッファで 「オブジェクト番号・ポリゴン番号・Z値」によって塗りつぶします(これはラスタライズ的に)。 それを色つきで可視化したもの。 {{ref_image sr_base_20050202.jpg}} 上記は64x64ピクセルのブロックごとに処理しているため、メモリとしては 最大64x64ピクセル分を保持するといいことになります (レンダリング画像全体だとさすがにメモリを食いますので)。 Zバッファで書いています。 ここのバッファに存在するピクセルは、「そのオブジェクト番号・ポリゴン番号」 の組み合わせでのみ交差判定を行えばいいことになり、反射・透過しない物体の レイトレースでは格段に速度アップします(実際、レイトレースしてないわけですし)。 2次レイ以降は普通のレイトレースになります。 以下、レイトレースの最終結果と合成してみました。 {{ref_image sr_20050202.jpg}} この手法の場合、込み入ったシーンほど速度アップが見込まれます。 これは、CALLISTOとShadeでテストしてみると一目瞭然で違いが分かると思います (複雑になればなるほど。例えば枝が多数分かれている木とか、髪の毛を ポリゴンで作ってレイトレレンダリングするとわかりやすいです)。 ただ、GIになるとすべてが反射するようなものですので効果が薄いです。 ですが、少しは足しにはなるかなぁ。 問題はアンチエイリアスの処理なんですが、これは基本はオーバーサンプリングで 行うといいと思います。 アンチ処理ではちょっと複雑にはなりますね。 ちなみに、上記画像は48002ポリゴンのシーンで320x240pixelのセレクティブレイトレースで、 このZバッファ描画の前処理は800ms程度(Athlon 1100MHzのWin2000にて)、 と負荷は無視できるレベルです。 このために、BMPにブロック書き出しするルーチンを作って組み込んでみました。 それ込みで(ブロックごとのアフィン変換・ファイル書き出し込みで)800msなんで 実用には使えそうですね。 (ブロックごとにいちいち計算を発生させるので遅いかと思ったけど大丈夫みたい) たぶんですが、CarraraとかMentalRayとかって このタイプかなぁと思って まねてます(^_^;;。