1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Unity 6.3のUnifiedRayTracing APIは何が違う?RayTracingShaderとの比較と制約

1
Posted at

Unity 6.3でpublic APIとして公開された UnifiedRayTracing は、ハードウェアRT対応GPUではHardware backendを、非対応GPUではCompute backendを使えるレイトレーシングAPIです。

ただし、これは RayTracingShader の完全な後継や上位互換ではありません。両者は想定している用途と実装モデルが異なります。

本記事では、Unity 6.3 LTS / Scriptable Render Pipeline Core 17.3 を対象に、2つのAPIの違いと、UnifiedRayTracingを採用する際の制約を整理します。

先に結論: 2つのAPIは用途が違う

  • RayTracingShader は、RT対応GPUを対象に、Material・hit shader・再帰を活かした高機能なRTを実装するAPI
  • UnifiedRayTracing は、Hardware RTとCompute fallbackを共通化し、幅広いGPUでMeshレイ問い合わせを実行するAPI

です。

観点 RayTracingShader(Hardware RT) UnifiedRayTracing
主目的 高機能なRT描画 ポータブルなGPUレイ問い合わせ
動作条件 RT対応GPU・OS・Graphics APIが必要 Compute Shader対応GPU。HW RTがあればHardware backend、なければCompute backend
shader形式 .raytrace とMaterial側のShader Pass .urtshader からHardware / Compute向けshaderを生成
hit shader Materialごとにclosest-hit / any-hit / intersectionを選択可能 Materialごとの自動選択は不可。.urtshader 全体で共有するcallbackを自前実装
Scene連携 RayTracingAccelerationStructure とRendererを使う設計 Mesh + Submeshを手動登録。Sceneとの自動同期なし
Geometry属性 Material shader中心の設計に組み込みやすい RTASは三角形位置への問い合わせが中心。normal / UV / tangentなどは自前GPU bufferで管理
Skinned Mesh ハードウェアRT用のRenderer連携を利用できる 自動追従なし。BakeMeshまたは頂点buffer更新とRTAS再登録が必要
Compute fallback なし あり。ただしHardware RTより大きく遅くなりうる
向く用途 高品質反射、屈折、複雑な材質、既存RT shader資産 可視性判定、遮蔽、GPU版Raycast、自前shadingのRTGI
既存RT shaderの移植 Material・Geometry属性・RTAS同期を自前化するため高い

UnifiedRayTracingは「どのGPUでも同じ高品質RT描画を簡単に行うAPI」ではなく、自前のGeometry・Material・shading基盤を持つプロジェクト向けの、ポータブルなGPUレイ問い合わせAPIです。

UnifiedRayTracing APIの特に大きな制約

UnifiedRayTracingは、Hardware RTの機能をそのままCompute対応GPUへ広げる互換レイヤーではありません。

特に大きい制約は、次の3点です。

  1. Materialと頂点属性を自動では扱わない
    RTASが提供するのは基本的に三角形への交差結果です。法線・UV・接線・頂点カラー・Materialパラメータは自前でGPU bufferへ保持し、instanceIDprimitiveIndex、barycentric座標から復元・補間します。

  2. 動的形状を自動追従しない
    Skinned Mesh、Morph、Compute変形などの頂点変形は自動反映されません。変形後のMeshを用意し、RTASの再登録・再ビルドを管理する必要があります。

  3. Material単位のhit shaderを選べない
    RayTracingShader のように、Materialごとにclosest-hit / any-hit shaderを差し替える仕組みはありません。共通callback内で自前のMaterialデータを参照し、分岐または独自のshading構成を実装します。

このため、「従来のUnity Materialを使っているSceneへ、そのままRT効果を足す」という用途には向きません。

UnifiedRayTracingを選ばないほうがよい場面

以下の要件がある場合は、RayTracingShader、HDRPの既存RT機能、または別の近似手法を優先する方が現実的です。

要件 UnifiedRayTracingを選びにくい理由
既存Materialの反射・屈折・透過をそのままRT化したい Material / hit shaderの自動連携がない
alpha cutoutや複雑な透明材質を多用する Any HitとMaterial参照を自前実装する必要がある
多数のSkinned Meshを毎フレーム正確に追従させたい 頂点変形とRTAS更新の管理・コストが大きい
Terrain、Particle、VFX、Line Rendererを直接レイ判定したい 公開APIの登録対象はMesh geometryのみ
高解像度・多重バウンスのリアルタイム反射を全GPUで維持したい Compute fallbackはHardware RTより大幅に遅くなりうる
既存の.raytrace資産を低コストで移植したい shader設計、Geometry属性、Material管理を作り直す必要がある

反対に、対象が静的または低頻度更新のMeshであり、少数レイの可視性判定・遮蔽判定・GPU問い合わせを行いたい場合は、UnifiedRayTracingの強みが活きます。

1. UnifiedRayTracingはMaterial駆動のAPIではない

RayTracingShader では、Materialに設定されたShader Passを使い、closest-hit / any-hit / intersection shaderを選択できます。

一方、UnifiedRayTracingの公開APIは、HardwareとComputeの両backendに共通化された以下の概念で構成されます。

  • RayTracingContext
  • IRayTracingAccelStruct
  • IRayTracingShader
  • .urtshader

公開APIには、Materialやhit groupの選択機構がありません。基本的には「rayを飛ばし、どの三角形に当たったか」を受け取り、その後のshadingを自前で実装します。

そのため、次のように理解すると設計を誤りにくくなります。

UnityのMaterialを辿る描画APIではなく、自前データをinstanceIDで紐付けて使うMeshレイ問い合わせAPI

公開APIには RayTracingShader のような再帰深度を設定する仕組みもありません。複数バウンスを両backendで扱う場合は、ray generation側で反復処理を組む設計が安全です。

2. RTASへの登録単位はMesh + Submesh

RTASへ登録するのは Renderer ではなく MeshInstanceDesc です。

uint instanceId = 42;

var desc = new MeshInstanceDesc(mesh, subMeshIndex);
desc.localToWorldMatrix = renderer.transform.localToWorldMatrix;
desc.instanceID = instanceId;

int handle = rtAccelStruct.AddInstance(desc);

1つの MeshInstanceDesc は、1つのMeshの1つのSubmeshだけを参照します。複数Submeshを持つMeshは、Submeshごとに別インスタンスとして登録します。

for (int subMeshIndex = 0; subMeshIndex < mesh.subMeshCount; subMeshIndex++)
{
    var desc = new MeshInstanceDesc(mesh, subMeshIndex);
    desc.localToWorldMatrix = renderer.transform.localToWorldMatrix;
    desc.instanceID = instanceId++;

    int handle = rtAccelStruct.AddInstance(desc);
}

MeshInstanceDesc に設定できる主な情報は以下です。

  • mesh
  • subMeshIndex
  • localToWorldMatrix
  • instanceID
  • mask
  • opaqueGeometry
  • enableTriangleCulling
  • frontTriangleCounterClockwise

ただし、MeshRendererSkinnedMeshRendererMaterial 自体を登録するわけではありません。

3. Mesh以外の形状は直接登録できない

現行の公開APIでRTASへ登録できるのはMesh geometryです。

そのため、以下をそのままレイ判定対象にはできません。

  • Terrain
  • Particle System
  • Line Renderer
  • Sprite Renderer
  • VFX Graphの出力
  • Renderer固有の描画形状

これらを対象にするには、Meshへ変換するか、別の判定方式を用意する必要があります。

4. Sceneとの自動同期はない

UnifiedRayTracingのRTASは、Scene内のRendererと自動同期しません。

そのため、アプリケーション側で変更を追跡し、以下のAPIを呼び分けます。

変更内容 更新方法
transform UpdateInstanceTransform
instanceID UpdateInstanceID
mask UpdateInstanceMask
インスタンス削除 RemoveInstance
全インスタンス削除 ClearInstances
Mesh / 頂点形状の変更 Remove → Add → Build

transform以外の単純なメタデータには更新用APIがあります。一方、頂点変形やMesh差し替えは、インスタンスを登録し直してRTASを再ビルドする必要があります。

rtAccelStruct.RemoveInstance(handle);

var updatedDesc = new MeshInstanceDesc(updatedMesh, subMeshIndex);
updatedDesc.localToWorldMatrix = transform.localToWorldMatrix;
updatedDesc.instanceID = instanceId;

handle = rtAccelStruct.AddInstance(updatedDesc);
rtAccelStruct.Build(cmd, buildScratchBuffer);

静的環境や低頻度更新のオブジェクトには扱いやすい一方、毎フレーム大量に形状が変わるSceneでは、RTAS更新コストの計測が必要です。

5. SkinnedMeshRendererは自動追従しない

SkinnedMeshRenderer をそのまま登録し、スキニング後の頂点をRTASへ自動反映する機能はありません。

sharedMesh を登録すること自体はできますが、それは元のMeshであり、アニメーションによる頂点変形は反映されません。

回避策1: BakeMesh

SkinnedMeshRenderer.BakeMesh で変形結果を通常のMeshへ焼き、それをRTASに登録できます。

skinnedMeshRenderer.BakeMesh(bakedMesh);

ただし、BakeMesh はCPUスキニングを実行します。多数キャラクターや高ポリゴンモデルを毎フレーム処理する用途には重い方法です。

回避策2: GPU側で頂点bufferを更新する

Unity開発者は、Compute ShaderでMeshの頂点bufferを更新し、RTASインスタンスを RemoveInstanceAddInstance し直す方法を例として挙げています。

こちらはCPUのBakeMeshを避けられますが、書き込み可能なMesh buffer、再登録、再ビルド、および対応GPUでの性能検証が必要です。Skinned Mesh対応が自動化されるわけではありません。

6. 最重要: RTASは頂点位置しか提供しない

TraceRayClosestHit で取得できるのは以下です。

  • instanceID
  • primitiveIndex
  • uvBarycentrics
  • hitDistance
  • isFrontFace
UnifiedRT::Hit hit = UnifiedRT::TraceRayClosestHit(
    dispatchInfo,
    accelStruct,
    0xFFFFFFFF,
    ray,
    0
);

ここで注意したいのは、uvBarycentricsUV値ではなく三角形上のbarycentric座標であることです。

現行APIは、三角形の位置に対するレイ判定を提供するだけです。法線、UV、接線、頂点カラーなどのGeometry属性は取得できません。

つまり、instanceIDprimitiveIndexuvBarycentrics があっても、補間する頂点データをGPU bufferへ自前で持たなければ、Material評価はできません。

Hit.instanceID
  ↓
自前のInstance情報Buffer
  ↓
Meshごとのindex / vertex buffer offset
  ↓
Hit.primitiveIndexで三角形のindexを取得
  ↓
3頂点のposition / normal / UVを取得
  ↓
Hit.uvBarycentricsで補間
  ↓
自前のMaterial情報Bufferを使ってshading

Unity内部にはGeometry属性管理用の GeometryPool / AccelStructAdapter がありますが、現時点でpublic APIではありません。

この頂点属性管理が、既存RT shaderを移植する際の実装コストを大きく支配します。

7. Materialごとのhit shaderはない

RayTracingShader ではMaterialのShader Passにより、closest-hit / any-hit / intersection shaderを選択できます。

UnifiedRayTracingには、このMaterial単位のhit shader選択はありません。

したがって、以下のような構成はそのまま移植できません。

金属Materialは反射用closest-hit shader
ガラスMaterialは屈折用closest-hit shader
alpha cutout Materialは専用any-hit shader

UnifiedRayTracingでは、instanceID から自前のInstance / Materialデータを引き、共通shader内で分岐または関数テーブル相当の処理を実装します。

8. 標準ヘルパーではAny Hitを使わない

通常は TraceRayAndQueryHit.hlsl をインクルードして、TraceRayClosestHit または TraceRayAnyHit を使います。

UnifiedRT::Hit hit = UnifiedRT::TraceRayClosestHit(
    dispatchInfo,
    accelStruct,
    0xFFFFFFFF,
    ray,
    0
);

この標準ヘルパーはopaqueとして走査し、ヒット情報を返すためのものです。Materialごとのalpha cutout判定のようなAny Hit処理は行いません。

MeshInstanceDesc.mask とレイ側のmaskはuintですが、実効的には下位8bitのinstance maskとして扱われます。公式サンプルに合わせて 0xFFFFFFFF を渡すと、全インスタンスを対象にする意図を明確にできます。

Any Hitなどを使う場合

AnyHitExecuteClosestHitExecuteMissExecuteIntersection を使うには、低レベルの TraceRay.hlsl を直接インクルードし、payloadとcallbackを自前定義します。

ただし、callbackは**.urtshader 全体で共有される関数**です。Materialごとの別shaderを自動選択する仕組みにはなりません。

opaqueGeometry = false のインスタンスではAny Hitを呼び出し、alpha cutoutのような候補ヒットの採用・破棄を実装できます。しかしMaterial参照はないため、instanceIDから自前のalpha textureやMaterialパラメータを参照する必要があります。

この低レベルcallback経路を使う場合は、Unityバージョンを固定し、Hardware / Compute両backendで検証するのが安全です。

9. Hardware backendとCompute backendは同じではない

Hardware backendは、現状では主にDX12経由でハードウェアRTを公開するGPUで使われます。それ以外の多くの環境ではCompute backendへフォールバックします。

Compute backendは実行可能なGPU範囲を広げますが、ハードウェアRTと同等の性能を保証しません。

Unity開発者は、単純なsingle-kernel path tracerで、Compute backendがHardware backendより約2〜10倍遅くなる例を示しています。この数値は保証値ではなく、以下で大きく変わります。

  • 三角形数
  • RTASのビルド設定
  • レイ本数
  • レイの長さ
  • shaderの分岐量
  • GPUとGraphics API

またCompute backendはRadeonRaysの移植を基にしており、Unity開発者自身も改善余地があると説明しています。将来のバージョンで性能特性が変わる可能性があります。

Compute fallbackでは、少数レイの可視性・遮蔽・問い合わせに用途を絞るのが安全です。高品質な反射や多重バウンスを行う場合は、Hardware RT専用の品質設定を分けるか、自前shadingを含めた十分なベンチマークが必要です。

10. Playerではshaderとscratch bufferを管理する

.urtshader をPlayerで使用するには、AssetBundleに含めてロードします。Editorで動作しても、Player用AssetBundleへ含め忘れると利用できません。

RTASの Build とshaderの Dispatch にはscratch用の GraphicsBuffer が必要です。

ulong buildSize =
    rtAccelStruct.GetBuildScratchBufferRequiredSizeInBytes();

ulong traceSize =
    rtShader.GetTraceScratchBufferRequiredSizeInBytes(
        width, height, depth
    );

uint3 threadGroupSize = rtShader.GetThreadGroupSizes();

GetThreadGroupSizes() を使い、shaderのthread groupサイズに合わせてdispatchサイズを計画します。

また、IRayTracingAccelStruct、shader、RayTracingContext は明示的なリソース管理が必要です。Contextを破棄する前に、そのContextが生成したRTASを破棄します。

まとめ

UnifiedRayTracingは、高品質RTを不可能にするAPIではありません。Unity開発者によれば、UnityのRTGIもこのAPIを使っています。

ただし、その高品質を成立させるには、以下をアプリケーション側で実装する必要があります。

  • SceneとRTASの同期
  • Geometryのvertex / index buffer管理
  • 頂点属性の補間
  • instanceIDとMaterialデータの対応付け
  • Material相当のshading
  • 動的Mesh更新戦略
  • Hardware / Compute両backendでの性能設計
観点 UnifiedRayTracing
登録単位 Mesh + Submesh
Renderer / Material自動連携 なし
Scene自動同期 なし
Skinned Mesh自動更新 なし
頂点属性取得 自前実装
Materialごとのhit shader なし
共通callback 可能
Compute fallback あり
自前shadingによる高品質RT 可能
既存Material駆動RTの移植適性 低い
GPUレイ問い合わせへの適性 高い

参考資料

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?