LITTLE CLAP ゲーム製作日記 -2ページ目

FLASHによるソフトウェアレンダリング その1

 1ピクセル単位で描画するソフトウェアレンダリングに挑戦しています。

 マウスでドラッグすると回転します。「FULL」ボタンを押すとフルスクリーンになり、もう一度押すと戻ります。


 勤め先で開発している某3D洋服作成ソフトのデータを拝借しました。2万ポリゴンもあるのでちょっと読み込みに時間がかかります、プリローダが必要ですね。
 FlashのGraphicsクラスで大量のポリゴンを描画すると、どうも頂点単位の演算で負荷がかかりすぎているようです。1ポリゴンあたりの描画面積が小さいならVector.<int>に自前で描画してBitmapData.setVectorで一括出力した方が早そうです。
 詳しい進捗はこちら(FC2内のマイページ) で。

int型の掛け算

 ActionScript3.0とC++(またはJava)で、今度は掛け算の演算結果が異なる現象に出くわしました。

 ゲームのデモシーンやデータの暗号化等で、しばしば再現性のある擬似乱数が必要になることがあります。再現すれば値は何でもいいという感じなので乗算結果がオーバーフローした分は捨てていたのですが、C++で作成したデータがActionScript3.0で読み込めなくなりました。デバッガで値を確認してみると…

var a:int = 0x12345678;
var b:int = 0xabcdef01;
var c:int;
c = a * b + a;

C++ 1731900672 [0x673AB500]
AS3 1731900656 [0x673AB4F0]

 結果が異なります。当然データの再現には失敗します。
 面白いことに、乗算した結果をそのまま変数に代入すると同一の結果が得られます。どうも、結果を即座にint型で得なかった時点でdouble型へ自動的にキャストされているようです。確かにdoubleの方が有効桁数が多いので通常の演算ならありがたいのですが、そのために下位ビットが桁落ちしてしまっては用が足せません。
 割り算のとき も思いましたが、把握できていないキャストが発生すると大混乱です。

ウォークスルーの素材製作

 FLASHでウォークスルーを表示するための素材を作成しています。

LITTLE CLAP ゲーム製作日記-ウォークスルー素材製作1
※動きません

 なかなか難しいです。テクスチャを貼っていないと凄く味気ないですね。
 まだ各面の頂点を真面目に共有していないので、所々隙間が開いています。

直方体部屋のテクスチャ

 FLASHのウォークスルーのために光源処理を焼き付けたテクスチャを作成したいのですが、どうすれば作れるんでしょうか。

 縦3メートル、横4メートル、高さ2メートルの何もない直方体の部屋を想定し、そこへ貼り付けるテクスチャを考えてみます。
LITTLE CLAP ゲーム製作日記-直方体部屋のテクスチャ1 テクスチャなし

 正面は部屋の天井に(計算しやすいよう1cm下に)、点光源を想定します。そしてテクスチャの各テクセルがどんな明るさを持つかを計算します。XY平面に平行な面から光源へのベクトルをx,y,zとします。



 まずは光源から離れている場所ほど暗くなるだろうということで、
テクセルの明るさ = 照明光度 ÷ sqrt(x*x+y*y+z*z)
 求めた明るさを元に天井、床、正面壁、横壁の順に配置します。

LITTLE CLAP ゲーム製作日記-直方体部屋のテクスチャ2 配置図

 作成したテクスチャをポリゴンモデルに貼り付けます。

LITTLE CLAP ゲーム製作日記-直方体部屋のテクスチャ3 光源からの距離

 一発でそれっぽい映像になりましたが、天井は光源からの距離が近いため真っ白です。



 光源を正面に捕らえる面は明るく、そうでない面は暗くなるはずです。法線計算時に距離による割り算が発生するため、sqrtが外れてくれます。
テクセルの明るさ = 照明光度 × z ÷ x*x+y*y+z*z
LITTLE CLAP ゲーム製作日記-直方体部屋のテクスチャ4 光源方向と面法線

 中心部以外の天井は光源に対して垂直であるため、真っ黒です。

 一度壁に当たった光は反射して他の壁にも当たるはずです。例えば床は400×300テクセルで構成され、そこから反射した光を300×200テクセルの壁に適用させる、となると合計72億回の演算が必要になります。
 別にラジオシティがやりたいわけではないのでそこは大幅カット。面の中心に全光量が集中していると乱暴に考えて次のステップへ進みます。



 壁4枚と床1枚が新たな光源となり、全6面へ同様に光を当てます。ただし一点の集中させたとはいえ本来は面光源であり、光源面法線と対象面法線の内積を求めてから光量を乗算し、距離で割ります。
UVに対してu方向の壁光源を適用する場合
dis2 = dx*dx+dy*dy+dz*dz
テクセルの明るさ += 照明光度 × z ÷ dis2 × fabs(x ÷ sqrt(dis2))
LITTLE CLAP ゲーム製作日記-直方体部屋のテクスチャ5 他の壁床からの反射

 だいたいこんな感じでしょうか。
 5年前のノートPCを使用し、このテクスチャを生成するのに0.2秒ほどかかりました。動的生成でもなんとかなる処理負荷です。
 ドアも机もない直方体だけの部屋なんて利用価値があるとも思えませんけどね。何かこう、淡々とモデルを作っただけでUV展開からアンビエントオークルージョンまで全自動でやってくれるような、そんなツールが欲しくなります。

FLASHによるウォークスルー その1

 ゲームのように仮想空間内を自由に歩きまわれる「ウォークスルー」に挑戦しています。

 行きたい場所にマウスポインタを置く感覚で操作します。「FULL」ボタンを押すとフルスクリーンになり、もう一度押すと戻ります。


 FLASHの表示はやっぱり重いです。なるべく軽く動作するように、思い切った機能の取捨選択をしなければなりません。とりあえず光源処理はなしの方向でいきます。
 詳しい進捗はこちら(FC2内のマイページ) で。