#UE4 #UE4Study Character #HairCloth #HairShadingModel #AdvancedLocomotionSystem ファサっと天使の輪と束感でUEのヘアーの使い方

服と髪をなびかせるHair Clothはこれをやった
https://docs.unrealengine.com/4.27/ja/InteractiveExperiences/Physics/Cloth/Overview/
1, [Section Selection (セクション選択)]
2,左クリックを使って、クロスとして使用したいメッシュの一部を選択します。次に右クリックして、コンテキスト メニューを開いて Cloth アセットを作成します。
3,コンテキスト メニューから、[Create Cloth Asset from Selection (選択したものから Cloth アセットを作成)] を選びます。

 A,Asset Name – 後で簡単に見つけられるようにアセットに名前を付けてください。

 B,Remove from Mesh – クロスとして関連付けたい別個のジオメトリのメッシュの構成要素があれば、このオプションを有効にします。そうでなければ、チェックを入れずにこのままにします。

 C,Physics Asset – Cloth アセットがキャラクター用ならば、その Physics アセットを使ってクロス シミュレーションで適切なコリジョンが生じるようにします。

4,[Create] ボタンをクリックします。
5,セクションを再度右クリックして、コンテキスト メニューを表示させて、[Apply Clothing Asset] にマウスをかざし、利用可能なクロス アセットから適用するものを選択します。これで作成した任意のクロス アセットが選択したセクションに関連付けられます。

・ペイント – マウスの左ボタン
・消去 – Shift キー + マウスの左ボタン
・クロスのプレビュー – H キー

[Window] を選択し、リストから [Clothing] を選択します。
[Clothing Data] リストから選択します。

[Activate Cloth Paint] ボタンをクリックして、選択した Cloth アセットをペイントするために使用可能なプロパティを有効にします。

・ブラシの半径を5にして
・強度を0.2
・フォールオフ0.5
でヘアをクリックすると塗れる。ピンクが塗ってない場所

走ってみると

髪が前に来ちゃう

ので

物理ボディを修正した

全骨コリジョン作ったほうが調整しやすかった。(指は消した)

Spine5がこういった設定 Radius 10以下ぐらい

以下は昔の設定

で設定することが重要

でやっといい感じ

HairShadingModel 基本はこれをやった。

つまりこれで髪の天使の輪みたいなものができる。 (まわしてみないと分からない)

でも髪の束感は出したかったのでOpacityMaskもありにするとこうなる。

束感のために使ってるテクスチャはこれで

https://drive.google.com/file/d/11JcBV0dAtrexQew0fbKUZcLRfbYn7FuZ/view?usp=sharing

こんな感じにスキャッター、スペキュラ、ラフネスにMultyplyしたらいい感じになった。

使っているMIでの値はこんな感じ

最後にまたこれをやって

やっとこうなった

元のモデルはここ

https://www.deviantart.com/xcrofty/art/NieR-Automata-A2-678696387

[Unreal Engine 5.3.2] Create a Cloth Simulation の使い方と流れ

unreal engine 5.3.2 create a cloth simulation How to use and flow

UnrealEngine5.3.2のCloth Toolの使い方と流れ。

0,再生ヘッドは止めておくべき
1,該当のマテリアルを Isolate でシングル表示後に
2,メッシュ右クリックからData >Create 


3,Window>Clothから作られた>Dataを選択
4,「Activate Cloth Paint」押す


5,ピンクになる Cloth WindowのBrushプロパティでる。


6,Cloth WindowのBrush> Radias 15.0程度に
7,Clothで動かしたいところをを白に塗る
8,「Deactivate Cloth Paint」押す 
9、メッシュ右クリック>Apply Clothing Dataでできる。
9,Preview Animation▼でWalkやRunで確認 再生ヘッドを再生する
10,SkeltalMesh保存
11,PhysicsAssetを開く
12,Details>BodySetup>Primitives>Capsules>Index[0]>
13,Radiusを減らす
14,Rotationも合わせる
15,PhysicsAssetを保存
16,Preview Animation▼でWalkやRunで確認
17,SkeltalMesh開きなおしでPhysicsAssetの修正が反映される様子。

別のメッシュからCloth Dataをコピーするには?

1,Add Clothing で追加できる。

2,9、メッシュ右クリック>Apply Clothing Dataでできる。

修正する場合の使い方と流れ


1,該当のマテリアルを Isolate でシングル表示後に
2,メッシュ右クリックからRemove Clothing Data する。>>必要はない。
3,(4,「Activate Cloth Paint」押す )からの流れをやり直す

・マテリアルが透明のTranslusentだとピンクが表示されないことがある。青に塗ると色が混ざって緑とかになる。
・メッシュの割りsubDivisionLevelは多くないと成功するものも成功しない。
・ClothのDeactiveClothPaintはすごく処理が重い。


・処理の早いマシンでならMarvelous Designerで作ったメッシュでもなんとか塗れる。


・Marvelous Designerで作った複雑なプリーツなどは再現されにくい。


・Runで前にあるスカートは太ももで蹴り上げてしまうので、ポリゴン数は少なめのほうがいいかも、割りは多い方がいいのでバランスが重要


・今回成功した前面の割りはこんなもの。

困った場合に成功したスカートだけのポリゴンデータを載せておく

Skirt_Short_Cage2_Middle_Koshi.fbx これだけダウンロードできます。

https://drive.google.com/file/d/18SzHq33gl-FMdSjuai_5FXDudgZiWxQc/view?usp=sharing

揺れのためには

全骨子リジョン作ったほうが調整しやすかった(指は消した)

でキチンと設定することが重要

成功した状態

参考URL

自分用リンク

jennie9_6_v12z_v00145_4JacketMiniSkirt_CageSizeedSW.zip

https://drive.google.com/file/d/1KGYQ4AlubC05BAtDRw5o5UKXlnh_XNwg/view?usp=sharing

jennie9UE532.zip

https://drive.google.com/file/d/156VO3HnXSrQEzEfB9UHOAPO3Q82FoZbl/view?usp=sharing

エラー集

DataでCreateでのエラー

三角形が縮退しているため、衣類シミュレーション メッシュの生成に失敗しました。三角形内に一致する頂点が見つかりました
Failed to generate clothing sim mesh due to degenerate triangle, found conincident vertices in triangle

とか言われたらクリーンアップしてバインドしなおしになっちゃう。。。

https://forums.unrealengine.com/t/failed-to-generate-clothing-sim-mesh-due-to-degenerate-triangle/94634/2

おそらく頂点が別の頂点の上に重なっていることを意味します。Blender では、Remove Doubles を実行してこれを修正します。

Remove Doublesは名前がMerge by Distanceに変わっただけです。

治らない。。。。

こうも書いてあった。

「出力単位をメートルではなくセンチメートルに変更してみてください。」

ミリメートルに変更した!

治った。

でも、できたのは後ろ髪だけ。

ほかはFailedなので作り直しが必要だった。MayaではNurbs CircleをLoftで全部作れた。

自分用 Hair_Furcraea_Plant_NurbsLoftV2.zip

https://drive.google.com/file/d/1ByJfw5QSSNDOQsdk_q9LjZPVS-n5bnEb/view?usp=sharing

Clothでひとふさずつ動かそうとしたらひどかった ボリュームがなくなった。つぶれた。

これならばKawaiiPhysicsのほうがいいかも?

と思ったが全体をやってみた。ボリュームは確かになくなるけど、ある程度形状は保っている感じ。いいのかもこれで。

ということで髪の毛全体テスト

自分用 Hair_Furcraea_Plant_NurbsLoftV3.zip

https://drive.google.com/file/d/1z4aipUFdHk19qCcrBb9bWvsf3KpWvlG9/view?usp=sharing

できたのがこれ ちょっとつぶれるし伸びた印象

でキャラごとmmで出力したけど

Preview Animationするとすごいちっさくなった。キャラBPで拡大すればいいでしょとおもっていたらそれは問題無い様子。

Dataを作り塗ることができた。Falloffは1.0にするともっとなだらかになるはず。

けども。DeactiveClothPaint後の様子がすごいバグ。

わーん

ということでmmにしてもキャラクターだとエンジンのサイズ計算がバグってますので使わないことにしました。

フォーラムに投稿しました。

https://forums.unrealengine.com/t/failed-to-generate-clothing-sim-mesh-due-to-degenerate-triangle-found-conincident-vertices-in-triangle/1678556

mmでは調整したスカートも壊れる

単位はcmにして後ろ髪はCloth 、前髪、左髪、右髪はスキンウェイトかKawaiiPhysicsにしておわりだなこりゃ。

完成2

ゲームでの再生

自分用 jennie9_6_v12z_v00148_HairFurcraea_mmSW.zip

https://drive.google.com/file/d/1FDRjjub_SM___Yb-u_kv5cwspP-1NdVf/view?usp=sharing

自分用 Hair_Furcraea_Plant_NurbsLoftV7_FullLoft.zip

https://drive.google.com/file/d/1pnZHcPUl-wykW3DBE_RcYHBIJ2Ks2N4-/view?usp=sharing

[UE5][BackUp]Cppプロジェクトでいらないフォルダを含めずにバックアップzipを作成するバッチを作った件

gitだと大容量なサーバーとか用意するの大変だから・・・

実行内容はこんなかんじ

D:\Sandbox\BookAnimation_Codex\UE574Book\UE5CppFolder_MakeBackUpZip.bat
にフォルダをドラッグしたら
中身の
.vs
Binaries
Build
DerivedDataCache
Intermediate
Saved
(pluginsのプラグイン名フォルダ内BinariesとIntermidiateも消してます)
を除いた内容のzipを
D:\Sandbox\BookAnimation_Codex\UE574Book\ドラッグしたフォルダ名.zipに作るバッチを作った
zip実行中になんでもいいからプログレスバーとパーセントを表示するようにした

※バックアップからの復旧方法

VisualStudioなどでビルドします。

UE5CppFolder_MakeBackUpZip.bat

@echo off
setlocal EnableExtensions

if "%~1"=="" (
    echo Usage:
    echo   Drag a folder onto this bat file.
    echo.
    pause
    exit /b 1
)

set "BACKUP_SOURCE=%~f1"
if not exist "%BACKUP_SOURCE%\" (
    echo Error: folder not found.
    echo   %BACKUP_SOURCE%
    echo.
    pause
    exit /b 1
)

set "BACKUP_ZIP=%~dp1%~nx1.zip"
set "BACKUP_SCRIPT=%~dp0UE5CppFolder_MakeBackUpZip.ps1"

echo Source:
echo   %BACKUP_SOURCE%
echo.
echo Output:
echo   %BACKUP_ZIP%
echo.
echo Excluding folders:
echo   .vs Binaries Build DerivedDataCache Intermediate Intermidiate Saved
echo.

if not exist "%BACKUP_SCRIPT%" (
    echo Error: helper script not found.
    echo   %BACKUP_SCRIPT%
    echo.
    pause
    exit /b 1
)

powershell -NoProfile -ExecutionPolicy Bypass -File "%BACKUP_SCRIPT%" -Source "%BACKUP_SOURCE%" -ZipPath "%BACKUP_ZIP%"
set "BACKUP_ERROR=%ERRORLEVEL%"

if not "%BACKUP_ERROR%"=="0" (
    echo.
    echo Failed.
    pause
    exit /b %BACKUP_ERROR%
)

echo.
echo Done.
pause

UE5CppFolder_MakeBackUpZip.ps1

param(
    [Parameter(Mandatory = $true)]
    [string]$Source,

    [Parameter(Mandatory = $true)]
    [string]$ZipPath
)

$ErrorActionPreference = 'Stop'

$sourceFullPath = [System.IO.Path]::GetFullPath($Source).TrimEnd('\', '/')
$zipFullPath = [System.IO.Path]::GetFullPath($ZipPath)

$exclude = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
'.vs', 'Binaries', 'Build', 'DerivedDataCache', 'Intermediate', 'Intermidiate', 'Saved' | ForEach-Object {
    [void]$exclude.Add($_)
}

function Test-IsExcludedBackupFile {
    param([Parameter(Mandatory = $true)][string]$FileFullPath)

    if ([System.StringComparer]::OrdinalIgnoreCase.Equals($FileFullPath, $zipFullPath)) {
        return $true
    }

    $relative = $FileFullPath.Substring($sourceFullPath.Length).TrimStart('\', '/')
    foreach ($part in ($relative -split '[\\/]')) {
        if ($exclude.Contains($part)) {
            return $true
        }
    }

    return $false
}

Add-Type -AssemblyName System.IO.Compression
Add-Type -AssemblyName System.IO.Compression.FileSystem

if (Test-Path -LiteralPath $zipFullPath) {
    Remove-Item -LiteralPath $zipFullPath -Force
}

Write-Host 'Scanning files...'
$files = @(
    Get-ChildItem -LiteralPath $sourceFullPath -Force -Recurse -File | Where-Object {
        $fileFullPath = [System.IO.Path]::GetFullPath($_.FullName)
        -not (Test-IsExcludedBackupFile -FileFullPath $fileFullPath)
    }
)

$total = $files.Count
Write-Host ("Files to zip: {0}" -f $total)

$zip = [System.IO.Compression.ZipFile]::Open($zipFullPath, [System.IO.Compression.ZipArchiveMode]::Create)
$count = 0

try {
    if ($total -eq 0) {
        Write-Progress -Activity 'Creating backup zip' -Status 'No files to zip' -PercentComplete 100
    }
    else {
        foreach ($file in $files) {
            $count++
            $fileFullPath = [System.IO.Path]::GetFullPath($file.FullName)
            $relative = $fileFullPath.Substring($sourceFullPath.Length).TrimStart('\', '/')
            $entryName = $relative -replace '\\', '/'
            $percent = [int][Math]::Floor(($count * 100.0) / $total)

            Write-Progress `
                -Activity 'Creating backup zip' `
                -Status ("{0}%  {1}/{2}  {3}" -f $percent, $count, $total, $entryName) `
                -PercentComplete $percent

            if (($count % 25) -eq 0 -or $count -eq 1 -or $count -eq $total) {
                Write-Host ("{0,3}%  {1}/{2}  {3}" -f $percent, $count, $total, $entryName)
            }

            [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
                $zip,
                $fileFullPath,
                $entryName,
                [System.IO.Compression.CompressionLevel]::Optimal) | Out-Null
        }
    }
}
finally {
    $zip.Dispose()
    Write-Progress -Activity 'Creating backup zip' -Completed
}

Write-Host ("Created: {0}" -f $zipFullPath)
Write-Host ("Files: {0}" -f $count)

[UE5.8.0][Maya][Retarget] TposeのキャラクターモデルをAposeのMannequinのモーションにリターゲットする方法

MM_T_Pose をエクスポート

Export Optionはこう

MayaにFBXインポートした状態で保存する SKM_Quinn_Simple_Tpose.ma

Tposeのキャラクターモデル(ここではfanModelのサイトからダウンロードしたものを用意した)

https://www.deviantart.com/d-presso/art/Nier-Re-in-carnation-Levannia-XPS-DL-880627377

を開いて


先ほどのTposeのFBXをインポートして

Root ( SKM_Quinn_Simple_Tpose:root_Quinn_T_pose ) のトップ のjointをスケールしてキャラクターにあわせる。

複製してフリーズする

以下ツールでスキンウェイトをコピー

SkinWeightCopy_First_Select_MeshGroup_to_Second Select_MeshGroup.mel

// SkinWeightCopy First Select MeshGroup to Second Select MeshGroup 
string $selectedArrFUllPath[] = `ls -long -sl`;
print($selectedArrFUllPath);

string $FirstSelect=$selectedArrFUllPath[0];

string $SecondSelect=$selectedArrFUllPath[1];

string $rejectArr[];

//string $inputNodes[] = `ls -type transform -long -dag $FirstSelect`;
//string $destNodes[] = `ls -type transform -long -dag $SecondSelect`;

string $inputNodes_mesh[] = `ls -type mesh -long -dag $FirstSelect`;
string $destNodes_mesh[] = `ls -type mesh -long -dag $SecondSelect`;

$inputNodes_meshlong=size($inputNodes_mesh);
$destNodes_meshlong=size($destNodes_mesh);

string $inputNodes[];
string $destNodes[];
clear $inputNodes;
clear $destNodes;
string $mesh;
string $parent;
for($d0 = 0; $d0 <$inputNodes_meshlong;$d0++){
    $mesh=$inputNodes_mesh[$d0];
    string $parentS[] = `listRelatives -parent -path -type transform $mesh`;
    $parent=$parentS[0];
    $inputNodes[size($inputNodes)] = $parent;
}
for($d0 = 0; $d0 <$destNodes_meshlong;$d0++){
    $mesh=$destNodes_mesh[$d0];
    string $parentS[] = `listRelatives -parent -path -type transform $mesh`;
    $parent=$parentS[0];
    $destNodes[size($destNodes)] = $parent;
}

print("$inputNodes= ------------------------------------------------ \n");
print($inputNodes);

print("$destNodes= ------------------------------------------------ \n");
print($destNodes);



$inputNodeslong=size($inputNodes);
$destNodeslong=size($destNodes);

string $buffer[];
string $buffer_i[];
$finded = 0;
for($d = 0; $d <$destNodeslong;$d++){
    string $destNode_name=$destNodes[$d];
    
    if($destNode_name==$SecondSelect){
            
    }else{
        print("$destNode_name= "+$destNode_name+"\n");
        
        $numTokens = `tokenize $destNode_name "|" $buffer`;
        $bufferlong=size($buffer);
        string $destNode_name_Short = $buffer[$bufferlong-1]+"";
        print("$destNode_name_Short= "+$destNode_name_Short+"\n");
        $finded = 0;
        for($i = 0; $i <$inputNodeslong;$i++){
            string $inputNode_name=$inputNodes[$i];
            $numTokens_i = `tokenize $inputNode_name "|" $buffer_i`;
            $bufferlong_i=size($buffer_i);
            string $inputNode_name_Short = $buffer_i[$bufferlong_i-1]+"";
            print("$inputNode_name_Short= "+$inputNode_name_Short+"\n");
                
            //$index=`gmatch $inputNode_name $destNode_name_Short`;
            //if($index > 0){
            if($inputNode_name_Short==$destNode_name_Short){
                //$blendShapeName = $blendshapeRet_name;
                print("$destNode_name= "+$destNode_name+" isHit!! "+"\n");
                select -r $inputNode_name;
                select -add $destNode_name;
                copySkinWeights  -noMirror -surfaceAssociation closestPoint -influenceAssociation closestJoint;
                //copySkinWeights -noMirror -surfaceAssociation closestPoint -influenceAssociation closestJoint -sourceSkin $inputNode_name -destinationSkin $destNode_name;
                $finded = 1;
            }//if
        }//for
        if($finded==0){
            $rejectArr[size($rejectArr)] = $destNode_name;
        }//if
    }//if
}//for
print("----rejected_list---start"+"\n");
print($rejectArr);
print("----rejected_list---end"+"\n");
select -r $FirstSelect ;
select -add $SecondSelect ;

適当にスキンウェイトを確認

rootとMesh 選択してFBX出力

UEへインポート

IKRig作成

IKRig設定

マネキンのほうはこう

IK Retargeter 作成

SounceにCreate>Import From Animation Sequence

MM_T_Pose選択

ポーズがそろう

Op Stack >Add Default Ops 押す とそろった

あとは必要なアニメーションを選択してエクスポート

追加で調整した作業 RootMotionを切ってエクスポートしないとだめだった

そのあとは以下を参考にしてください。

[UE5.8]UEをログ付きで起動

Shell

Start-Process -FilePath ‘D:\Program Files\Epic Games\UE_5.8\Engine\Binaries\Win64\UnrealEditor.exe’ -ArgumentList @(‘D:\Sandbox\BookAnimation_Codex\UE574Book\UE574Book 5.8\UE574Book.uproject’,’-log’)


Start-Process -FilePath 'D:\Program Files\Epic Games\UE_5.8\Engine\Binaries\Win64\UnrealEditor.exe' -ArgumentList @('D:\Sandbox\BookAnimation_Codex\UE574Book\UE574Book 5.8\UE574Book.uproject','-log')

UE4の場合 ログを出すので、これでShader Compileが止まってるか見えるようになる。

Start-Process -FilePath ‘D:\Program Files\Epic Games\UE_4.26\Engine\Binaries\Win64\UE4Editor.exe’ -ArgumentList @(‘D:\Sandbox\UE426ArchVizInterior\UE426ArchVizInterior\UE426ArchVizInterior.uproject’,’-log’)

[UE5.7.3] Deferred ShadingかForward Shading設定によって変わるもの変わらないもの

Unreal Engine 5(UE5)におけるディファード(Deferred)とフォワード(Forward)レンダリングの設定は、プロジェクトのターゲット端末(PC/コンソールかモバイルか、VRか)によって異なります

設定方法とそれぞれの使い分けを解説します。

Deferred ShadingかForward Shading設定

1. 設定の変更方法 (Forward Shading)

UE5はデフォルトで「ディファードレンダリング(Deferred Rendering)」が有効になっています。フォワードレンダリングに変更したい場合、以下の手順で行います。

  1. [Edit (編集)] > [Project Settings (プロジェクト設定)] を開く。
  2. [Engine] > [Rendering] セクションを選択。
  3. [Forward Shading] カテゴリを探す。
  4. [Forward Shading] チェックボックスをオンにする(フォワード)、またはオフ(ディファード)にする。
  5. プロジェクトを再起動する。

2. ディファード vs フォワードの使い分け

特徴 [1, 2, 3]ディファード (Deferred)フォワード (Forward)
主な用途PC, コンソール, ハイエンドVRモバイル, 軽量VR, VR軽量化
光源数制限なし、大量のライト少ない(主要ライトのみ)
機能Lumen, Nanite対応基本非対応(機能制限)
メモリ/負荷大容量、パスが多くメモリ転送多MSAAが利用可能

ディファード(デフォルトDeferred Shading)

  • メリット: 高品質なライティング、多数のライト、LumenやNaniteなどの高機能。
  • デメリット: フォワードに比べてGPU・メモリ負荷が高い。

フォワード(Forward Shading)

  • メリット: 高いパフォーマンス(軽量)、MSAA(高品質なアンチエイリアス)が使える、VRなどで負荷を下げたい場合に有効。
  • デメリット: 多数のライトや複雑な影の表現が苦手。

3. モバイル向けの設定 (モバイルフォワード)

モバイルでは、さらに専用のレンダリングパイプラインが推奨されます。 [1]

  1. Project Settings > Platforms > Android/iOS > Rendering
  2. [Forward Shading] を有効にするか、[Mobile Deferred] を選択。
  3. 負荷を抑えるため、[Local Lights Buffer] などの詳細設定を調整。

まとめ

  • 高グラフィックPCゲーム: デフォルトのまま(ディファード)。
  • VR / 軽量化したいプロジェクト: Forward Shadingをオン。
  • モバイルゲーム: Mobile Forward または Mobile Deferred を選択。 [1, 2]

設定変更後はシェーダーの再コンパイルが発生するため、少し時間がかかります。

左がDeferred 右がForward

今回の場合

UE標準のライティングモデルに乗せるのではなく、UnlitのEmissive側でNdotLを計算してRampを参照しているため、DeferredかForwardかによるGBufferやライト計算の差分を受けにくい構成にしています。一方で、標準の影やGIを使う場合はLit系に寄せる必要があり、その場合はレンダリングパス差分を考慮します。

Unlit自前ライティングなら、Deferred / Forward差はほぼない。Litに乗せるなら差が出る

[UE5.7.3][RenderDoc]RenderDocでGPU計測する方法

https://renderdoc.org

Latest Stable Build(.zip) を選ぶ

それは初回起動時の匿名データ収集の確認画面
一番下を選べばOK

「Do not gather or submit any statistics.」

起動する

Executable Pathに UEのパスを入れる

D:\Program Files\Epic Games\UE_5.7\Engine\Binaries\Win64\UnrealEditor.exe

Command Line ArgumentsにUEプロジェクトのパスを入れる


D:\Sandbox\UE573petit25Cl\UE574petit25Cl_Lighting\UE574petit25Cl.uproject

Lunchで起動すると

RenderDoc経由でUEが起動する

UE開いたら

UEにフォーカス当てて👉 F12押す

出てきたキャプチャをダブルクリックすると

Filterを使って描画やCompute処理だけに絞って確認しています。
DrawCallはDrawIndexed DrawInstanced Dispatch Clearなので

Dispatch をFillterしてみると見えた。

Filterはこう使う👇

■ ■ 重い描画だけ見たい

Draw

■ ■ Computeだけ

Dispatch

■ ■ 特定のPass

BasePass

どのDrawCallを見るべきか?

見る順番はこれでOK。

1. まず「大きいPass名」を見る

UEならこのあたりを探す。

ShadowDepths
影が重いか見る。

BasePass
メッシュ本体の描画。マテリアルやテクスチャ参照を見る。

Lighting / DeferredLighting
ライト計算を見る。

Translucency
半透明。重くなりやすい。

PostProcess
Bloom、Tonemap、DOF、独自ポストを見る。

2. 次に、その中のDrawを見る

Passを開いて、こういう行をクリックする。

DrawIndexed
DrawInstanced
Dispatch

クリックしたら右側で見る場所は3つ。

Texture Viewer
→ 何が描かれているか見る。

Pipeline State
→ どのShader、Texture、Blend設定か見る。

Mesh Viewer
→ どのメッシュを描いているか見る。

まずShadow、BasePass、Translucency、PostProcessなどの大きいPass単位で見て、次にDrawIndexedやDispatchを選んで、RenderTarget・Shader・Texture参照を確認します。

最初に見るおすすめ

迷ったらまずこれ。

BasePassのDrawIndexed  や  PostProcessのDraw/Dispatchだが
→ マテリアル、テクスチャ、メッシュが確認しやすい。
BassPassが出たらクリックしてフラッグを立てるそして、Filterを解除

フラッグが立っている場所までスクロールすると中が見える状態

ExecutecommandListに入ってるのが見えないので。設定を変えてキャプチャし直し。

DX12ではExecuteCommandListsとしてまとまって見える場合があるので、RenderDocではCapture all Cmd Listsを有効にするか、確認用にDX11で起動してDrawIndexed単位で確認します。

■ やり直す設定

RenderDocの Launch Application 画面でチェックする:

  • Capture all Cmd Lists
  • Ref all Resources も付けてOK

DX11でやる

Command Lineにこれ入力👇

"D:\Sandbox\UE573petit25Cl\UE574petit25Cl_Lighting\UE574petit25Cl.uproject" -d3d11 -NoRHIThread

DX12ではDrawCallがコマンドリストにまとまるため、Pass単位で処理を確認しつつ、必要に応じてDX11でDrawIndexed単位でも確認しています。

見つかった!

DrawIndexedInstanced(6, 17)

意味:

  • Index数:6(1ポリの簡単な形)
  • Instance数:17(同じものを17個描画)

👉 パーティクル or 草(インスタンシング)

DrawIndexedInstancedを見て、インスタンシングで同じメッシュを複数描画していることを確認できます。

1回のDrawCallで複数インスタンスを描画しているため、DrawCall削減による最適化がされています。

次見るべきポイント PSSetShader (Pixel Shader)

重そうか(分岐 / テクスチャ数) マテリアル名

PSSetShaderResources テクスチャ数(ここ重要)

見る

  • 何枚使ってるか
  • 無駄に多くないか

目安

  • 1〜3枚 → 軽い
  • 4〜6枚 → 普通
  • 7枚以上 → 重い可能性

このDrawはまだ画面を全部埋めてない


■ ここでやるべき操作(超重要)

■ ① Eventを少しずつ進める

👉 左のEvent Browserで

  • ↓キー or クリックで1個ずつ進む

■ ② 右のTexture Viewerを見る

👉 変化を見る

変わった

■ 今起きてること

👉 Eventを進めたことで

  • 上の黒い部分に
  • 小さい点(葉っぱ)が出てきた

👉 つまり

このDrawが実際に画面に何かを描いてる


■ 今のDrawの正体

左を見ると👇
DrawIndexedInstanced(6, 16)

👉 意味

  • 小さいメッシュ(葉っぱ)
  • 16個まとめて描画

👉 つまり

パーティクル or インスタンス草

■ ① このDrawで何が変わった?

👉 右画面で見る

  • 点が増えた
  • 画面に追加された

👉 これ言える

「このDrawでパーティクルが追加されているのが確認できます」

イベントを進めることで、最初は未描画だった画面が、各Drawによって徐々に埋まっていく様子を確認できます。

チェッカーが消えるタイミングを見ることで、どの描画処理が最終的な画面に影響しているかを特定できます。

RenderDocではイベントを進めながら、どのDrawで画面に要素が追加されるかを確認しています。今回のケースでは、インスタンシングされたパーティクルが描画されているのが確認できます。

このようにDrawごとの変化を見ることで、描画順や負荷のかかる処理を特定しています。

■ ここまでできてること

  • DrawCall見つけた
  • 実際の変化を追えてる
  • インスタンシング理解してる

■ どういう意味?

RenderDocの流れ👇

  1. 最初
    👉 何も描いてない(黒 / チェッカー)
  2. 途中
    👉 一部だけ描画(点・葉っぱ)

  3. 👉 全体が描画で埋まった ← 今ここ

👉 つまり

この辺のDrawで最終結果に近づいた

イベントを進めることで、最初は未描画だった画面が、各Drawによって徐々に埋まっていく様子を確認できます。

チェッカーが消えるタイミングを見ることで、どの描画処理が最終的な画面に影響しているかを特定できます。

状態は「まだ画面を全部塗るDrawに来てない」ってこと。
(チェッカーが残ってる=未描画領域がある)

■ 今の位置の意味

左を見ると👇

  • BasePass
  • DrawIndexedInstanced(6, 17)(葉っぱ)

👉 これは

“オブジェクト描画フェーズ”


👉 だから

  • 一部だけ描かれる
  • 画面全部は埋まらない
  • チェッカー残る

■ 次に探すべきもの(重要)

👉 画面を一気に埋めるDraw


■ 目印

これ探す👇

  • PostProcess
  • Tonemap
  • Fullscreen
  • Resolve
  • Composite

■ 何が起きてるか(技術的に)

👉 今のDrawで

  • SceneColorに
  • あなたのHLSLで描いた月が加算された

👉 つまり

Pixel Shaderが最終色を決めている瞬間

このDrawでは、独自のHLSLシェーダを使って月の表現を描画していて、SceneColorに対してピクセル単位で最終色を出力しています。

RenderDocでこのDrawを確認することで、実際にどのシェーダが最終結果に影響しているかを特定できます。

このようにDrawごとの出力を追うことで、意図したシェーダが正しく画面に反映されているかを検証できます。

■ ここで見るべきポイント(重要)


■ ① Pixel Shader

👉 ここ

PSSetShader

HLSLが動いてる場所

■ ② Shader Resource(テクスチャ)

👉 月の模様

Shader Resource View

■ ③ DrawIndexedInstanced

👉 描画回数

■ さらに強い視点

  • フルスクリーンじゃない → オブジェクト描画
  • 一部だけ変わる → メッシュ単位
  • ピクセルで模様 → Pixel Shader

RenderDocを使うことで、実際の描画結果とシェーダの対応関係を確認しています。

■ 結論(今回のケース)

👉 重くなりやすい要因はこれ

① パーティクル(葉っぱ)のインスタンス描画

  • DrawIndexedInstanced(6, 16/17)
  • 数が増えると一気に負荷増える

② Pixel Shader負荷

  • 独自HLSL(月の模様)
  • ピクセル単位で計算してる

③ テクスチャ参照

  • PSSetShaderResources
  • 複数テクスチャ使ってる

④ オーバードロー(これが一番重要)

👉 葉っぱ(半透明)が重なる
👉 同じピクセル何回も計算される


■ 一言でまとめると

パーティクルのオーバードロー+ピクセルシェーダ負荷


今回のケースでは、パーティクルのインスタンス描画によるオーバードローと、ピクセルシェーダの計算量が主な負荷要因だと考えています。


特に半透明オブジェクトは重なりやすく、ピクセル処理が増えるため注意が必要です。


■ もう一段上

👉 改善案も言う

  • インスタンス数制御
  • テクスチャ削減
  • シェーダ簡略化
  • LODや距離カリング

■ まとめ

👉 今回の分析

  • Draw見た
  • Shader見た
  • 結果から原因言えた

[UE5.7.4][Unreal Insights] Unreal Insightsを利用してのC++最適化方法

計測開始

計測終了

Unreal Insightsの起動

計測結果の選択

時間範囲計測の方法

左右ドラッグで位置移動、

マウスオーバーで このマテリアルの処理だとかが、わかる

左クリックで選択

右クリックでメニュー表示

シングルクリックしてから、別の位置で Ctrl + クリックで 範囲の時間を表示できる。


TRACE_CPUPROFILER_EVENT_SCOPEで関数をマークする。

public:
	virtual void Tick(float DeltaTime) override;

cpp

#include "ProfilingDebugging/CpuProfilerTrace.h"

void ASideScrollingCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	///////////////////////////////////////////////////////////////////
	TRACE_CPUPROFILER_EVENT_SCOPE(ASideScrollingCharacter::Tick);

	// 重たい処理1
	for (int32 i = 0; i < 100; ++i)
	{
		UE_LOG(LogTemp, Log, TEXT("Omotai 1"));
	}
	// 重たい処理2
	for (int32 i = 0; i < 1000; ++i)
	{
		UE_LOG(LogTemp, Log, TEXT("Omotai 2"));
	}

	////////////////////////////////////////////////////////////////////
	//////////////////////他の処理//////////////////////////////////////
	if (!bIsOnLadder)
	{
		return;
	}
}

ビルドしてから実行

TRACE_CPUPROFILER_EVENT_SCOPE の処理の箇所を検索

1,Timersで「ASideScrollingCharacter::Tick」で検索し

2,出てきたASideScrollingCharacter::Tickを右クリックしHighlighting Eventを使い

3,出てきたASideScrollingCharacter::Tickを右クリックしFind Instance>First Instanceでスレッドが見つかる

参考URL

式会社アドグローブの公式ブログ:TRACE_CPUPROFILER_EVENT_SCOPEによるお手軽C++プロファイリング![UE5.1]
https://blog.adglobe.co.jp/entry/2023/05/12/100000

※はてなブログ(mawasiの備忘録)
https://mawasi.hateblo.jp/entry/2025/06/16/023611
によると、以前のQUICK_SCOPE_CYCLE_COUNTERより、こちらのマクロが推奨されています。
Unreal Insightsの起動: Engine/Binaries/Win64/UnrealInsights.exe を実行します。
プロファイリングの実行: エディタまたはパッケージ化したゲームを、コマンドライン引数 -trace=cpu,frame を使用して起動します。
データの確認: Unreal Insights上の「Timing Insights」タブで、埋め込んだタグ(例: MyFunction_Tag)を検索して計測結果を確認します。

関連・補足情報
詳細なボトルネック調査: Qiitaの記事

https://qiita.com/nonbiri15/items/7968e55bbf4fd61ab4df

で述べられている通り、CPUとGPUのボトルネックを特定し、ボトルネックの修正に活用できます。
関数の呼び出し回数: TRACE_CPUPROFILER_EVENT_SCOPEを使用すると、処理時間だけでなく、関数の呼び出しツリーや回数も確認できます。
詳細な情報源: 株式会社ヒストリアさんの改訂版記事

https://historia.co.jp/archives/48769

では、より詳細なUnreal Insightsの使用方法が解説されています。

この方法を使うことで、ゲームパフォーマンスの改善に役立つ正確なデータを得ることができます。

[UE5.8][C++]遂に完成したC++プラグインUE用HLSL.EditorのMaterial作成機能

もうこれでノードスパゲッティから解放される

導入方法

0,以下のリンクを1つダウンロード (特に理由がなければ最新版使ってください)

furcraeaHLSLEditor_UE5.8.0V9.zip UE5.8に対応しました。
https://drive.google.com/file/d/14nWd_4X9uQvt6KjFlmgRbYp2LUYSth8o/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V8.zip float4出力に対応しました。
https://drive.google.com/file/d/1PaBHAT9O4m6DC6UceUtwrj5o8N9qrrhn/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V7.zip ポストプロセスマテリアル対応
https://drive.google.com/file/d/1ieBRb5zpW36LGldmREROGcWJ8WZot1Xg/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V6_2.zip コーディングBugFix
https://drive.google.com/file/d/1BzMiQt4dXcu8p-dIfkyH3v1SRVSKjiCn/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V6.zip コーディングBugFix
https://drive.google.com/file/d/1APYn65u1yo3xkJlDFmqJ2yuCE5zHViqc/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4V5.zip 関数インライン化によるコンパイラ整理
https://drive.google.com/file/d/1YiUHmR1g6d9WwvAtd1rGADsiNZEXRMNX/view?usp=sharing

furcraeaHLSLEditor_UE5.7.4.zip (V4) FragmentShader とVertexShader(Optional)に分離
https://drive.google.com/file/d/1gInP7W5hFB3pwlwbrbkekSzC8xOwusap/view?usp=sharing

furcraeaHLSLEditor_UE5.7.3V4.zip ユーザーが作った)CodeMaterialAssetと同じフォルダに変更
https://drive.google.com/file/d/1XhVZgV6FRiyGOOquqO5nJVFXbmg_8DA-/view?usp=sharing

furcraeaHLSLEditor_UE5.7.3V3.zip Projects と RenderCore を bBuildEditorをガード外に移動
https://drive.google.com/file/d/1Qmz5Y_uT0VGKkrk1wskvw2DRbnND6or4/view?
usp=drive_link

furcraeaHLSLEditor_UE5.7.3V2.zip 1つしかCodeMatUser.ushがない不備修正
https://drive.google.com/file/d/1CSXmSebk7hLM02qM5jKDv2ndNJ4jhUi7/view?usp=sharing

1,Pluginsフォルダにzipを解凍して入れてください。

  パスの例:UEプロジェクトフォルダ\Plugins\furcraeaHLSLEditor\Shaders

2,プラグインで「furcraeaHLSLEditor」を有効化

使用方法

コンテンツブラウザで右クリック>Miscellaneous>Code Material Assetを作成

できた New Code Material AssetをダブルクリックでHLSL編集画面が開く

Saveをクリックすると。。。GeneratedフォルダーにM_NewCodeMaterialAssetが作成されます。>CodeMaterialAssetと同じフォルダーに保存するように変更しました。


まだまだ、1つしかCodeMatUser.ushがないので一つしかマテリアルが成立しないなどの不備があるので更新していく予定です。<-以下の画像のように修正済みです。

furcraeaHLSLEditorをGitHub で公開しました。
https://github.com/nobolu-ootsuka-unrealengine/furcraeaHLSLEditor/commits?author=nobolu-ootsuka-unrealengine

修正履歴



1つしかCodeMatUser.ushがないので一つしかマテリアルが成立しないなどの不備を修正

furcraeaHLSLEditor_UE5.7.3V2

Projects と RenderCore を bBuildEditorをガード外に移動(ランタイムでも必要なモジュールのため)


furcraeaHLSLEditor_UE5.7.3V3

CodeMaterialAsset が吐くMaterialのフォルダを (固定)Generated から (ユーザーが作った)CodeMaterialAssetと同じフォルダに変更した

CodeMaterialCompiler.cpp に2箇所変更しました。

① MakeMaterialPackagePath 関数(生成先パスを決定)

  • 変更前:/Game/Generated/M_xxx 固定
  • 変更後:Asset->GetOutermost()->GetName() でアセット自身のパッケージパスを取得し、FPackageName::GetLongPackagePath()
    でフォルダ部分を抜き出して {同じフォルダ}/M_xxx を返す ② CreateOrLoadMaterial の MakeDirectory 呼び出し
  • 変更前:MakeDirectory(“/Game/Generated”) 固定
  • 変更後:MakeDirectory(FPackageName::GetLongPackagePath(MakeMaterialPackagePath(Asset))) —
    生成先パスからフォルダを算出して作成 これにより、例えば Content/0_furcraeaTokyo/CodeMaterialAsset/NewCodeMaterialAsset に保存された CodeMaterialAsset
    に対しては、生成マテリアルも同じ Content/0_furcraeaTokyo/CodeMaterialAsset/M_NewCodeMaterialAsset に出力されます。

furcraeaHLSLEditor_UE5.7.3V4

アウトライン表示用のVertexNormalを拡張のために

FragmentShader VertexShader(Optional)に分離しました!

安定性のためにincludeを辞めました。

furcraeaHLSLEditor_UE5.7.4V5.zip


ルール: FragmentShaderCode / VertexShaderCode には 関数定義を書かない。ヘルパーが必要なら全てインライン化する。
コンパイラの整理

  • ExtractHelperFunctions + エスケープトリック (将来の一般的ヘルパー対応) は保持
    // @param float3 ColorC = 0.90,0.20,1.20//でBPでパラメーター化

furcraeaHLSLEditor_UE5.7.4V6.zip


・日本語コメントがあるとVertex Shader側のコードカラーリングが効いてない不具合を修正
・こんどは両ペインで改行が入力できないを解決
・ユーザーが .ush のボディ内で Phase * Time のように Time を直接書いても View.GameTime として展開され、HLSL
コンパイルエラー → クラッシュが防がれます。

furcraeaHLSLEditor_UE5.7.4V7.zip

ポストプロセスマテリアルを CodeMaterialAssetで作れるようになりました。
Domain が「Post Process」の時に Blendable Location ドロップダウンが横に表示されます:

CustomDepth のアウトライン系には Before Tonemapping が一般的です。

自動生成パラメーターにテクスチャが指定できるようになりました。
// ===== Fragment Shader =====
// @param Texture2D AlbedoTex
// @param Texture2D HatchTex = /Game/3Dnchu/Textures/T_Stroke-SD11.T_Stroke-SD11
// @param float HatchTiling = 10.0

なぜか裏面だけに色が乗ってる場合

● Vertex Shader Code に何か入っているはずです。

Vertex Shader Code が空でないとプラグインが「シェル法アウトライン用」と判断して:

  • TwoSided = true
  • BlendMode = Masked
  • OpacityMask = TwoSidedSign × -1(裏面のみ表示) を自動設定します。これが原因です。 修正手順:
  1. CodeMaterialAsset エディタで Vertex Shader Code を完全に空 にする
  2. Save をクリックして再生成 Vertex Shader Code が空になると:
  • TwoSided = false
  • BlendMode = Opaque
  • OpacityMask なし → 表面だけに通常表示

furcraeaHLSLEditor_UE5.7.4V8.zip

 float4出力に対応しました。

furcraeaHLSLEditor_UE5.8.0V9.zip

UE5.8に対応しました。