!!!実装の手順 実際に「レンダリング画像」を得るまでの手順はだいたい以下のような感じでしょうか。 なお、「レイトレーシング」というと球を配置する(球の式で交点計算)というスタンダードな例が ありますが、ここでは「ポリゴン」でシーンを構成するものとして考えていきます。 *オブジェクトをシーンに配置する *視点をシーンに配置する *光源をシーンに配置する *オブジェクトとの交差判定 *光源計算(放射照度計算) 以下、順を追って説明していきます。 ちなみに「レイトレーシング」というのは逆光線追跡法(視点からレイをたどる)という直接照明のみを考慮したレンダリング手法という感じで言われますが、 「レイトレースする」となると視点からレイをとばして、といった行為を指したりしますので、グローバルイルミネーションのような間接照明を求める場合でもレイトレース処理は行われます(レイトレーシングの拡張がグローバルイルミネーションでのレンダリングに結びつく)。 !!オブジェクトをシーンに配置する まずは物体なくしては始まりません。 シーン上に物体を配置します。ちなみに、オブジェクト・視点・光源を配置する 空間のことを「'''シーン'''」と言い、その座標系を「'''ワールド座標系'''」と いいます。 {{ref_image world_20040821.png}} 上記はよく使われる「ワールド座標」です。Z軸が手前になっていて「右手系」と いいます。「右手」とは親指をX・人差し指をY・中指をZに見立てて直交させたときに 上記のような座標が得られる手です(右手になる)。 逆にZ軸が奥に向く座標系は「左手系」になります。DirectXの世界では左手系になります。 ここではワールド座標は右手系で考えていきます。 ワールド座標上では一般的に小数点の座標で位置を表します。(x, y, z) = (0.0, 0.0, 0.0)のときはワールド座標の中心位置です。 オブジェクトのみでなく、視点・光源もこの空間上に配置することになります。 で、オブジェクトはポリゴンで構成されるわけですが、ここでは「ポリゴン=三角形」で考えます。3つの辺のある図形ですね。多角形ポリゴン(3辺以上のもの)の場合は分割します。 {{ref_image polygon_20040821.png}} レンダラでは「三角形でポリゴンを表現する」というのが多いです。多角形のままではあまり扱いません(普通はレンダラにわたるときに三角形に分解される)。というのも三角形は交差判定を行うときに効率がいいからです。 ちなみに「'''ポリゴン'''」とは頂点座標を持つ多角形のことをあらわします。 上記の図の場合A〜Eの5つの頂点があり、「A-B-Eで面0」「E-B-Dで面1」「D-B-Cで面2」の3つの三角形に分解されることが分かります。 球や人や車や・・・すべてのオブジェクトはこのポリゴン(ここでは三角形)で構成されています。 オブジェクトのポリゴン情報だけでは色も何もない「形状」でしかないのですが、物体ごとに「'''マテリアル'''」(Shadeで言う表面材質)というものが割り当てられます。 これはおいおい説明していきましょう。 !!視点をシーンに配置する シーン上にオブジェクトが配置されたとして、最終的にレンダリング画像を求めるときには「見る位置」が必要です。これが視点になります。 視点では、「視点位置(ワールド座標上の位置)」と「視線ベクトル(視線方向)」が与えられて初めてどこを見ているか、というのが判断できます。視線ベクトルは単位ベクトル(長さが1のベクトル)に正規化されます。この視点・視線のことを「レイ」と呼んだりします。 レイトレーシングでは、その視線方向に仮想的なスクリーンを配置し、このスクリーン上の2次元での(x, y)位置にレイを飛ばしてその左記に物体がある場合は交差判定処理を行うことになります。この2次元スクリーンでの1ピクセルごとの最終的な色計算をX * Y分繰り返すとレンダリング画像が得られるわけです。 {{ref_image eye_20040821.png}} 視点情報はこれ以外に「スクリーンサイズ(レンダリング画像のサイズ)」「視点からスクリーンまでの距離」「視野角」などがあります。 !!光源をシーンに配置する 「光源」とは読んで字のごとく光の元となる情報です。これもシーン上に配置することになります。詳しいことは別で書きますが、大きく分けて「平行光源」「点光源」「スポットライト」「面光源(エリアライト)」に分類することが多いです。 太陽のような遠くにあるのでほぼ全方向に同じ向きから届く光を「平行光源」、ある一点から放射される光を「点光源」、点光源に角度制限がついたものを「スポットライト」、面(ポリゴン)から一度に放射される光を「面光源」と言ってます。 現実世界では太陽も遠くの位置にある点と見ることができ(実際は球状の面光源の集まりですけど)、点光源・スポットライトは点、面光源も点光源の集まり、ということで点光源のみで世界を表現できそうではあります。が、これは物体をポリゴンの集まりで表現しているのと同様にそんなルールと思ってください。 !!オブジェクトとの[[交差判定|交差判定_3DCG]] 視点のとこでチラッと説明しましたが、視点からレイをスクリーンに対してとばしてオブジェクトとの交差判定を行います。 ここで、シーン上のポリゴンとレイとの交差判定を行い、視点から距離が一番近いポリゴンを求めます。 シーン上に総ポリゴン数が10000個あるとすると、単純に言うと10000回の交差判定処理を行い、視点から一番近いポリゴンを検索していきます。 実際はスクリーンが640 x 480 Pixelとすると、10000 x (640 x 480)回の交差判定が必要になってしまう、ということが分かるでしょうか。 しかも、物体表面で反射でもしようものならこれの何乗という交差判定が必要になってしまいます。これではいくら時間があっても足りませんね。 ですので、「最適化」と称して「空間分割」や「バウンディングボリューム」を行って交差判定をはしょります。 実はレイトレーシング(基本的なレイトレだけではなくグローバルイルミネーションなどの方法でも)では、この交差判定の負荷が一番高いです(レンダリング時間全体の8割近くを占める、らしい)。 レンダリングで数時間待たされる、などの場合でもひたすらこの計算が行われていることになります。なんで、最適化がいかに大事かというのが身にしみてわかる部分でもあります。 !!光源計算(放射照度計算) レイを飛ばした位置でポリゴンと交わると、その交点位置と法線ベクトル(ポリゴンから垂直に出ている単位ベクトル)が判明します。これと光源情報を元に放射照度を計算することができます。 また、影を計算する場合は交点位置と光源との間に物体があれば影になる、とできます(ここでも交差判定処理が発生)。 また、オブジェクトに割り当てられた「マテリアル」情報にて色やテクスチャを考慮して最終的なその交点での色が求まります。 レイがぶつかったポリゴンにて、鏡面反射や屈折などが行われる場合はさらに「二次レイ」を今度は交点座標から飛ばしてレイトレースを繰り返すことになります。 グローバルイルミネーションの場合は、交点から複数のレイを飛ばすことがあるでしょう。 {{ref_image raytrace_20040821.png}} そんな感じで、交差判定と光源計算は繰り返されて最終的な「レイとスクリーンの交わった2次元位置でのピクセル色」を累積していきます。いわば、スクリーンに対し投影することになりますね。これをスクリーンピクセル数分繰り返す(アンチエイリアスする場合は、ピクセル同士の間の小数点以下のレイもたどりますのでさらに増えます)ことになります。 これがだいたいのレイトレーシングのアルゴリズムとなります。