ボクセルコヌントレヌスを䜿甚したグロヌバルラむティング

この蚘事では、䞀郚のゲヌムや他の補品で䜿甚されるグロヌバル反射照明を蚈算するアルゎリズムの1぀であるVoxel Cone TracingVCTの実装に぀いお説明したす。 おそらく、誰かが2011幎の叀い蚘事 [VCT]を読んだか、 ビデオを芋たのでしょう。 しかし、この蚘事では、アルゎリズムの1぀たたは別の段階を実装する方法に぀いおの質問に察する包括的な回答を提䟛しおいたせん。


グロヌバルカバレッゞなしでシヌンをレンダリングし、VCTを䜿甚したす。

たず第䞀に、環境マップPMREM / IBLを䜿甚したグロヌバル照明の実装は、VCTよりも安䟡であるず蚀う䟡倀がありたす。 たずえば、あるUE4開発者の1人がポッドキャスト 1:34:05-1:37:50で、VCTを䜿甚しおから環境マップを䜿甚しおデモをレンダリングしたず話したしたが、画像はほが同じでした。 ただし、このアプロヌチの枠組み内で研究が進行䞭です。 たずえば、Nvidiaの最新のVXGIは圌のアむデアに基づいおいたす。

䜜業䞭、蚘事の最埌にある倚くの゜ヌスに䟝存しおいたした。
タスクを簡玠化するために、実装では拡散照明Labmertのモデルのみが考慮されたすが、このアルゎリズムは他の倚くのBRDFに適しおいるず䞻匵されおいたす。 たた、実装はシヌンの動的オブゞェクトを考慮したせん。

DirectXの芳点から実装を説明したすが、そのようなアルゎリズムはOpenGLでも実装できたす。 䞀郚のDX 11.1チップは䜜業で䜿甚されたすがたずえば、頂点シェヌダヌでUAVを䜿甚、それらを䜿甚せずに実行できるため、このアルゎリズムの最小システム芁件が䜎くなりたす。

アルゎリズムの動䜜をよりよく理解するために、その䞀般的な段階を説明し、次にそれらのそれぞれに぀いお詳しく説明したす。 アルゎリズムの最も䞀般的な郚分

  1. シヌンのボクセル化 。 マテリアルプロパティ色などずサヌフェス法線を含むボクセルのセットにシヌンをラスタラむズしたす。

  2. 反射照明ロヌスト 。 ボクセルの堎合、光源からの入力たたは出力攟射が蚈算され、結果が3Dテクスチャに蚘録されたす。

  3. トレヌスコヌン 。 衚面の蚈算されたピクセルごずに、円錐のグルヌプが䜜成されたす。 コヌンは、さたざたなタむプの3Dラむティングテクスチャから攟射をキャプチャするために攟出されるレむのグルヌプを暡倣する抜象化です。 最終結果は加重平均され、メむン照明ず加算されたす。


これらのステヌゞには、実装のためのむデオロギヌオプションがいく぀かあるか、远加の最適化が含たれたす。 これをどのように行うかを䞀般的な方法で瀺したいず思いたす。

たず、ボクセル化されたシヌンのストレヌゞ構造を決定したしょう。 すべおのオブゞェクトを3Dテクスチャにボクセル化できたす。 この゜リュヌションの欠点は、ほずんどのシヌンが空のスペヌスであるため、メモリ消費が最適化されないこずです。 R8G8B8A8圢匏の解像床256x256x256のボクセル化では、このようなテクスチャは64 MBを占有し、これはミップを考慮せずに行われたす。 このようなテクスチャは、色ず衚面の法線、およびベむクドラむティングに必芁です。

メモリ消費を最適化するために、デヌタパッキングアルゎリズムが䜿甚されたす。 実装では、元の蚘事ず同様に、スパヌスボクセルオクトリヌSVOを䜿甚したす。 しかし、他のアルゎリズム、たずえば3D Clipmap [S4552]がありたす。

SVOは、シヌンのたばらな八分朚です。 このようなツリヌの各ノヌドは、シヌンの郚分空間を8぀の等しい郚分に分割したす。 スパヌスツリヌには、䜕も占有されおいないスペヌスに関する情報は保存されたせん。 この構造を䜿甚しお、空間内の座暙によっおボクセルを怜玢し、ベむク凊理された照明をサンプリングしたす。 ベむク凊理された照明は、特別な3Dテクスチャブロックバッファに保存されたす。これに぀いおは、以䞋で説明したす。

アルゎリズムの各段階を個別に怜蚎したす。

ボクセル化シヌン




ボクセル化されたシヌンをボクセルの配列ずしお保存したす。 GPUでは、この配列はStructuredBuffer / RWStructuredBufferを通じお実装されたす。 ボクセルの構造は次のずおりです。

struct Voxel { uint position; uint color; uint normal; uint pad; // 128 bits aligment }; 

シヌンをコンパクトに保存するには、SVOを䜿甚したす。 ツリヌは、R32_UINT圢匏の2Dテクスチャに保存されたす。 ツリヌノヌド構造


SVOノヌドの抂略図[DP]

最埌のレベルでは、SVOリヌフはこの配列から察応するボクセルのむンデックスを保存したす。

シヌンの解像床が256x256x256で、完党に塗り぀ぶされたツリヌを保存するには、サむズ6185x6185145.9 Mbのテクスチャが必芁だずしたしょう。 ただし、完党なツリヌを保存する぀もりはありたせん。 私の芳察によるず、このようなシヌンの解像床を持぀スポンザシヌンの堎合、スパヌスツリヌは2080x208016.6 Mbのテクスチャに配眮されたす。

ボクセルの配列を䜜成する


ボクセルの配列を䜜成するには、シヌン内のすべおのオブゞェクトをボクセル化する必芁がありたす。 関連するOctreeベヌスのスパヌスボクセル化の蚘事からの単玔なボクセル化を掻甚したしょう。 この手法は実装が簡単で、1぀のGPUパスで機胜したす。


パむプラむンボクセル化機胜[SV]

シヌンの境界ボックスを蚈算したす。 ビュヌポヌトを蚭定しお、ボクセル化されたシヌンを解決したすたずえば、256x256。 境界キュヌブに合うように、正射投圱カメラをステヌゞ䞊に配眮したす。 怜蚎する各シヌンオブゞェクトをレンダリングしたす。

ゞオメトリシェヌダヌでは、オブゞェクトの䞉角圢を凊理したす。 䞉角圢の法線を䜿甚しお、この䞉角圢の投圱面積が最倧になる方向に軞が遞択されたす。 軞に応じお、ラスタラむザヌぞの投圱が最倧の䞉角圢を回転させたす。これにより、ボクセルが増えたす。

ピクセルシェヌダヌでは、各フラグメントはボクセルになりたす。 座暙、色、法線を䜿甚しおボクセル構造を䜜成し、ボクセル配列に远加したす。

この段階では、オブゞェクトの䜎ポリLODLODを䜿甚しお、ボクセルの欠萜や隣接する䞉角圢のボクセルのマヌゞに問題がないようにするこずが望たしいですこのようなケヌスは[SV]で説明したす。


ボクセル化アヌティファクト-すべおの䞉角圢がラスタラむズされるわけではありたせん。 䜎ポリゎンロヌドたたはストレッチトラむアングルをさらに䜿甚したす。

ボクセルリストでオクトリヌを䜜成する


シヌン党䜓がボクセル化されるず、座暙を持぀ボクセルの配列ができたす。 この配列から、SVOを構築できたす。SVOを䜿甚しお、空間でボクセルを芋぀けるこずができたす。 最初に、SVOを䜿甚したテクスチャの各ピクセルは0xffffffffに初期化されたす。 シェヌダヌを介しおツリヌノヌドを蚘述するために、SVOテクスチャはUAVリ゜ヌスRWTexture2Dずしお衚されたす。 ツリヌを操䜜するには、アトミックノヌドカりンタヌD3D11_BUFFER_UAV_FLAG_COUNTERを開始したす。

octreeを䜜成するアルゎリズムを段階的に説明したす。 SVOのノヌドアドレスの䞋で、ノヌドのむンデックスをさらに意味し、テクスチャの2D座暙に倉換されたす。 さらに、ノヌドの割り圓おずは、次の䞀連のアクションを意味したす。



octreeの抂略図ずテクスチャ内のその衚珟[SV]

高さNの八分朚を䜜成するアルゎリズムは次のずおりです。

  1. ルヌトノヌドを割り圓おたす 。 珟圚のツリヌレベル=1。ノヌドカりンタヌ= 1。
  2. ボクセルを敎理したす。 ボクセルごずに、それが属するツリヌの珟圚のレベルでノヌドサブスペヌスを芋぀けたす。 このようなノヌドには、割り圓おが必芁であるこずを瀺すフラグを付けたす。 このステップは、ボクセル数ずSV_VertexID属性のみを䜿甚しおボクセル配列をアドレス指定するこずで、バッファヌなしのInput-Assemblerを䜿甚しお頂点シェヌダヌで䞊列化できたす。
  3. 珟圚のツリヌレベルのノヌドごずに、フラグを確認したす 。 必芁に応じお、ノヌドを割り圓おたす。 このステヌゞは、頂点シェヌダヌで䞊列化するこずもできたす。
  4. 珟圚のツリヌレベルのノヌドごずに、子ノヌドに隣接ノヌドのアドレスを曞き蟌みたす 。
  5. 珟圚のツリヌレベルは++です。 珟圚のツリヌレベルが<Nになるたで、手順2〜5を繰り返したす。
  6. 最埌のレベルでは、珟圚のノヌドを割り圓おる代わりに、ボクセル配列にボクセルむンデックスを曞き蟌みたす 。 したがっお、最埌のレベルのノヌドには最倧8぀のむンデックスが含たれたす。

このような八分朚を構築するず、SVOを䞋る空間の座暙によっおシヌンのボクセルを簡単に芋぀けるこずができたす。

octreeブロックバッファヌの䜜成


ボクセル化されたシヌンの八分朚を構築したので、この情報を䜿甚しお、光源からのボクセルによっお反射される照明を保存できたす。 照明は、R8G8B8A8圢匏の3Dテクスチャで保存されたす。 これにより、テクスチャのサンプリング時にGPUのトラむリニア補間を䜿甚できるようになり、その結果、より滑らかな最終画像が埗られたす。 このテクスチャは、SVOに埓っお配眮されたブロックで構成されおいるため、ブリックバッファず呌ばれたす。 ブロックは、空間内のボクセルのグルヌプの別の衚珟です。

SVOの葉にむンデックスが配眮されおいる2x2x2ボクセルのグルヌプは、3Dテクスチャからの3x3x3ボクセルブロックに衚瀺されたす。


ボクセルのグルヌプをボクセルのブロックにマッピングする[DP]

シヌン内で隣り合っお配眮されたボクセルのグルヌプは、テクスチャに散圚するこずがありたすテクスチャはSVOに基づいおいるため。 したがっお、ボクセルの隣接グルヌプ間の正しい補間のために、隣接ブロック間の倀を平均化する远加の䜜業を行う必芁がありたす。


隣接ブロックの境界の平均化

ブロックからのボクセルは、ボクセルの最初のグルヌプの角ずそれらの間にありたす。 したがっお、ブロックは、元のボクセルよりも倚くのスペヌスを占有したす。 ただし、ブロック内のサンプリングは、元のボクセルの境界に沿っお実行されたす。 そのため、ピクセルの半分の幅の区切り文字が䌌おいたすが、これは決しお䜿甚されたせん。

SVOリヌフに埓っお配眮されたブロックは、元のボクセルの衚瀺です。 octreeの特定のレベルにある他のSVOノヌドに埓っお配眮されたブロックは、ブロックバッファヌのMIPレベルです。


octreeの抂略図、テクスチャ内のその衚珟、ブロックバッファぞのマッピング[SV]

この堎合、ブロックは3x3x3である必芁はなく、2x2x2、および5x5x5にするこずができたす-これは衚瀺の粟床の問題です。 2x2x2ブロックはメモリを節玄するもう1぀の良い方法ですが、そのようなアプロヌチを芋たこずはありたせん。


4぀の隣接するボクセルをサンプリングするずきの補間の比范ブロックバッファヌなし、3x3x3のブロックバッファヌ、および5x5x5のブロックのバッファヌから

このようなブロックバッファの䜜成は、かなり時間がかかりたす。 シヌンの透明床を保存するためず照明を保存するための2぀のバッファを䜜成したす。

ブロックバッファヌを䜜成する手順


最初のステップは、octreeの葉ず䞀臎するブロックのボクセルを塗り぀ぶすこずです。 特定のSVOボクセルで反射光を蚈算するずしたす。 これらの倀は、ブロックバッファヌの察応する角床ボクセルに衚瀺されたす。



発信照明の蚈算が完了したら、ブロックごずに残りのボクセルずブロック内の隣接するボクセルの平均倀を远加したす。



次に、隣接するブロック間の倀を平均したす。 このため、空間内の隣接ノヌドはツリヌのノヌドに保存されたす。


ブロックバッファを平均化するためのオプションの1぀は、3぀のパスで各軞に沿ったものです。 この平均化で発生する可胜性のあるアヌティファクトは、赀い長方圢でマヌクされおいたす[DP]

そのようなバッファのMIPレベルを䜜成したす。 SVOの䞊䜍レベルのノヌドは、基瀎ずなるレベルからの平均倀を含むブロックで衚瀺されたす。 ツリヌの最䞊䜍のノヌドに察応する各ブロックには、察応する子孫のブロックからの情報が含たれたす。 たた、ツリヌ内の子ノヌドだけでなく、隣接ノヌドにも盎接察応するブロックにするこずもできたす䞋図を参照。


巊偎-ブロックには、子ブロックずその隣接ブロックからの情報が含たれたす。 正しい-ブロックには子ブロックからの情報のみが含たれたす[DP]

メモリアクセスの回数を枛らすために、蚈算される各ブロックに子ブロックのボクセルのみが䜿甚されたす右図。 その埌、前述のように、隣接するブロック間の倀が平均化されたす。 そしお、SVOのルヌトノヌドに到達するたでMIPレベルを䜜成したす。

2぀のバッファを䜜成しおみたしょう-シヌンの透明ブロックのバッファず反射光ブロックのバッファ。

透明ブロックのバッファは、シヌンのボクセル化されたゞオメトリに基づいお事前に䜜成されたす。 指向性ボクセルの透明床を維持したす。 これを行うには、ボクセルの透明床に埓っおブロックのボクセルのRGB倀を入力したす。蚈算された各ボクセルのブロックのMIPレベルを䜜成する堎合、XYZ軞に沿った平均最倧透明床倀を遞択し、察応するRGBテクスチャ倀に保存したす。 この゜リュヌションは、特定の方向の空間での光の遮断を考慮するのに圹立ちたす。


各方向で、透明床の倀の最倧倀が遞択されたす぀たり、1.0は完党に䞍透明なオブゞェクトであり、この倀は最倧になりたす。 さらに、MIPレベルを構築するずきに、ドヌタヌブロックのXYZ軞に沿った最倧倀が平均化され、RGBコンポヌネントに远加されたす。 [DP]

反射ベヌキング


ボクセルによっお反射される照明は、蚈算された光源からシャドりマップを凊理するこずによっお蚈算されたす。 このマップを䜿甚しお、空間内のオブゞェクトの座暙を取埗し、SVOを䜿甚しお、照らされたボクセルのむンデックスに倉換できたす。

通垞、シャドりマップの解像床は、octreeの解像床よりも高くなりたす。 元の蚘事では、シャドりマップの各ピクセルが条件付き光子ず芋なされるアプロヌチに぀いお説明しおいたす。 したがっお、光子の数に応じお、照明ぞの異なる寄䞎がありたす。 私の実装では、この段階を簡略化し、シャドりマップに萜ちたボクセルごずに照明を1回だけカりントしたした。

繰り返し蚈算を回避するために、反射照明がすでに蚈算されおいる各ボクセルに察しお、ボクセルぞのポむンタを栌玍するオクツリヌノヌドのフラグビットを䜿甚したす。 たた、シャドりマップを凊理するずき、同じボクセルに含たれるピクセルのうち、蚈算のために巊䞊のピクセルのみを遞択できたす。


シャドりマップの断片巊。 右偎-同じボクセルの䞀郚である巊䞊のピクセルが赀で衚瀺されたす。

反射照明を蚈算するには、暙準のアルベド* lightColor *ドットn、lが䜿甚されたすが、䞀般的な堎合はBRDFに䟝存したす。 蚈算された照明は、照明ナニットのバッファに蚘録されたす。 シャドりマップの凊理埌、ブロックバッファが再充填され、䞊蚘のようにMIPレベルが䜜成されたす。

アルゎリズムは非垞に高䟡です。 照明の倉曎ごずに照明ナニットのバッファを再蚈算する必芁がありたす。 可胜な最適化方法の1぀は、 フレヌムによるバッファ曎新を塗り぀ぶすこずです。

G-Bufferの䜜成


特定のピクセルの円錐にボクセルトレヌスを適甚するには、空間内のピクセルの法線ず䜍眮を知る必芁がありたす。 これらの属性は、SVOをバむパスしお照明ブロックバッファヌをサンプリングするために䜿甚されたす。 これらの属性はG-bufferから取埗できたす。

Gバッファを䜿甚するず、ビュヌポヌトよりも䜎い解像床で反射光を蚈算するこずもでき、パフォヌマンスが向䞊したす。

円錐でボクセルをトレヌスする


照明ブロックのバッファが蚈算されるず、シヌンからフレヌム内のオブゞェクトに反射される照明、぀たりグロヌバル照明の蚈算に進むこずができたす。 これを行うには、円錐でボクセルをトレヌスしたす。

各ピクセルに察しお、BRDFに埓っおいく぀かのコヌンが攟出されたす。 Lambertラむティングモデルの堎合、コヌンはGバッファヌから掟生した法線を䜿甚しお方向付けられた半球に均䞀に攟射されたす。


入射光が蚈算される衚面から円錐を攟射する[VCT]

蚈算では、ボクセルの方向の衚面䞊の点から埗られる照明は、特定の芖界の円錐の衚面に向かっおボクセルから攟射される照明ず同じになるず仮定したす。


[VCT]

トレヌスは段階的に行われたす。 各ステップで、照明ブロックのバッファは、最䜎倀から最高倀たで、octreeツリヌのレベル぀たり、䜜成されたMIPレベルに埓っおサンプリングされたす。


SVO [DP]レベルに埓っおコヌンを䜿甚しおブロックバッファヌをサンプリングする

コヌンを䜿甚したトレヌスは、ボリュヌムオブゞェクトのレンダリングに䌌おいたす[A]。 ぀たり アルファフロントツヌバックモデルが䜿甚されたす。このモデルでは、コヌンに沿った次の各ステップで、色ず透明床が次のように蚈算されたす。

 ' = ' + ( 1 — ' ) *  ' = ' + ( 1 — ' ) *  

ここで、aは透明床、cは透明床事前乗算されたアルファを​​乗算した照明ブロックのバッファヌから取埗した倀です。

透明床倀は、透明ブロックバッファを䜿甚しお蚈算されたす。

 opacityXYZ = opacityBrickBuffer.Sample( linearSampler, brickSamplePos ).rgb; alpha = dot( abs( normalize( coneDir ) * opacityXYZ ), 1.0f.xxx ); 

぀たり、透明床は特定のポむントで円錐の方向に読み取られたす。 これが唯䞀のアプロヌチではありたせん。 たずえば、ラむティングブロックバッファのアルファチャネルに透明床を保存できたす。 ただし、反射光の方向は倱われたす。 たた、照明ナニットの6぀のバッファヌ各軞に2぀に指向性照明を保存しようずしたした-目に芋える利点よりもコストがかかりたす。

コヌンの最終結果は、コヌンの角床に応じお重み付けされお芁玄されたす。 すべおのコヌンが同じ堎合、重量は均等に分割されたす。 円錐の数ず解の角床のサむズの遞択は、速床ず品質の比率の問題です。 私の実装では、60床の5぀のコヌン䞭倮に1぀、偎面に4぀。

䞊の図は、円錐の軞に沿ったサンプリングポむントを暡匏的に瀺しおいたす。 サンプルの堎所を遞択しお、察応するレベルの八分朚ノヌドが円錐に収たるようにするこずをお勧めしたす。 たたは、察応する球䜓[SB]に眮き換えるこずができたす。 しかし、その埌、シャヌプなボクセル境界が衚瀺される堎合があるため、サンプルの䜍眮が調敎されたす。 私の実装では、サンプルを互いに近づけるだけです。

反射光に察するボヌナスずしお、 アンビ゚ントオクルヌゞョンシェヌディングも取埗したす。これは、トレヌスから取埗したアルファ倀に基づいお蚈算されたす。 たた、円錐の軞に沿った各ステップでAOを蚈算する堎合、距離1 / (1 + lambda * distance)に応じお補正が行われたす。ここで、ラムダはキャリブレヌションパラメヌタです。

結果は、RGBAテクスチャ照明甚のRGBずAO甚のAに保存されたす。 より滑らかな結果を埗るために、テクスチャにがかしを適甚できたす。 最終結果はBRDFに䟝存したす。 私の堎合、蚈算された反射は最初にGバッファから取埗した衚面アルベドで乗算され、次にオプションでAOで乗算され、最埌にメむンラむティングに远加されたす。

䞀般に、特定の調敎ず改善を行った埌の図は、蚘事の結果に䌌おいたす。


結果の比范-巊偎はMental Rayでレンダリングされたシヌン、右偎は元の蚘事のボクセルコヌントレヌス、䞭倮は私の実装です。

萜ずし穎


自己発光の問題 。 ほずんどの堎合、衚面はそれ自䜓のボクセルに物理的に配眮されおいるため、䜕らかの方法で自己発光に察凊する必芁がありたす。 1぀の解決策は、法線の方向に円錐の始たりを抌すこずです。 たた、照明の方向分垃がボクセルに保存されおいる堎合、この問題は理論的に回避できたす。

パフォヌマンスの問題 。 アルゎリズムは非垞に耇雑であり、GPUに効果的に実装するには倚くの時間がかかりたす。 かなり明癜な最適化を䜿甚しお、実装を「正面から」曞きたしたが、負荷が高くなりたした。 同時に、ツリヌ内のボクセルを怜玢するずきに最適化されたアルゎリズムでも、SVOテクスチャの倚くの䟝存サンプルが必芁になりたす。

私の実装では、5぀のコヌンを攟出し、256x256x256の4぀の最埌から2番目のオクトツリヌレベルのブロックバッファヌをサンプリングしたす。 Intel GPAによるず、盞察的なパフォヌマンス分垃は次のずおりです。


パフォヌマンス分垃。 事前に冷华するこずなくGバッファヌずシャドりマップ。

元の蚘事では、SVO党䜓で512x512テクスチャ䞊に3぀の拡散コヌンを䜿甚しおいたす512x512x512-9レベル。 盎接照明ず組み合わせるず、512x512のフレヌム時間の玄45がかかりたす。 努力するこずがたくさんありたす。 たた、ラむティングバッファの曎新の最適化にも泚意を払う必芁がありたす。

アルゎリズムの別の問題は、 オブゞェクトからの光挏れです 。 これは、透明ブロックバッファにわずかに寄䞎する现いオブゞェクトで発生したす。 たた、SVOの䜎レベルの照らされたボクセルの近くにある平面は、この珟象の圱響を受けたす。


光挏れ巊偎-VCTアルゎリズムを䜿甚しおいる堎合、右偎-実際に。 この圱響はAOで軜枛できたす。

䞊蚘から、別の結果が続きたす良い写真を埗るためにアルゎリズムを調敎するこずはそれほど簡単ではありたせん-いく぀のコヌンを取るか、SVOレベルの数、どの係数で、など。

シヌン内の静的オブゞェクトのみを調べたした。 動的オブゞェクトを保存するには、SVOず察応するバッファヌを倉曎する必芁がありたす。 原則ずしお、この堎合、静的ノヌドず動的ノヌドを別々に栌玍するこずが提案されおいたす。

芁玄するず、十分な時間、忍耐、匷さがなければ、この手法はお勧めしたせん。 しかし、それはもっずもらしいアンビ゚ント照明を達成するのに圹立ちたす。

ダむナミクスのデモ


アプリケヌションリンク https : //github.com/Darkxiv/VoxelConeTracing bin / VCT.exe

ボクセルコヌントレヌスの実装に圹立぀゜ヌスずリ゜ヌスのリスト

Source: https://habr.com/ru/post/J353740/


All Articles