プロシージャル コンテンツ生成フレームワーク (PCG:Procedural Content Generation Framework) は、Unreal Engine 内で独自のプロシージャル コンテンツおよびツールを作成するためのツールセットです。 PCG GPU 処理は、テクニカル アーティストやデザイナーに多数の PCG 処理タスクを直接 GPU に送信し、CPU のリソースを解放する機能を提供します。
PCG GPU 処理は、ポイント (点) 処理、ランタイム生成、スタティックメッシュのスポーンなど、さまざまなタスクで効率的に活用できます。
将来的に、GPU 実行をサポートするノードが追加で利用可能になる予定です。
GPU をターゲットにするように設定されたノードは、PCG グラフ内で GPU のラベルが表示されます。 接続された GPU ノードのサブセットは、GPU で効率的にまとめて実行されます。これは、コンピュート グラフと呼ばれます。
番号 | 説明 |
1 | CPU と GPU の間でデータを転送します。 これらのポイントがパフォーマンス コストを表しています。 |
2 | まとめて実行される GPU 実行ノードです。 |
GPU をターゲットにした場合、GPU ハードウェアを最大限に活用するのに十分な数のポイントがデータ内にあれば CPU 実行よりもパフォーマンスが向上する可能性があります。 また、接続された GPU ノードのシーケンスと GPU に対応した Static Mesh Spawner ノードにより、スタティックメッシュのスポーンの高速パスが提供されます。
CPU と GPU の間でデータを転送する際と実行用のコンピュート グラフを準備する際に CPU コストが発生することに注意してください。 したがって、GPU 実行機能の最適な使用方法は、GPU 対応ノードをグループ化して、各コンピュート グラフに入出力されるデータの量を最小限に抑えることです。
サポートされるノード
Custom HLSL ノード
Custom HLSL ノードは、ユーザーが作成した HLSL ソース コードを介して任意のデータ処理タスクをスクリプト化するのに使用できます。 このソース コードはコンピュート シェーダーに挿入され、GPU ハードウェアでデータ要素に対して並列に実行されます。
このノードは、GPU ハードウェアへの低レベルのアクセスを提供します。これは上級ユーザー向けです。
オプション
| 説明 |
Kernel Type (カーネル タイプ) | ノードの動作のプリセットを選択します。 使用可能なオプションに関する文書は、以下の「 Custom HLSL ノードのカーネル タイプ 」セクションを参照してください。 |
Input Pins (入力ピン) | 入力として受け取るデータを定義します。 展開すると次のオプションがあります。
|
Output Pins (出力ピン) | ノードから出力されるデータを定義します。 [Input Pins] と同じオプションに加え、出力データを設定する追加オプションを含んでいます。 これらについては、以下の 「ピンをセットアップする」セクションで説明します。 あります |
Kernel Source Override (カーネルソースのオーバーライド) | [Shader Source (シェーダーソース)] フィールドを UComputeSource アセットで置換するために使用します。 |
Additional Sources (追加のソース) | Custom HLSL ノードにバンドルされる追加の UComputeSource アセットの参照を可能にします。 |
Mute Unwritten Pin Data Errors (書き込まれていないピンデータのエラーをミュート) | 初期化されていないデータがある可能性のある出力ピンの警告をミュートします。 |
Seed (シード) | ランダム生成を制御するために使用するシード値を定義します。 |
Dump Cooked HLSL (クック済み HLSL をダンプ) | デバッグ用にクックされた HLSL データが生成されたときにログに出力します。 |
Dump Data Descriptions (データの説明をダンプ) | デバッグ用に生成時に入力データと出力データのデータの説明をログに出力します。 |
Print Shader Debug Values (シェーダー デバッグ値を出力) | シェーダー コードからのシンプルなデバッグ ログを提供します。 説明は以下の「 Custom HLSL をデバッグする」を参照してください。 」セクションを参照してください。 |
HLSL ソース エディタ
HLSL ソース エディタを使用すると、Custom HLSL ノードをすばやく作成できます。 これを見つけるには、PCG グラフ エディタで [Window (ウィンドウ)] -> [HLSL Source Editor (HLSL ソース エディタ)] の順に移動するか、Custom HLSL ノードを選択した状態でノード設定の [Open Source Editor (ソース エディタを開く)] ボタンをクリックします。
HLSL ソース エディタは次の 3 つの部分から構成されています。
Declarations (宣言) パネル
Shader Functions (シェーダー関数)
Shader Source (シェーダー ソース)
[Declarations] パネルはシェーダー コードを作成する際の API リファレンスの役割を果たします。 宣言は、Custom HLSL ノード設定のカーネル タイプ設定や入出力ピン設定などから自動的に生成されます。
[Shader Functions] フィールドでは、[Shader Source] で呼び出すことのできる再利用可能な関数を作成できます。
[Shader Source] フィールドは、カーネル実装のメイン エントリ ポイントを実装する場所です。
Custom HLSL ノードのカーネル タイプ
[Kernel Type] はノードの動作のプリセットを定義します。
ポイント プロセッサ
Point Processor (ポイント プロセッサ) カーネル タイプは、ポイントを変更するのに最適です。 プライマリ入力ピンと出力ピンの型が Point である必要があり、各ポイントに対して HLSL コードが 1 回実行されます。 プライマリ出力ピンから送信されるデータは、プライマリ入力ピンと同じレイアウトを持っています。つまり、データ数と要素数は同じです。
プライマリ出力にあるすべてのポイントはプライマリ入力から自動的に初期化されるため、必要なのは変更すべき出力属性を設定することだけです。
また、Point Processor を使用して追加の入力ピンと出力ピンを作成することもできます。これらのピンは手動で設定し、目的のデータ型やデータ/要素カウントを設定する必要があります。
Point Generator
Point Generator カーネル タイプは、ポイントのセットを作成、配置するのに最適です。 プライマリ出力ピンの型が Point である必要があり、各ポイントに対して HLSL コードが 1 回実行されます。
このカーネル タイプには次の追加オプションがあります。
オプション
| 説明 |
Point Count (ポイント カウント)
| 生成されるポイントの数を決定します。 シェーダー コードは生成される各ポイントに対して実行されます。 |
Point Processor と同様に、Point Generator を使用すると、追加の入力ピンと出力ピンを作成できます。目的のデータ型およびデータ (要素) カウントを設定するには、これらのピンを手動で構成する必要があります。
カスタム
Custom カーネル タイプは、高度なユース ケースでの実行に関するきめ細かなコントロールを公開します。 他の 2 つのカーネル タイプとは異なり、ノードは入力と出力の間に特定の関係を想定しないため、入力ピンまたは出力ピンに適用される設定はありません。 出力データは、以下に記載されている出力ピンの設定で構成する必要があります。 シェーダー コードを実行するスレッドの数も構成する必要があります。
このカーネル タイプには次の追加オプションがあります。
オプション | 説明 |
Dispatch Thread Count (スレッド数をディスパッチ) | シェーダー コードが実行に使用するスレッドの数を決定します。 以下のモードを使用できます。
|
ピンをセットアップする
カーネル タイプによって制御されないピンは、手動で構成する必要があります。
出力ピンでは、データ サイズとレイアウトを明示的に記述する必要があります。これは、出力ピン設定の [GPU Properties (GPU のプロパティ)] ドロップダウンで設定できます。
Initialization Mode (初期化モード) | このピンの出力データの初期化方法を指定します。 このメニューには、次のモードがあります。
|
Pins to Initialize From (初期化を開始するピン) | このピンのデータの初期化に使用される入力ピンを定義します。 |
Data Count Mode (データ カウント モード) | データ オブジェクトの数を定義します。 このメニューには、次のモードがあります。
|
Data Multiplicity (データの多重性) | 初期化元のピンが複数ある場合、データ カウントを結合します。 利用可能なモードは次のとおりです。
|
Element Count Mode (要素カウント モード) | 要素数を定義します。 このメニューには、次のモードがあります。
|
Element Multiplicity (要素の多重性) | 初期化元のピンが複数ある場合、要素カウントを結合します。 利用可能なモードは次のとおりです。
|
Attribute Inheritance Mode (属性継承モード) | 属性名、型、および値の継承方法を定義します。このメニューには次のモードがあります。
|
Attributes to Create (作成する属性) | 出力データに作成する新しい属性のリストを定義します。 |
Custom HLSL をデバッグする
[Debug Display (デバッグ表示)] (デフォルトのホットキーは「D」) 機能と [Inspection (検査)] (デフォルトのホットキーは「A」) 機能は GPU ノードを対象としており、GPU ノードを流れるデータの検査を有効にします。
Custom HLSL ノードの [Print Shader Debug Values (シェーダー デバッグ値を出力)] オプションを切り替えることで、カスタム シェーダー コードをデバッグすることもできます。 これによって、新しい関数 WriteDebugValue が公開され、この関数を使用して、実行時にログに記録されるバッファに浮動小数値を書き込むことができます。 バッファ サイズは [Debug Buffer Size (デバッグ バッファ サイズ)] プロパティで制御します。
例
例 1:正弦波を使用した高さのオフセット
以下の例では、Point Processor を使用して正弦波ベースの高さオフセットをポイントのセットに適用しています。
次のコードは、HLSL ソース エディタ ウィンドウの [Shader Source] フィールドに追加されています。
// Get the position of the incoming point from input pin ‘In’.
float3 Position = In_GetPosition(In_DataIndex, ElementIndex);
// Compute a sine wave with amplitude 500cm and wavelength 400cm.
const float Wave = 500.0f * sin(Position.x / 400.0f);
// Add the wave to the Z coordinate of the point’s position.
Position.z += Wave;
// Write the offset position to the output point on pin ‘Out’.
例 2:属性を作成する
以下の例では、Point Generator を使用してポイントのグリッドを作成し、属性セットを使用してグリッドの高さを制御しています。
次のコードは、HLSL ソース エディタ ウィンドウの [Shader Source] フィールドに追加されています。
// Get PCG Component bounds.
const float3 BoundsMin = GetComponentBoundsMin();
const float3 BoundsMax = GetComponentBoundsMax();
// Get the current point position in a 2D grid, based on the
// number of points and the component bounds.
float3 Position = CreateGrid2D(ElementIndex, NumPoints, BoundsMin, BoundsMax);
Position.z += InHeight_GetFloat(0, 0, 'GridHeight');
// Set the point's position.
シェーダー コードで属性にアクセスするには、用意されている Get 関数と Set 関数を使用します。また、アポストロフィで名前を囲むことで、属性を名前でクエリできます。 ‘GridHeight’ がその例です。
例 3:ランドスケープにランダム メッシュをスポーンする
Custom HLSL ノードは、一連の操作を実行することもできます。
以下の例では、シェーダー コードは次の操作を実行します。
ランドスケープにいくつかのポイントを作成する。
各ポイントにランダムな位置調整を適用する。
ポイントの位置を設定する。
各ポイントにランダム シード値を書き込む。
スタティック メッシュのリストを含む属性セットを読み取り、各ポイントにランダム メッシュを割り当てます。
Custom HLSL ノードの下流には、GPU 実行が有効であり、メッシュ属性が「MeshPath」に設定されている Static Mesh Spawner があります。
GPU 属性では、type String、Name、Soft Object Path、Soft Class Path が StringKey になり、各文字列を一意に識別します。
次のコードは、[HLSL Source] ウィンドウの [Shader Source] フィールドに追加されています。
// Get generation volume bounds
const float3 BoundsMin = GetComponentBoundsMin();
const float3 BoundsMax = GetComponentBoundsMax();
// Compute a position on a 2D grid within the volume.
float3 Pos = CreateGrid2D(ElementIndex, NumPoints, BoundsMin, BoundsMax);
// Initialize the random seed from the position.
uint Seed = ComputeSeedFromPosition(Pos);
Static Mesh Spawner ノード
ノード設定の [Execute on GPU (GPU で実行)] オプションを切り替えることで、Static Mesh Spawner ノードに GPU で実行させることができます。
プロシージャルなインスタンス化
Static Mesh Spawner が GPU で実行されるように設定している場合、メッシュ インスタンスは GPU で完全にセットアップされるため、CPU 時間とメモリが節約されます。 これには、プロシージャルなインスタンス化スタティックメッシュ コンポーネントが使用されます。 これはメッシュをスポーンするための非常に効率的なパスになりますが、実験的機能であり、次のトレードオフを伴います。
インスタンスは、どのような方法でも保持または保存されません。 GPU メモリに存在するのはランタイム時のみです。
したがって、この主なユースケースはランタイム生成です。
静的ベイク ライティングと HLOD は保持されたインスタンス情報を必要としており、現時点ではサポートされていません。
次に挙げるいくつか機能は現在、インスタンス データに CPU がアクセスする必要があり、サポートされていません。
コリジョン/物理
Navigation
レイ トレーシング
ディスタンス フィールドのライティングに影響を与える
GPU 実装は実験的機能であり、スタティックメッシュ スポナーの機能がすべてサポートされているわけではありません。
メッシュ セレクタ タイプ
次のメッシュ セレクタは、GPU での実行時に使用できます。インスタンスの割り当て方法によって、動作が多少異なります。
Weighted (PCGMeshSelectorWeighted)
CPU 実装と同様に、このモードでは入力ポイントのランダム シードおよび設定済みの選択のウェイトを使用して、各インスタンスのメッシュをランダムに選択します。 これらのメッシュは属性によって設定されないので、ノード上に設定する必要があります。
システムはウェイトを使用して、各メッシュに割り当てるインスタンスの数を決定します。 過剰割り当ては、1 つまたは複数のプリミティブへの割り当てが飽和してインスタンスが失われる可能性を最小限に抑えるためのヒューリスティックに基づいて行われます。
このモードは、たとえば、指定されたシェーダー関数「ComputeSeedFromPosition()」を使用するなどで、適切に初期化されているポイントのシード属性に依存します。 すべてのポイントのシードが同じ値に設定されている場合、すべてのポイントに対して同じ選択が行われることになり、推定される割り当てを超えることがあるため、結果からインスタンスが欠落することがあります。
By-Attribute (PCGMeshSelectorByAttribute)
現時点では、他のメッシュ セレクタ タイプ (PCGMeshSelectorWeightedByCategory など) は、GPU での実行時には使用できません。
最終的な割り当てインスタンス数を調べるには、生成されたプロシージャルにインスタンス化されたスタティックメッシュ コンポーネントを選択して、Num Instances プロパティを確認します。
インスタンス データをパッキングする
CPU 実行と同様に、属性をインスタンス データにパッキングすることができます。
システムでは、GPU 実行の前に、いくつの属性がパックされるかを把握しておく必要があるため、属性別のパッカー タイプ (PCGInstanceDataPackerByAttribute) のみをサポートしています。
その他のノード
以下のノードが現在 GPU 実行をサポートしています。
Copy Points
Attribute Partition
現時点では、String、Soft Object Path、Soft Class Path 型の属性でのパーティション化のみがサポートされています。
Normal To Density
データ数
スタティックメッシュスポナー
Custom HLSL
CPU 実行はサポートされていません。
コンピュート ソース
コンピュート ソース アセットにより、ソース コードの共有が容易になり、ノード間でのコードの重複が削減されます。
このアセットでは、HLSL ソース コードのインライン編集がサポートされており、構文ハイライトや、データ ラベルや属性名などの PCG 固有の構文が利用できます。
コンピュート ソース アセットは、複数のコンピュート ソース間の依存関係階層を作成する [Additional Sources (追加のソース)] プロパティを使用して他のコンピュート ソース アセットを参照することもできます。
データ ラベル
データ ラベルを使用すると、カスタム HLSL ソースのインデックスではなくラベルでデータを参照できます。 データ ラベルは、プレフィックス PCG_DATA_LABEL が付いたタグを介してデータ上でやり取りされます。
一部のノードは、出力データに自動的にラベルを付けます。それには以下があります。
Get Texture Data
Get Virtual Texture Data
Generate Grass Maps
草マップを生成中
PCG は、ランタイムのプロシージャル生成ワークフローに対応するため、指定したランドスケープ マテリアルからのランドスケープ草レイヤーのサンプリングをサポートしています。
Landscape Grass Output ノードを使用してランドスケープ マテリアルを設定します。 ランドスケープ マテリアルの設定の詳細については、「ランドスケープ マテリアル」を参照してください。
ランドスケープ データを Generate Grass Maps ノードに接続します。 オーバーライドまたは除外を使用して、目的の草のタイプを直接選択します。
草マップ テクスチャをサンプリングします。 インデックスでサンプリングすることも、自動的に割り当てられたデータ ラベルでサンプリングすることもできます。 次のコードは、HLSL ソース エディタ ウィンドウの [Shader Source] フィールドに追加されています。
float3 Min = GetComponentBoundsMin();
float3 Max = GetComponentBoundsMax();
float3 Position = CreateGrid2D(ElementIndex, NumPoints, Min, Max);
uint Seed = ComputeSeedFromPosition(Position);
Position.xy += (float2(FRand(Seed), FRand(Seed)) - 0.5) * 45.0;
Position.z = LS_GetHeight(Position);
float Density = FRand(Seed);
float Thresh = GrassMaps_SampleWorldPos('GSM_PCGGrass1', Position.xy).x;
草マップ テクスチャのサンプリングを GPU のみで行う場合は、PCG グラフで [Skip Readback to CPU (CPU へのリードバックをスキップ)] をオンに切り替えると、パフォーマンスが大幅に向上します。
ペイントされたランドスケープ レイヤー:
生成結果:
PCG で仮想テクスチャを使用する
PCG では、プロシージャル コンテンツ生成ワークフローの一環として仮想テクスチャの使用をサポートしています。
仮想テクスチャのサンプリング
仮想テクスチャをランドスケープ データからサンプリングすることで、高さサンプリングのパフォーマンスを向上させることができます。
例 1:ランドスケープ データ
仮想テクスチャを使用してランドスケープ データをサンプリングするには、Get Landscape Data ノードの設定で [Sample Virtual Textures (仮想テクスチャをサンプリング)] がオンになっていることを確認してください。 これにより、Landscape Data ノードは、対応するランドスケープ マテリアルを介して提供される仮想テクスチャを使用できるようになります。
これは、GPU サンプリングにのみ影響します。
// Get Position and Height
float3 Position = CreateGrid2D(ElementIndex, NumPoints, GetComponentBoundsMin(), GetComponentBoundsMax());
Position.z = A_GetHeight(Position);
// Get Normal and Orientation
const float3 Normal = A_GetNormal(Position);
const FQuat Orientation = QuatFromNormal(Normal);
// Get Base Color
const float3 BaseColor = A_GetBaseColor(Position);
例 2:仮想テクスチャ データ
仮想テクスチャをサンプリングするには、ワールドをクエリしてランタイム仮想テクスチャ コンポーネントを探します。 それぞれが、ランタイム仮想テクスチャ アセット用のデータ ラベルでタグ付けされた仮想テクスチャ データを生成します。
float3 Position = CreateGrid2D(ElementIndex, NumPoints, GetComponentBoundsMin(), GetComponentBoundsMax());
// Sample virtual textures
bool bInsideVolume;
float3 BaseColor;
float Specular;
float Roughness;
float WorldHeight;
float3 Normal;
float Displacement;
仮想テクスチャ プライミング
生成の前に仮想テクスチャがプライムされていることの確認が重要です。プライムされていない場合、サンプリング結果が不正確になる可能性があります。
仮想テクスチャ プライミングを要求するには、タイプ FPCGVirtualTexturePrimingInfo のグラフ パラメータを PCG グラフに追加します。 これで、次のオプションが公開されます。
Virtual Texture (仮想テクスチャ) | プライムされる仮想テクスチャ アセットを定義します。 |
Grid (グリッド) | グラフでこの仮想テクスチャがサンプリングされる最大のグリッドを定義します。 仮想テクスチャは、このグリッドによって決まる生成半径に対してプライムされます。 |
World Texel Size (ワールド テクセル サイズ) | プライムされた仮想テクスチャのテクセルの想定サイズを定義します。 これにより、どのミップ マップ レベルをプライムするかを決定します。 |
コンソール コマンド pcg.VirtualTexturePriming.Enable を使用して、仮想テクスチャ プライミングを制御できます。 この機能は、pcg.VirtualTexturePriming.DebugDrawTexturePrimingBounds コマンドを使用してデバッグできます。