2020年2月17日月曜日

小ネタ

 社名:Satellite System Solutions Co., Ltd.
 事業内容:主に宇宙関連機器のソフトウェアの開発を行っているベンチャー企業。
 口コミ:時々中の人が「死んだ世界戦線」や「天使」といった言葉を使っている。よほどスケジュール管理のヤバいブラック企業のようだ。

 と、いうネタを思いついたのだがいかがだろうか(おい

 ぐぐったら、NECとかInmarsatとかの事業内容紹介が出てくるけど、社名とかでこの名前を使ってるところはなさそう。はやいものがち!だれか!!
 やりたいこと一通りやったら消えて無くなりそう。そのためにも次々と新しい目標を作って…… あれ?ブラック一直線コース?

***

 試しに面の塗りつぶしを実装してみた。



 デプスの計算を、頂点の平均で作ってるので、アンテナの面に背後の筐体の色が出てしまってる。が、それ以外は特に問題なく書けてる。頂点の平均、思ったより性能良さそう。表面の凹凸が激しい物体がめり込むような状況だと厳しいけど、シンプルな形状がある程度の隙間で並んでるなら、あんまり厳密に前後判定しなくても良さそう。
 三角形の塗りつぶしアルゴリズムが難解すぎて、とりあえず外接する四角をforで回して、当該ピクセルがポリゴンの中にあるかを判定する、という処理をやってる。これまた結構パフォーマンス出てびっくりしてる。せいぜい20ポリ有るかないかくらいで小さな画面1枚書くのに100msecかかってるし、ちょっと画像大きくしたらものすごい時間かかるので、全然実用的じゃないけど。GPUってすげーんだな、とか思ったり。3Dゲームとかで遊んでて「全然フレームレートでねーじゃねーか!」とか怒って悪かったな。。。

 処理としては、頂点シェーダ的なプリプロセスで画面座標に変換して、裏面のポリは除外してキューに突っ込んで、続いてピクセルシェーダ的なプロセスで、実際に塗りつぶしを行ってる。
 おそらくピクセルの書き込みに時間がかかってるので、頂点シェーダで外接矩形の計算までやって、矩形が重ならない部分を選んで並列処理で回す、みたいなことをやれば、2倍位は早くなるはず。とはいえ、普通にforeachで回すと、矩形が重ならない部分を優先的に取り出す、みたいな処理はできないわけだが。
 レンダリングバッファ3枚分くらい用意してスレッドごとに自分のバッファに書き込んで、最終的にデプスバッファで比較しながら1枚にまとめる、あたりが落としどころかなぁ。
 早いところちゃんとしたレンダリングエンジンに移行しろよ、という気もするが。

 そーいえば、XNAで遊んでたときも、普通にサンプルプログラム走らせるだけだとポリゴンの深度が考慮されなくて、前後が破綻してたっけ。あれがVisual Studio 2008とかのはずだから、もう10年も前になるのか。ゲゲ、あの頃からやってること変わらんのか。。。

***

 面が塗れるようになれば、太陽位置を計算して、ポリの法線ベクトルとの内積から輝度を調整すれば、陰影処理が動くようになるんだよな。
 もっとも、20ポリ前後でも速度ギリギリなので、球体みたいなポリ数の多い物体をレンダリングすると悲惨なことになりそうだけど。
 うーん、まともなレンダリングエンジンが使いたくなってきたぞ……

 30年くらい前のアーケード機が、これくらいの機能だったっぽいですね。テクスチャなし、ポリ単位で色つけたり陰影処理したり。向こうのほうがポリ数多いしボーン入れて動かせる分高性能か。

 今の所、classで構造作ってインスタンス作ったり壊したりを大量にやってるので、多分そのあたりがネックになってるはず。ある程度調整するだけでも数倍は早くなるはず。ということで、もうちょっとリファクタリングしてみる。
 軌道計算周り全然手つけてないな。。。

***
追記
 だいぶ早くなった。思ってたところと違うところがネックだったけど。



 前後関係が適切に表示されるだけで大幅に現実感が出てくる。

 ワイヤーは、面倒なので幅1pxに固定してしまった。気が向いたらどうにかしたい。
 ワイヤーと、ワイヤーポリ(輪郭だけレンダリング)は、かなり軽量な処理。面はやはりかなり時間がかかる。地球の陰影をやろうとすると、画面の大部分の塗りつぶしが必要だから、相当高カロリーな処理になりそう。
 衛星とか重要なオブジェクトだけ単色で塗りつぶして、他はワイヤーで表示が落とし所かなぁ。
 やっぱりちゃんとしたレンダリングエンジン使うべきか。。。(はやく軌道計算やれ

***
追記
 画面座標で手前方向のベクトルとの内積を取って色を暗くしてみた。



 球体の中心部は明るく、周囲は暗くなっているのがわかる。
 あと、極付近にポリを貼ってないので向こう側が透けて見える。リソースケチった3Dでよくあるやつだ!!(極にポリを貼ってないのはリソースじゃなくて特異点の問題)


 ワールド座標との内積だと、こんな感じ



 画面左上の方向から光が届いてるようなイメージ。パラメーター調整を注意しないと、真っ黒だったり真っ白だったりになってしまう。

 光源と視線の双方との内積をうまく組み合わせれば、光沢のような質感や、つや消しな質感も作れる。はず。

 ぐりぐり動かしてるとなんか違和感あるので、どっかバグってそう。
 やっぱり付け焼き刃で作ったエンジンだと不具合マシマシだなぁ。。。

***
追記
 やっと照明がちゃんと動くようになってきた。



 見づらいけど、衛星の各面が球体と同じように照明されてる。
 いままで、ローカル座標のポリゴンを一気に画面座標に変換してキューに入れてたけど、一旦グローバル座標を経由するようにした。まぁ、そうだよな。。。
 グローバル座標で法線ベクトルを計算して、グローバル座標での視線ベクトルとの内積から裏表を判定して、裏面は捨てるようにしている。
 最終的に、キューから1枚ずつ読み出して、それを画面座標に変換してから、描画処理を行っている。その際に、色がRGB888で指定されているので、グローバル座標の平行光ベクトルとの内積から、RGBの輝度を調整している。

 今の所、光源はグローバルに平行光を1個しか配置できない。
 特定のグループにのみ影響する光源とかが作れれば、例えばロケットのノズルの中だけ照明する、みたいな表現ができるけど、今の所そういう表現はできない。ポリゴンの色を変えれば似たようなエフェクトは作れるので、とりあえずグローバルの照明1個でいいかな、と思ってる。

 とりあえず、今は光線ベクトルは固定だけど、可変にすれば、自転や公転による光線の変化が表現できるようになる。他にも、光線ベクトルの長さを変えれば、明るくしたり暗くしたりもできるようになる。
 平行光だけでなく、拡散光(全周から同じ強度で当たる光)も加えれば、適当な陰影も調整できるはず。
 ということで、そのあたりまでやれば、3D周りはある程度終わりかな。いよいよ軌道計算に手を付けることになる(フラグ

***

 ここ最近、生活サイクルのジッターが激しい。数hour/dayくらいのレートで遅れていってる。せっかくだし1周させて位相合わせたい。

0 件のコメント:

コメントを投稿