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点です。
-
Materialと頂点属性を自動では扱わない
RTASが提供するのは基本的に三角形への交差結果です。法線・UV・接線・頂点カラー・Materialパラメータは自前でGPU bufferへ保持し、instanceID、primitiveIndex、barycentric座標から復元・補間します。 -
動的形状を自動追従しない
Skinned Mesh、Morph、Compute変形などの頂点変形は自動反映されません。変形後のMeshを用意し、RTASの再登録・再ビルドを管理する必要があります。 -
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に共通化された以下の概念で構成されます。
RayTracingContextIRayTracingAccelStructIRayTracingShader.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 に設定できる主な情報は以下です。
meshsubMeshIndexlocalToWorldMatrixinstanceIDmaskopaqueGeometryenableTriangleCullingfrontTriangleCounterClockwise
ただし、MeshRenderer、SkinnedMeshRenderer、Material 自体を登録するわけではありません。
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インスタンスを RemoveInstance → AddInstance し直す方法を例として挙げています。
こちらはCPUのBakeMeshを避けられますが、書き込み可能なMesh buffer、再登録、再ビルド、および対応GPUでの性能検証が必要です。Skinned Mesh対応が自動化されるわけではありません。
6. 最重要: RTASは頂点位置しか提供しない
TraceRayClosestHit で取得できるのは以下です。
instanceIDprimitiveIndexuvBarycentricshitDistanceisFrontFace
UnifiedRT::Hit hit = UnifiedRT::TraceRayClosestHit(
dispatchInfo,
accelStruct,
0xFFFFFFFF,
ray,
0
);
ここで注意したいのは、uvBarycentrics はUV値ではなく三角形上のbarycentric座標であることです。
現行APIは、三角形の位置に対するレイ判定を提供するだけです。法線、UV、接線、頂点カラーなどのGeometry属性は取得できません。
つまり、instanceID、primitiveIndex、uvBarycentrics があっても、補間する頂点データを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などを使う場合
AnyHitExecute、ClosestHitExecute、MissExecute、Intersection を使うには、低レベルの 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レイ問い合わせへの適性 | 高い |
参考資料
- Introducing the UnifiedRayTracing API | Unity Discussions
- Get started with ray tracing | Unity Documentation
- Create an acceleration structure | Unity Documentation
- MeshInstanceDesc | Unity Documentation
- IRayTracingAccelStruct | Unity Documentation
- Write your ray tracing code | Unity Documentation
- TraceRay.hlsl | Unity Graphics repository