2009年12月10日木曜日

リアルタイムレイトレーシング事始め

Check
『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;
    }

0 件のコメント:

コメントを投稿