『Javaではじめるレイトレーシング入門』という面白い書籍を見つけたので、レイトレーシングに挑戦。大まかな仕組みをつかんだところで、C++で書き起こしてみることに。先生にお借りした
『CによるCGレイトレーシング』がかなり参考になった。
とりあえず、カメラとスクリーンはワールド空間に固定して、球体を描画。シェーディングはランバートで。画素数は500*500です。
我が家のポンコツマシン(Northwood Celeron 2.4GHz)で実行したところ、Debugで600ミリ秒、Releaseで93ミリ秒というなんとも情けない結果に終わった。FPS換算だと1~10FPSとかちょっと…。というかまだオブジェクト1個だし、屈折とかテクスチャリングとかやってないし!
言い訳すると有り合わせのクラスをパチ組みしただけなので、無駄な呼び出しというか、OOPっぽい書き方になってるのが遅れの原因か。ローカルに作ったワーク変数が、空のコンストラクタを呼び出してたりいろいろ無駄がありそう。
とはいえ、一番の原因はアルゴリズム部分でしょうね。きっとまだ無駄な判定やってるに違いない、今から見なおそう。
TODO:
飽和加算とか。
<追記 2009.12.10@2:10am>
320*240で10fps@Debug, 60fps@Releaseを達成できました。
500*500は3fps@Debug, 13fps@Releaseが今のところ限界…。
ベクトルの正規化がかなり足を引っ張っていたようです。0割防止のため、ノルムが0の時は割り算を行わないという処理をやっていたのですが…。
Vector3 &Vector3::normalize()
{
float len = x*x+y*y+z*z;//ノルムの平方
//以下len = sqrt(len);と同じ
__asm{
fld len
fsqrt
fstp len//お行儀が悪いがlenを使いまわす
}
//0割防止
if(len < FLT_EPSILON){
x=y=z=0;
}
else{
float denom = 1.f / len;
x *= denom;
y *= denom;
z *= denom;
}
return *this;
}
上記のif文の評価式をlen >= EPSILONにして、ブロックを入れ替えた方がジャンプが減る分確率的に速くなる…気がする。てかここでごっそり速くなった。
if(len >= FLT_EPSILON){
float denom = 1.f / len;
x *= denom;
y *= denom;
z *= denom;
}
else{
x=y=z=0;
}