2012-03-25 14 views
1

私は学習の練習として単純なボクセルレイキャスターを書こうとしています。これは純粋にCPUをベースにしています。今のところ、どのように動作するかを理解するまでは、OpenGLは単に生成されたビットマップを可能な限り頻繁にブリットするために使用されています。歪んだ:単純なCPUベースのボクセルレイキャスター/レイトレーサーの回転カメラ

私は遠近投影カメラが世界を動かすことができるようになりました。私は、「世界」の3次元視点を遠近法で正確に(現在は調査が必要なアーティファクトを除いて)レンダリングできます。基本的に空ですが、Stanford Bunnyのボクセルキューブを含んでいます。

私はカメラを持っていますので、上下左右にずらして前後に歩くことができます。すべての軸は今まで通り、カメラの回転はありません。ここに私の問題があります。

スクリーンショット:(1) raycasting voxels while......(2) the camera remains......(3) strictly axis-aligned.

は今、私は数日のために働く回転を取得しようとしています。理論上の行列と3D回転の基本的な論理と理論は、私には非常に明確です。しかし、カメラが回転すると「2.5レンダリング」しか達成できませんでした。Google Streetviewのような魚眼では、ボリュームメトリックな世界表現を持っていても、最初に「正面図」からレンダリングを作成し、次にカメラの回転に従ってその平坦なレンダリングを回転させます。言うまでもなく、私は、回転する光線が特に必要ではなく、エラーを起こしやすいことを認識しています。

はまだ、私の最も最近のセットアップでは、最も単純化されたレイキャスト線位置と方向のアルゴリズム可能で、私の回転がまだ同じ魚eyeyフラットレンダリング回転スタイルが見え生産:

camera "rotated to the right by 39 degrees" - - この回転では、スクリーン#2の立方体の青い影付きの左側がどのように見えているのか、今は "本当にすべき"ことに注意してください。

もちろん私はこれを知っています:最初に持っていたような簡単な軸 - 整列 - 回転設定では、光線は小さなステップで正のz方向を単に横切って左に発散しますまたはピクセルの位置および投影行列に応じて右および上または下にのみ移動する。私は "カメラを右または左に回転させる" - すなわち、私はそれをY軸の周りに回転させる - それらの非常に踏み込んだステップは、適切な回転行列で簡単に変換する必要があります。したがって、順方向のトラバーサルの場合、Zステップは、カムが回転するほど小さくなり、Xステップの「増加」によって相殺されます。しかし、画素位置ベースの水平+垂直発散については、xステップの増加分をzステップに「加算」する必要があります。何とか、私が実験した多くの行列のどれも、行列のないハードコードの冗長なsin/cos計算を使った私の実験でも、実際にこの部分を正しく取得することはできません。

  • FX年度:ピクセル位置xとy
  • rayPosゴーで構文が、擬似コードとしてそれを取る -

    は、ここに私の基本的なにつき線前トラバーサルアルゴリズムです:ワールド空間での光線開始位置のvec3(下に計算されます)

  • rayDir:各ステップでrayPosにxyz-stepsを追加するvec3線トラバーサル
  • rayStep一時vec3
  • カンポス:ワールド空間内のカメラ位置のvec3
  • camRad:ラジアンカメラ回転用vec3
  • PMAT:典型的な透視投影マトリックス

アルゴリズム/擬似コード:

// 1: rayPos is for now "this pixel, as a vector on the view plane in 3d, at The Origin" 
rayPos.X, rayPos.Y, rayPos.Z = ((fx/width) - 0.5), ((fy/height) - 0.5), 0 

// 2: rotate around Y axis depending on cam rotation. No prob since view plane still at Origin 0,0,0 
rayPos.MultMat(num.NewDmat4RotationY(camRad.Y)) 

// 3: a temp vec3. planeDist is -0.15 or some such -- fov-based dist of view plane from eye and also the non-normalized, "in axis-aligned world" traversal step size "forward into the screen" 
rayStep.X, rayStep.Y, rayStep.Z = 0, 0, planeDist 

// 4: rotate this too -- 0,zstep should become some meaningful xzstep,xzstep 
rayStep.MultMat(num.NewDmat4RotationY(CamRad.Y)) 

// set up direction vector from still-origin-based-ray-position-off-rotated-view-plane plus rotated-zstep-vector 
rayDir.X, rayDir.Y, rayDir.Z = -rayPos.X - me.rayStep.X, -rayPos.Y, rayPos.Z + rayStep.Z 

// perspective projection 
rayDir.Normalize() 
rayDir.MultMat(pmat) 

// before traversal, the ray starting position has to be transformed from origin-relative to campos-relative 
rayPos.Add(camPos) 

Iはトラバーサルをスキップし、部品をサンプリングいる - それらが、「基本的にほとんど正しい」(きれいではないが)であり、スクリーン#1に従って#3を介して - たときに軸整列/非回転。

答えて

4

システムを他のものよりピンホールカメラとして描写する方がずっと簡単です。あなたのイメージを表す長方形の表面から光線を射る代わりに、あなたのイメージ・プレーンになる矩形を通して、光線をある場所からシーンに射します。全ての主光線は、わずかに異なる方向のみで、同じ起点を持つはずです。方向は、イメージプレーン内のピクセルを通過させる基本トリグを使用して決定されます。最も簡単な例を作るために、ポイントがカメラにあり、イメージプレーンがz軸に沿って1つの単位であり、2つの単位が高さと幅であるとします。このようにして、左上隅のピクセルは(0,0,0)から(-1、-1,1)に移動します。方向を取得するには、(-1、-1、1)を正規化します。 (実際には、光線交差を行うために方向を正規化する必要はありませんが、そうでない場合は、光線が移動した距離などを計算する前に方向が正規化されていないことを忘れないでください)。他のすべてのピクセルでは、プレーンのサイズを各方向のピクセル数で割って、既に行っていた方法で移動したい平面上の点を計算します。

次に、これが最も重要なことです。はありません透視投影を試みてください。スキャン変換テクニックでは、すべての頂点を画面上のあるポイントにマッピングする必要がありますが、レイトレーシングでは、あるポイントから1つのスペースに広がるだけでレイを達成します。始点(カメラ位置、この例では原点)からイメージプレーンを通る方向は、正確にトレースする必要がある方向です。代わりに正射投影を望むなら、これはほとんど望みませんが、すべての光線で方向を同じにすることでこれを達成できます。開始位置はイメージ平面全体で異なります。

これを行うと、良い出発点が得られます。次に、カメラの回転を追加するには、反復処理の前に原点を中心にイメージプレーンを回転して、光線の方向を計算するか、光線の方向を直接回転させます。直接方向を回転させることには何も問題ありません。方向が、原点から始まる場合にはあなたの光線が通過する位置にすぎないことに留意すると、方向を回転させ、それが通過する点を回転させることはまったく同じことを見るのは簡単です。

関連する問題