Share
Embed
Object Space Raymarching in Unreal Engine 5.2
がむ
September 01, 2023
Transcript
44 slides
-
自己紹介 @gam0022(がむ)/ Sho HOSODA グラフィックスエンジニア/Unityでモバイルゲームを開発 『Unityバイブル R5夏号』 を執筆 • ボーンデジタルの
Unityバイブルシリーズの最新号 • 年2回の定期刊行の第1号 • ShaderGraphの章を担当 • 2023-08-29発売 2 -
自己紹介 @gam0022(がむ)/ Sho HOSODA グラフィックスエンジニア/Unityでモバイルゲームを開発 • CGWORLDにデモシーンの記事を寄稿 ◦ 「メガデモ」とも呼ばれる ◦
これが64KB?! デモシーンを支える プロシージャル技術 ◦ https://cgworld.jp/feature/202101-de moscene.html 3 -
自己紹介 @gam0022(がむ)/ Sho HOSODA グラフィックスエンジニア/Unityでモバイルゲームを開発 • Aphex TwinのARアプリの開発に協力 •
アルバムのジャケットがARマーカー • レイマーチングでメンガースポンジを描画 4 -
自己紹介 @gam0022(がむ)/ Sho HOSODA グラフィックスエンジニア/Unityでモバイルゲームを開発 WORMHOLE by @gam0022 & @sadakkey
1st place in Combined Demo Compo at Tokyo Demo Fest 2018 Made with Unity RE: SIMULATED by @gam0022 & @sadakkey 1st place in PC 64K Intro at Revision 2020 Original WebGL Framework Unityゲーム プログラミング・バイブル 2nd Generation 2021年 ボーンデジタル出版 著者のひとりとして参加 商業誌でレイマーチングを解説する実績を解禁 🏆 5 -
レイマーチングとは? • レイマーチングとは ‣ 距離関数で表現された形状に対する交差判定の手法 • 距離関数とは ‣ 任意の座標pから物体表面への最短距離を返す関数
float sdSphere(vec3 p, float r) { return length(p) - r; } 11 -
レイマーチングとは? float sdBox(vec3 p, vec3 b) { vec3 q =
abs(p) - b; return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0); } https://iquilezles.org/articles/distfunctions/ 12 -
レイマーチングとは? • レイマーチングを可視化したアニメーション by @kanetaaaaa ‣ Raymarching in Raymarching
‣ https://twitter.com/kanetaaaaa/status/1141307706139004934 ‣ https://qiita.com/kaneta1992/items/21149c78159bd27e0860 13 -
レイマーチングとは? • レイマーチングのアルゴリズム ‣ 距離関数だけレイを進めるのを繰り返す(マーチング・ループ) • 距離関数dが0に近似できたら衝突したと判定 ‣ abs(d) <
eps ‣ epsは0.001 など適切に設定 • ループ回数がNを超えたら衝突していないと判定 ‣ Nは100〜300くらいが一般的 極めてシンプル 14 -
実装の流れ 1. UE上のHLSL(.ush)シェーダー開発環境の構築 a. C++の開発環境のセットアップ b. AddShaderSourceDirectoryMappingでシェーダーを配置するディレクトリを登録
2. UE上のレイマーチングの実装 a. HLSL(.ush)でレイマーチングを実装 b. MaterialのCustomノードの Include File Paths に .ush を追加、 レイマーチングの関数を呼び出す c. Customノードの計算結果をResultノードに出力、ライティング計算はエンジン側に任せる 19 -
HLSL(.ush)によるシェーダー開発環境の構築 • まずはC++の開発環境を整える必要がある • Visual Studio 2022のセットアップ|Unreal Engine 5から始める
C++ & Blueprint • 上記の記事を参考にVisual Studio 2022と必要なコンポーネントをインストール 20 -
HLSL(.ush)によるシェーダー開発環境の構築 • C++の開発環境をセットアップしたら、AddShaderSourceDirectoryMappingを呼び出してシェーダーを配置するディレクトリをエ ンジン側に登録する • 下記の記事の「普通の方法」を参考にC++のコード実装 • UE4,5 プロジェクトファイル内の外部シェーダーファイル(usf,
ush, hlsl)をインクルードする為の設定。 - Qiita • C++プロジェクト化 • プロジェクト名.Build.csにRenderCoreへの依存関係を追加 • プロジェクトにモジュール開始,終了ファンクションを追加 • モジュール開始のStartupModule()に下記のコードを追加 void FMyProjectModule::StartupModule() { UE_LOG(LogTemp, Warning, TEXT("Module Started")); FString ShaderDir = FPaths::Combine(FPaths::ProjectDir(), "Shaders"); AddShaderSourceDirectoryMapping("/Project", ShaderDir); } 21 -
HLSL(.ush)によるシェーダー開発環境の構築 • ディレクトリ構成 • プロジェクト直下にShadersディレクトリを作成 • .ushのファイル名例 • D:\UnrealProjects\プロジェクト名\Shaders\Raymarching.ush
• Customノードからの参照方法 • Include File Pathsでは以下のように指定 • /Project/Raymarching.ush 22 -
余談:Include File Pathsが無かった時代の関数定義の手法 2015年の記事によると、当時はCustomノードのInclude File Pathsが無かった SQLインジェクションのような感じで、HLSLのコードが展開される仕様をハックして関数定義 • https://twitter.com/TakuroKX/status/670292440369094656
• Customノード3分ハッキング • UE4のCustomノード(カスタムHLSLシェーダ)を使ってみた - ぼっちプログラマのメモ 23 -
レイマーチングの Customノード Emissiveのパターン計算 前後関係の解消のための Pixel Depth Offsetの計算 カメラのレイの生成 定数パラメーター World
Position 定数パラ メーター Material全体 -
Material Editor全体 • レイマーチングの処理はHLSLで実装 ‣ ノードで実装するには複雑すぎる • ノード部分の実装内容は限定的 ‣
カメラのレイの生成 ‣ Emissiveのパターン計算 ‣ 前後関係の解消のためのPixel Depth Offsetの計算 25 -
実装解説:レイマーチング基本 Raymarching.ush では以下のインターフェースで関数定義 ノードの Additional Outpus に対応する値は inout を指定
void raymarching( float3 origin, float3 ray, int raymarchingLoop, float uniformScale, float3 mengerOffst, float mengerScale, inout float hit, inout float depth, inout float3 hitPosition, inout float3 albedo, inout float3 normal, inout float ao, inout float emissive ) コード全体は長いので省略 26 -
実装解説:レイマーチング基本 CustomノードのCodeでは、raymarhcingの関数を呼び出すだけ albedo = objectAlbedo; raymarching( origin, ray,
raymarchingLoop, uniformScale, mengerOffst, mengerScale, hit, depth, hitPosition, albedo, normal, ao, emissive ); return albedo; 27 -
実装解説:レイマーチング基本 Raymarching.ush では以下のインターフェースで関数定義 ノードの Additional Outpus に対応する値は inout を指定
void raymarching( float3 origin, float3 ray, int raymarchingLoop, float uniformScale, float3 mengerOffst, float mengerScale, inout float hit, inout float depth, inout float3 hitPosition, inout float3 albedo, inout float3 normal, inout float ao, inout float emissive ) コード全体は長いので省略 29 -
実装解説:レイマーチング基本 • Material Domain: Surface ◦ レイマーチングはボリュームレダリングの印象があるかもしれないが、SurfaceでOK • Blend Mode:
Masked ◦ レイマーチングの衝突判定によって形状をマスクする必要がある ◦ このオプションを有効にすることで、Opacity Maskを出力できる ▪ 交差している場合は1、交差していない場合は0を出力 ▪ 要するにdiscard • Shading Model: Default Lit ◦ ライティング計算はエンジン側に任せる • Two Sideded: ON ◦ カメラがレイマーチングの内部に 入った場合に両面描画が必要 31 -
Materialノード解説:カメラのレイの生成 • ray(レイの方向)は簡単 ‣ ray = normalize(Surfaceの座標 - カメラの位置)
‣ ※Surfaceの座標 = 描画しようとしているピクセルのワールド座標 33 カメラの位置 Surfaceの座標 差分 正規化 レイの方向(ray)の生成 -
カメラがレイマーチング空間に潜った場合の考慮 • レイの原点はカメラの位置によって分岐 • カメラがCube外部 → Cubeの表面 • カメラがCube内部
→ カメラ座標 内外判定のCustomノード Cubeの表面 カメラ座標 動的分岐 38 -
もっと詳しい情報 • GitHub ‣ UnrealEngineのプロジェクト ‣ https://github.com/gam0022/RaymarchingInUE5 • 解説記事
‣ Object Space Raymarching in Unreal Engine 5.2 | gam0022.net ‣ https://gam0022.net/blog/2023/07/31/raymarching-in-ue5/ 43