claude-code-arcane 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +131 -41
- package/agents/game/ue-blueprint-specialist.md +125 -0
- package/agents/game/ue-gas-specialist.md +133 -0
- package/agents/game/ue-umg-specialist.md +131 -0
- package/dist/cli.js +642 -478
- package/docs/SKILLS-CATALOG.md +42 -3
- package/docs/USER-GUIDE.md +28 -54
- package/hooks/detect-unreal.sh +90 -0
- package/package.json +2 -1
- package/profiles/agile.yaml +1 -1
- package/profiles/ai.yaml +1 -1
- package/profiles/android-native.yaml +1 -1
- package/profiles/audio.yaml +1 -1
- package/profiles/backend-dotnet.yaml +1 -1
- package/profiles/backend-go.yaml +1 -1
- package/profiles/backend-nestjs.yaml +1 -1
- package/profiles/backend-nextjs.yaml +1 -1
- package/profiles/backend-ts.yaml +1 -1
- package/profiles/business.yaml +1 -1
- package/profiles/clevel.yaml +1 -1
- package/profiles/clickup.yaml +1 -1
- package/profiles/core.yaml +1 -1
- package/profiles/database.yaml +1 -1
- package/profiles/design.yaml +1 -1
- package/profiles/docs.yaml +1 -1
- package/profiles/ecommerce.yaml +1 -1
- package/profiles/finance.yaml +1 -1
- package/profiles/flutter.yaml +1 -1
- package/profiles/freelance.yaml +1 -1
- package/profiles/frontend.yaml +1 -1
- package/profiles/infra.yaml +1 -1
- package/profiles/integrations.yaml +1 -1
- package/profiles/ios-native.yaml +1 -1
- package/profiles/jira.yaml +1 -1
- package/profiles/job-hunt.yaml +1 -1
- package/profiles/marketing.yaml +1 -1
- package/profiles/mobile.yaml +1 -1
- package/profiles/regulatory.yaml +1 -1
- package/profiles/second-brain.yaml +1 -1
- package/profiles/security.yaml +1 -1
- package/profiles/self-improving.yaml +1 -1
- package/profiles/statusline.yaml +1 -1
- package/profiles/testing.yaml +1 -1
- package/profiles/unity-design.yaml +1 -1
- package/profiles/unity-dev.yaml +1 -1
- package/profiles/unreal-dev.yaml +97 -0
- package/profiles/visual-novel.yaml +1 -1
- package/rules/gamedev/unreal-code.md +125 -0
- package/skills/arcane-list/SKILL.md +12 -7
- package/skills/install-mcp/SKILL.md +135 -46
- package/skills/install-mcp/references/unreal-operations.md +55 -0
- package/skills/ue-actor-component-architecture/SKILL.md +509 -0
- package/skills/ue-actor-component-architecture/references/actor-lifecycle.md +301 -0
- package/skills/ue-actor-component-architecture/references/component-types.md +592 -0
- package/skills/ue-ai-navigation/SKILL.md +526 -0
- package/skills/ue-ai-navigation/references/behavior-tree-patterns.md +392 -0
- package/skills/ue-ai-navigation/references/behavior-tree-workflow.md +107 -0
- package/skills/ue-ai-navigation/references/custom-bttask.md +104 -0
- package/skills/ue-ai-navigation/references/eqs-reference.md +423 -0
- package/skills/ue-animation-system/SKILL.md +521 -0
- package/skills/ue-animation-system/references/anim-notify-reference.md +486 -0
- package/skills/ue-animation-system/references/locomotion-setup.md +550 -0
- package/skills/ue-async-threading/SKILL.md +433 -0
- package/skills/ue-async-threading/references/thread-safety-guide.md +213 -0
- package/skills/ue-async-threading/references/threading-patterns.md +345 -0
- package/skills/ue-audio-system/SKILL.md +527 -0
- package/skills/ue-audio-system/references/audio-setup-patterns.md +700 -0
- package/skills/ue-blueprints/SKILL.md +134 -0
- package/skills/ue-blueprints/references/communication.md +82 -0
- package/skills/ue-character-movement/SKILL.md +475 -0
- package/skills/ue-character-movement/references/cmc-extension-patterns.md +335 -0
- package/skills/ue-character-movement/references/movement-pipeline.md +189 -0
- package/skills/ue-cpp-foundations/SKILL.md +533 -0
- package/skills/ue-cpp-foundations/references/components-and-gc.md +107 -0
- package/skills/ue-cpp-foundations/references/container-patterns.md +544 -0
- package/skills/ue-cpp-foundations/references/delegate-patterns.md +497 -0
- package/skills/ue-cpp-foundations/references/gameplay-classes-cpp.md +136 -0
- package/skills/ue-cpp-foundations/references/property-specifiers.md +306 -0
- package/skills/ue-data-assets-tables/SKILL.md +527 -0
- package/skills/ue-data-assets-tables/references/asset-loading-patterns.md +306 -0
- package/skills/ue-data-assets-tables/references/data-driven-design.md +378 -0
- package/skills/ue-editor-tools/SKILL.md +523 -0
- package/skills/ue-editor-tools/references/detail-customization-patterns.md +395 -0
- package/skills/ue-editor-tools/references/editor-module-setup.md +480 -0
- package/skills/ue-game-features/SKILL.md +477 -0
- package/skills/ue-game-features/references/experience-system.md +222 -0
- package/skills/ue-game-features/references/game-feature-patterns.md +308 -0
- package/skills/ue-gameplay-abilities/SKILL.md +518 -0
- package/skills/ue-gameplay-abilities/references/ability-task-reference.md +391 -0
- package/skills/ue-gameplay-abilities/references/gameplay-effect-reference.md +397 -0
- package/skills/ue-gameplay-abilities/references/gas-setup-patterns.md +369 -0
- package/skills/ue-gameplay-framework/SKILL.md +466 -0
- package/skills/ue-gameplay-framework/references/framework-class-map.md +243 -0
- package/skills/ue-input-system/SKILL.md +394 -0
- package/skills/ue-input-system/references/cpp-setup.md +131 -0
- package/skills/ue-input-system/references/enhanced-input-workflow.md +117 -0
- package/skills/ue-input-system/references/input-action-reference.md +731 -0
- package/skills/ue-mass-entity/SKILL.md +476 -0
- package/skills/ue-mass-entity/references/mass-entity-patterns.md +319 -0
- package/skills/ue-mass-entity/references/mass-fragment-reference.md +119 -0
- package/skills/ue-materials-rendering/SKILL.md +526 -0
- package/skills/ue-materials-rendering/references/material-parameter-reference.md +216 -0
- package/skills/ue-materials-rendering/references/post-process-settings.md +383 -0
- package/skills/ue-module-build-system/SKILL.md +487 -0
- package/skills/ue-module-build-system/references/build-cs-reference.md +418 -0
- package/skills/ue-module-build-system/references/common-build-errors.md +381 -0
- package/skills/ue-naming-conventions/SKILL.md +142 -0
- package/skills/ue-naming-conventions/references/asset-name-modifiers.md +233 -0
- package/skills/ue-naming-conventions/references/content-structure.md +83 -0
- package/skills/ue-networking-replication/SKILL.md +452 -0
- package/skills/ue-networking-replication/references/replication-patterns.md +526 -0
- package/skills/ue-networking-replication/references/rpc-decision-guide.md +393 -0
- package/skills/ue-niagara-effects/SKILL.md +531 -0
- package/skills/ue-niagara-effects/references/niagara-data-interfaces.md +491 -0
- package/skills/ue-niagara-effects/references/niagara-parameter-types.md +153 -0
- package/skills/ue-niagara-effects/references/niagara-workflow.md +115 -0
- package/skills/ue-packaging/SKILL.md +116 -0
- package/skills/ue-physics-collision/SKILL.md +423 -0
- package/skills/ue-physics-collision/references/collision-channel-setup.md +218 -0
- package/skills/ue-physics-collision/references/trace-patterns.md +499 -0
- package/skills/ue-procedural-generation/SKILL.md +505 -0
- package/skills/ue-procedural-generation/references/pcg-node-reference.md +381 -0
- package/skills/ue-procedural-generation/references/procedural-mesh-patterns.md +940 -0
- package/skills/ue-project-context/SKILL.md +305 -0
- package/skills/ue-sequencer-cinematics/SKILL.md +506 -0
- package/skills/ue-sequencer-cinematics/references/sequencer-patterns.md +629 -0
- package/skills/ue-serialization-savegames/SKILL.md +524 -0
- package/skills/ue-serialization-savegames/references/save-system-architecture.md +705 -0
- package/skills/ue-state-trees/SKILL.md +489 -0
- package/skills/ue-state-trees/references/state-tree-mass-integration.md +184 -0
- package/skills/ue-state-trees/references/state-tree-patterns.md +321 -0
- package/skills/ue-testing-debugging/SKILL.md +520 -0
- package/skills/ue-testing-debugging/references/automation-test-patterns.md +387 -0
- package/skills/ue-testing-debugging/references/profiling-commands.md +357 -0
- package/skills/ue-ui-umg-slate/SKILL.md +431 -0
- package/skills/ue-ui-umg-slate/references/common-ui-setup.md +484 -0
- package/skills/ue-ui-umg-slate/references/widget-types.md +487 -0
- package/skills/ue-world-level-streaming/SKILL.md +518 -0
- package/skills/ue-world-level-streaming/references/streaming-patterns.md +414 -0
- package/templates/gamedev/unreal-project-context.md +107 -0
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ue-materials-rendering
|
|
3
|
+
description: "Materials, shaders, dynamic material instances, post-process, render targets, Nanite, Lumen"
|
|
4
|
+
category: "gamedev"
|
|
5
|
+
argument-hint: "[material o effect]"
|
|
6
|
+
user-invocable: true
|
|
7
|
+
allowed-tools: Read, Glob, Grep, Bash, Write, Edit
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# UE Materials and Rendering
|
|
11
|
+
|
|
12
|
+
You are an expert in Unreal Engine's material and rendering systems. You provide accurate C++ patterns for dynamic materials, parameter collections, post-process, render targets, decals, and UE5 rendering features (Nanite, Lumen, Virtual Shadow Maps).
|
|
13
|
+
|
|
14
|
+
Ask before writing: this skill edits material assets, material functions and rendering code. Propose the change and get approval before using Write or Edit.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Step 1: Read Project Context
|
|
19
|
+
|
|
20
|
+
Read `docs/unreal/project-context.md` before giving advice. From it, extract:
|
|
21
|
+
|
|
22
|
+
- **Engine version** — UE5.0–5.4 APIs differ (e.g., `SetNaniteOverride` added in 5.x; `CopyScalarAndVectorParameters` signature changed in 5.7)
|
|
23
|
+
- **Target platforms** — Mobile requires forward rendering; many post-process features are desktop-only
|
|
24
|
+
- **Rendering settings** — Nanite/Lumen enabled status affects which material features are safe
|
|
25
|
+
- **Module names** — needed for correct `#include` paths and `Build.cs` dependencies
|
|
26
|
+
|
|
27
|
+
If the context file is missing, ask for engine version and target platforms before proceeding.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Step 2: Clarify the Rendering Need
|
|
32
|
+
|
|
33
|
+
Ask which area the user needs:
|
|
34
|
+
|
|
35
|
+
1. **Dynamic Material Instances (MID)** — runtime parameter changes on mesh components
|
|
36
|
+
2. **Material Parameter Collections** — global parameters shared across all materials
|
|
37
|
+
3. **Post-Process** — bloom, exposure, color grading, DOF, AO via volumes or components
|
|
38
|
+
4. **Render Targets** — scene capture, minimap, security camera, canvas drawing
|
|
39
|
+
5. **Decals** — deferred decals spawned at runtime, fade, sort order
|
|
40
|
+
6. **Rendering Pipeline / UE5 Features** — Nanite, Lumen, Virtual Shadow Maps, custom depth/stencil
|
|
41
|
+
|
|
42
|
+
Multiple areas can be combined.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Core Patterns
|
|
47
|
+
|
|
48
|
+
### 1. Dynamic Material Instances (MID)
|
|
49
|
+
|
|
50
|
+
#### Creation
|
|
51
|
+
|
|
52
|
+
**Pattern A — from UMaterialInterface (standalone, not tied to a component slot):**
|
|
53
|
+
|
|
54
|
+
```cpp
|
|
55
|
+
// Header
|
|
56
|
+
UPROPERTY()
|
|
57
|
+
TObjectPtr<UMaterialInstanceDynamic> MyMID;
|
|
58
|
+
|
|
59
|
+
// Implementation — call once (BeginPlay or equivalent), cache the result
|
|
60
|
+
UMaterialInterface* BaseMat = LoadObject<UMaterialInterface>(
|
|
61
|
+
nullptr, TEXT("/Game/Materials/M_MyBase.M_MyBase"));
|
|
62
|
+
|
|
63
|
+
MyMID = UMaterialInstanceDynamic::Create(BaseMat, this);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Pattern B — via component slot (preferred for meshes):**
|
|
67
|
+
|
|
68
|
+
```cpp
|
|
69
|
+
// UMeshComponent::CreateDynamicMaterialInstance creates a MID for the given
|
|
70
|
+
// element index and assigns it to the slot automatically.
|
|
71
|
+
// Signature: CreateDynamicMaterialInstance(int32 ElementIndex,
|
|
72
|
+
// UMaterialInterface* SourceMaterial = nullptr,
|
|
73
|
+
// FName OptionalName = NAME_None)
|
|
74
|
+
|
|
75
|
+
UMaterialInstanceDynamic* MID = MeshComponent->CreateDynamicMaterialInstance(
|
|
76
|
+
0, // element index
|
|
77
|
+
nullptr, // nullptr = use the slot's current material as parent
|
|
78
|
+
TEXT("MyMID") // optional debug name
|
|
79
|
+
);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Source: `MaterialInstanceDynamic.h`, `PrimitiveComponent.h`. Build.cs: `"Engine"`.
|
|
83
|
+
|
|
84
|
+
#### Setting Parameters
|
|
85
|
+
|
|
86
|
+
```cpp
|
|
87
|
+
MyMID->SetScalarParameterValue(TEXT("Opacity"), 0.5f);
|
|
88
|
+
MyMID->SetVectorParameterValue(TEXT("BaseColor"), FLinearColor(1.f, 0.2f, 0.1f, 1.f));
|
|
89
|
+
MyMID->SetVectorParameterValue(TEXT("Offset"), FLinearColor(0.f, 0.f, 100.f, 0.f)); // XYZ via FLinearColor
|
|
90
|
+
MyMID->SetTextureParameterValue(TEXT("DamageMask"), MyTexture);
|
|
91
|
+
MyMID->SetTextureParameterValue(TEXT("SecurityFeed"), RenderTargetAsset); // RT as texture
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Full setter signatures from `MaterialInstanceDynamic.h`:
|
|
95
|
+
```cpp
|
|
96
|
+
void SetScalarParameterValue(FName ParameterName, float Value);
|
|
97
|
+
void SetVectorParameterValue(FName ParameterName, FLinearColor Value); // Pass FLinearColor; no implicit conversion from FVector
|
|
98
|
+
void SetTextureParameterValue(FName ParameterName, UTexture* Value);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### High-Frequency Updates — Index-Based API
|
|
102
|
+
|
|
103
|
+
When setting dozens of parameters per frame (rare but valid), use index caching:
|
|
104
|
+
|
|
105
|
+
```cpp
|
|
106
|
+
// In BeginPlay or initialization — call once per parameter name:
|
|
107
|
+
int32 OpacityIndex = -1;
|
|
108
|
+
MyMID->InitializeScalarParameterAndGetIndex(TEXT("Opacity"), 1.0f, OpacityIndex);
|
|
109
|
+
|
|
110
|
+
// In Tick — use index, no name lookup:
|
|
111
|
+
if (OpacityIndex >= 0)
|
|
112
|
+
{
|
|
113
|
+
MyMID->SetScalarParameterByIndex(OpacityIndex, NewOpacity);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Index is invalidated if the parent material changes. Do not share indices across different MID instances.
|
|
118
|
+
|
|
119
|
+
#### MID Lifecycle and GC
|
|
120
|
+
|
|
121
|
+
MIDs are `UObject`s — they are garbage collected when unreferenced. To keep a MID alive:
|
|
122
|
+
|
|
123
|
+
```cpp
|
|
124
|
+
// In your class header — must be UPROPERTY to prevent GC
|
|
125
|
+
UPROPERTY()
|
|
126
|
+
TObjectPtr<UMaterialInstanceDynamic> CachedMID;
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Never store MIDs in raw pointers or local variables across frames.
|
|
130
|
+
|
|
131
|
+
#### Additional MID Operations
|
|
132
|
+
|
|
133
|
+
```cpp
|
|
134
|
+
// Lerp between two instances' scalar/vector params
|
|
135
|
+
MyMID->K2_InterpolateMaterialInstanceParams(InstanceA, InstanceB, Alpha);
|
|
136
|
+
|
|
137
|
+
// Assign Nanite-compatible override material (UE5)
|
|
138
|
+
MyMID->SetNaniteOverride(NaniteCompatibleMaterial);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
### 2. Material Parameter Collections
|
|
144
|
+
|
|
145
|
+
`UMaterialParameterCollection` is an asset holding scalar and vector parameters accessible from any material via `CollectionParameter` expression. One GPU buffer update propagates to all referencing materials. Source: `MaterialParameterCollection.h`, `MaterialParameterCollectionInstance.h`.
|
|
146
|
+
|
|
147
|
+
#### Setting Parameters at Runtime
|
|
148
|
+
|
|
149
|
+
```cpp
|
|
150
|
+
// MyCollection is a UPROPERTY(EditAnywhere) pointing to the MPC asset.
|
|
151
|
+
UPROPERTY(EditAnywhere, Category="Rendering")
|
|
152
|
+
TObjectPtr<UMaterialParameterCollection> GlobalRenderingCollection;
|
|
153
|
+
|
|
154
|
+
// At runtime — get the per-world instance and set values:
|
|
155
|
+
void AMyActor::UpdateGlobalWeather(float RainIntensity, FLinearColor FogColor)
|
|
156
|
+
{
|
|
157
|
+
UMaterialParameterCollectionInstance* Instance =
|
|
158
|
+
GetWorld()->GetParameterCollectionInstance(GlobalRenderingCollection);
|
|
159
|
+
|
|
160
|
+
if (Instance)
|
|
161
|
+
{
|
|
162
|
+
Instance->SetScalarParameterValue(TEXT("RainIntensity"), RainIntensity);
|
|
163
|
+
Instance->SetVectorParameterValue(TEXT("FogColor"), FogColor);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Both setters return `false` if the parameter name is not found. Names are case-sensitive. Limits: max 1024 scalars + 1024 vectors per collection; no texture parameters; global to the world instance.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### 3. Post-Process Volumes
|
|
173
|
+
|
|
174
|
+
`APostProcessVolume` wraps `FPostProcessSettings` and controls how the camera is rendered when inside (or globally when `bUnbound = true`).
|
|
175
|
+
|
|
176
|
+
From `PostProcessVolume.h`:
|
|
177
|
+
```cpp
|
|
178
|
+
struct FPostProcessSettings Settings; // The settings payload
|
|
179
|
+
float Priority; // Higher priority wins on overlap (undefined order when equal)
|
|
180
|
+
float BlendRadius; // World-space blend distance in cm (only when bUnbound = false)
|
|
181
|
+
float BlendWeight; // 0 = no effect, 1 = full effect
|
|
182
|
+
uint32 bEnabled:1;
|
|
183
|
+
uint32 bUnbound:1; // true = applies globally regardless of camera position
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### Modifying a Post-Process Volume from C++
|
|
187
|
+
|
|
188
|
+
```cpp
|
|
189
|
+
// Assume PostProcessVolume is assigned or found:
|
|
190
|
+
APostProcessVolume* PPV = /* find or spawn */;
|
|
191
|
+
|
|
192
|
+
// Enable and configure
|
|
193
|
+
PPV->bEnabled = true;
|
|
194
|
+
PPV->bUnbound = true; // global effect
|
|
195
|
+
PPV->BlendWeight = 1.0f;
|
|
196
|
+
|
|
197
|
+
// Bloom
|
|
198
|
+
PPV->Settings.bOverride_BloomIntensity = true;
|
|
199
|
+
PPV->Settings.BloomIntensity = 0.5f;
|
|
200
|
+
|
|
201
|
+
// Auto Exposure
|
|
202
|
+
PPV->Settings.bOverride_AutoExposureMinBrightness = true;
|
|
203
|
+
PPV->Settings.AutoExposureMinBrightness = 0.1f;
|
|
204
|
+
PPV->Settings.bOverride_AutoExposureMaxBrightness = true;
|
|
205
|
+
PPV->Settings.AutoExposureMaxBrightness = 2.0f;
|
|
206
|
+
|
|
207
|
+
// Depth of Field (Cinematic DOF)
|
|
208
|
+
PPV->Settings.bOverride_DepthOfFieldFstop = true;
|
|
209
|
+
PPV->Settings.DepthOfFieldFstop = 2.8f;
|
|
210
|
+
PPV->Settings.bOverride_DepthOfFieldFocalDistance = true;
|
|
211
|
+
PPV->Settings.DepthOfFieldFocalDistance = 300.0f; // cm
|
|
212
|
+
|
|
213
|
+
// Ambient Occlusion
|
|
214
|
+
PPV->Settings.bOverride_AmbientOcclusionIntensity = true;
|
|
215
|
+
PPV->Settings.AmbientOcclusionIntensity = 0.5f;
|
|
216
|
+
|
|
217
|
+
// Vignette
|
|
218
|
+
PPV->Settings.bOverride_VignetteIntensity = true;
|
|
219
|
+
PPV->Settings.VignetteIntensity = 0.4f;
|
|
220
|
+
|
|
221
|
+
// Color Grading
|
|
222
|
+
PPV->Settings.bOverride_ColorSaturation = true;
|
|
223
|
+
PPV->Settings.ColorSaturation = FVector4(1.2f, 1.0f, 0.8f, 1.0f); // per-channel RGBA
|
|
224
|
+
PPV->Settings.bOverride_FilmSlope = true;
|
|
225
|
+
PPV->Settings.FilmSlope = 0.88f; // 0–1 (default 0.88)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Every field in `FPostProcessSettings` has a corresponding `bOverride_*` bool that must be set to `true` for the value to take effect. See `references/post-process-settings.md` for a full field reference.
|
|
229
|
+
|
|
230
|
+
#### Post-Process Materials (Blendables)
|
|
231
|
+
|
|
232
|
+
Material Domain must be "Post Process". Add via:
|
|
233
|
+
```cpp
|
|
234
|
+
PPV->AddOrUpdateBlendable(PostProcessMaterial, 1.0f); // weight 0.0–1.0
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### UPostProcessComponent (Actor-Owned)
|
|
238
|
+
|
|
239
|
+
```cpp
|
|
240
|
+
// Constructor
|
|
241
|
+
PostProcessComp = CreateDefaultSubobject<UPostProcessComponent>(TEXT("PostProcess"));
|
|
242
|
+
PostProcessComp->bUnbound = true;
|
|
243
|
+
PostProcessComp->Priority = 5.0f;
|
|
244
|
+
|
|
245
|
+
// Runtime
|
|
246
|
+
PostProcessComp->Settings.bOverride_BloomIntensity = true;
|
|
247
|
+
PostProcessComp->Settings.BloomIntensity = 1.5f;
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Includes: `"Components/PostProcessComponent.h"`, `"Engine/PostProcessVolume.h"`, `"Engine/Scene.h"`.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
### 4. Render Targets
|
|
255
|
+
|
|
256
|
+
#### Creating a Render Target in C++
|
|
257
|
+
|
|
258
|
+
```cpp
|
|
259
|
+
#include "Engine/TextureRenderTarget2D.h"
|
|
260
|
+
#include "Kismet/KismetRenderingLibrary.h"
|
|
261
|
+
|
|
262
|
+
// Option A — via UKismetRenderingLibrary (handles resource init automatically)
|
|
263
|
+
UTextureRenderTarget2D* RT = UKismetRenderingLibrary::CreateRenderTarget2D(
|
|
264
|
+
this, // WorldContextObject
|
|
265
|
+
512, // Width
|
|
266
|
+
512, // Height
|
|
267
|
+
RTF_RGBA16f, // Format (see ETextureRenderTargetFormat)
|
|
268
|
+
FLinearColor::Black,
|
|
269
|
+
false // bAutoGenerateMipMaps
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
// Option B — manual creation
|
|
273
|
+
UTextureRenderTarget2D* RT = NewObject<UTextureRenderTarget2D>(this);
|
|
274
|
+
RT->InitCustomFormat(512, 512, PF_FloatRGBA, /*bInForceLinearGamma=*/true);
|
|
275
|
+
RT->UpdateResourceImmediate(/*bClearRenderTarget=*/true);
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
`ETextureRenderTargetFormat` values from `TextureRenderTarget2D.h`:
|
|
279
|
+
| Format | Channels | Bits/Channel | Use Case |
|
|
280
|
+
|--------|----------|-------------|----------|
|
|
281
|
+
| `RTF_RGBA8` | RGBA | 8 fixed | LDR color, UI |
|
|
282
|
+
| `RTF_RGBA8_SRGB` | RGBA | 8 fixed | sRGB color |
|
|
283
|
+
| `RTF_RGBA16f` | RGBA | 16 float | HDR color (default) |
|
|
284
|
+
| `RTF_RGBA32f` | RGBA | 32 float | High precision data |
|
|
285
|
+
| `RTF_R16f` | R | 16 float | Single channel data |
|
|
286
|
+
| `RTF_RGB10A2` | RGB+A | 10+2 bit | Display output |
|
|
287
|
+
|
|
288
|
+
#### Scene Capture (Security Camera / Minimap)
|
|
289
|
+
|
|
290
|
+
```cpp
|
|
291
|
+
#include "Components/SceneCaptureComponent2D.h"
|
|
292
|
+
|
|
293
|
+
// In actor constructor
|
|
294
|
+
SceneCapture = CreateDefaultSubobject<USceneCaptureComponent2D>(TEXT("SceneCapture"));
|
|
295
|
+
SceneCapture->SetupAttachment(RootComponent);
|
|
296
|
+
SceneCapture->FOVAngle = 90.f;
|
|
297
|
+
SceneCapture->CaptureSource = ESceneCaptureSource::SCS_FinalColorLDR; // or SCS_SceneColorHDR
|
|
298
|
+
SceneCapture->bCaptureEveryFrame = true; // continuous update
|
|
299
|
+
|
|
300
|
+
// Assign a render target asset or a runtime-created one
|
|
301
|
+
SceneCapture->TextureTarget = MyRenderTargetAsset;
|
|
302
|
+
|
|
303
|
+
// Limit what's captured for performance
|
|
304
|
+
SceneCapture->ShowFlags.SetAtmosphere(false);
|
|
305
|
+
SceneCapture->ShowFlags.SetFog(false);
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
#### Drawing a Material to a Render Target
|
|
309
|
+
|
|
310
|
+
```cpp
|
|
311
|
+
// Renders a full-screen quad with Material applied to TextureTarget.
|
|
312
|
+
// This is expensive (sets render target each call); use canvas API for batching.
|
|
313
|
+
UKismetRenderingLibrary::DrawMaterialToRenderTarget(
|
|
314
|
+
this, // WorldContextObject
|
|
315
|
+
RT, // UTextureRenderTarget2D*
|
|
316
|
+
MyMaterial // UMaterialInterface*
|
|
317
|
+
);
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Canvas Drawing (Batched)
|
|
321
|
+
|
|
322
|
+
```cpp
|
|
323
|
+
UCanvas* Canvas;
|
|
324
|
+
FVector2D CanvasSize;
|
|
325
|
+
FDrawToRenderTargetContext Context;
|
|
326
|
+
|
|
327
|
+
UKismetRenderingLibrary::BeginDrawCanvasToRenderTarget(this, RT, Canvas, CanvasSize, Context);
|
|
328
|
+
|
|
329
|
+
// Draw primitives to Canvas here...
|
|
330
|
+
Canvas->K2_DrawMaterial(MyMaterial, FVector2D(0, 0), CanvasSize, FVector2D(0, 0), FVector2D(1, 1));
|
|
331
|
+
|
|
332
|
+
UKismetRenderingLibrary::EndDrawCanvasToRenderTarget(this, Context);
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
**`UCanvasRenderTarget2D`** — subclass of `UTextureRenderTarget2D` with a built-in `OnCanvasRenderTargetUpdate` delegate. Use for automatic 2D canvas redraw (minimaps, runtime texture painting) instead of manual `BeginDrawCanvasToRenderTarget` calls.
|
|
336
|
+
|
|
337
|
+
#### Reading Pixels (GPU Stall — Offline Only)
|
|
338
|
+
|
|
339
|
+
```cpp
|
|
340
|
+
// WARNING: stalls GPU pipeline. Editor tools / screenshot only, never per-frame.
|
|
341
|
+
FColor Pixel = UKismetRenderingLibrary::ReadRenderTargetPixel(this, RT, X, Y);
|
|
342
|
+
TArray<FColor> Pixels;
|
|
343
|
+
UKismetRenderingLibrary::ReadRenderTarget(this, RT, Pixels); // whole RT, 8-bit sRGB
|
|
344
|
+
FLinearColor Raw = UKismetRenderingLibrary::ReadRenderTargetRawPixel(this, RT, X, Y);
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
### 5. Decals
|
|
350
|
+
|
|
351
|
+
`UDecalComponent` projects a material onto surfaces. Key API from `DecalComponent.h`:
|
|
352
|
+
|
|
353
|
+
```cpp
|
|
354
|
+
void SetDecalMaterial(UMaterialInterface* NewDecalMaterial);
|
|
355
|
+
UMaterialInstanceDynamic* CreateDynamicMaterialInstance(); // MID on the decal
|
|
356
|
+
void SetFadeOut(float StartDelay, float Duration, bool DestroyOwnerAfterFade = true);
|
|
357
|
+
void SetFadeIn(float StartDelay, float Duration);
|
|
358
|
+
void SetSortOrder(int32 Value); // higher = draws on top
|
|
359
|
+
void SetLifeSpan(float LifeSpan);
|
|
360
|
+
FVector DecalSize; // local-space extent (not component scale)
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
#### Spawning Decals at Runtime
|
|
364
|
+
|
|
365
|
+
```cpp
|
|
366
|
+
// 0.0f lifespan = persistent; >0.0f = auto-destroy after N seconds
|
|
367
|
+
UDecalComponent* Decal = UGameplayStatics::SpawnDecalAtLocation(
|
|
368
|
+
this, DecalMaterial, FVector(200.f), HitLocation, HitNormal.Rotation(), 0.0f);
|
|
369
|
+
|
|
370
|
+
// Dynamic parameters on the decal
|
|
371
|
+
UMaterialInstanceDynamic* DecalMID = Decal->CreateDynamicMaterialInstance();
|
|
372
|
+
DecalMID->SetScalarParameterValue(TEXT("Opacity"), 0.8f);
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
#### DBuffer vs Non-DBuffer Decals
|
|
376
|
+
|
|
377
|
+
- **DBuffer** (Translucent + DBuffer enabled): writes before lighting, affects diffuse/normals/roughness. Enable via `Project Settings > Rendering > DBuffer Decals`.
|
|
378
|
+
- **Non-DBuffer**: rendered after lighting, emissive/opacity only; cheaper but limited.
|
|
379
|
+
|
|
380
|
+
For level-placed decals, use `ADecalActor` (a wrapper around `UDecalComponent`). For runtime-spawned decals, prefer `UGameplayStatics::SpawnDecalAtLocation` or `SpawnDecalAttached`.
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
### 6. Nanite and Lumen (UE5)
|
|
385
|
+
|
|
386
|
+
#### Nanite
|
|
387
|
+
|
|
388
|
+
Nanite is UE5's virtualized geometry system. Material compatibility rules:
|
|
389
|
+
|
|
390
|
+
| Feature | Nanite Compatible |
|
|
391
|
+
|---------|------------------|
|
|
392
|
+
| Opaque materials | Yes |
|
|
393
|
+
| Two-sided materials | Yes |
|
|
394
|
+
| Masked materials | Yes (with `r.Nanite.AllowMaskedMaterials=1`) |
|
|
395
|
+
| Translucent materials | No — falls back to non-Nanite path |
|
|
396
|
+
| World Position Offset (WPO) | Supported in UE 5.1+ (`bEvaluateWorldPositionOffset` on mesh) |
|
|
397
|
+
| Pixel Depth Offset | No |
|
|
398
|
+
| Custom vertex normals via shader | Limited |
|
|
399
|
+
|
|
400
|
+
Check at runtime:
|
|
401
|
+
```cpp
|
|
402
|
+
// Check if a static mesh component is using Nanite (IsNaniteEnabled is on UStaticMesh, not on the component)
|
|
403
|
+
bool bIsNanite = StaticMeshComponent->GetStaticMesh() && StaticMeshComponent->GetStaticMesh()->IsNaniteEnabled();
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Override material for Nanite path:
|
|
407
|
+
```cpp
|
|
408
|
+
MyMID->SetNaniteOverride(NaniteCompatibleMaterial);
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
#### Lumen
|
|
412
|
+
|
|
413
|
+
Lumen is UE5's dynamic GI and reflections system. Emissive surfaces can act as lights. Translucent surfaces are not traced by default. Control quality via post-process settings:
|
|
414
|
+
|
|
415
|
+
```cpp
|
|
416
|
+
PPV->Settings.bOverride_LumenReflectionQuality = true;
|
|
417
|
+
PPV->Settings.LumenReflectionQuality = 1.0f; // 0–4
|
|
418
|
+
|
|
419
|
+
PPV->Settings.bOverride_LumenSceneDetail = true;
|
|
420
|
+
PPV->Settings.LumenSceneDetail = 1.0f; // surface cache resolution multiplier
|
|
421
|
+
|
|
422
|
+
PPV->Settings.bOverride_LumenSceneLightingQuality = true;
|
|
423
|
+
PPV->Settings.LumenSceneLightingQuality = 1.0f;
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
Performance: `r.Lumen.SurfaceCache.UpdateDownsampleFactor` controls cache update rate.
|
|
427
|
+
|
|
428
|
+
#### Deferred vs Forward Rendering
|
|
429
|
+
|
|
430
|
+
**Deferred vs Forward**: UE5 desktop uses deferred rendering by default — geometry writes to GBuffer, then lighting is computed per-pixel. Forward rendering (mobile, VR) processes lighting per-object, supports MSAA, but limits dynamic light count. Set via `Project Settings > Rendering > Forward Shading`.
|
|
431
|
+
|
|
432
|
+
**Scalability**: Use `Scalability::SetQualityLevels()` (in `Scalability.h`) or console commands such as `sg.PostProcessQuality 0-3` to adjust rendering quality at runtime. Configure presets in `BaseScalability.ini`.
|
|
433
|
+
|
|
434
|
+
#### Virtual Shadow Maps (VSM)
|
|
435
|
+
|
|
436
|
+
- WPO materials: enable "Evaluate World Position Offset" in the material's Details panel (material editor setting, not a C++ property) for correct VSM shadows.
|
|
437
|
+
- Masked materials: opacity masks respected correctly.
|
|
438
|
+
- Decals do not cast VSM shadows.
|
|
439
|
+
|
|
440
|
+
#### Custom Depth / Stencil (Outlines and Effects)
|
|
441
|
+
|
|
442
|
+
```cpp
|
|
443
|
+
MeshComponent->SetRenderCustomDepth(true);
|
|
444
|
+
MeshComponent->SetCustomDepthStencilValue(1); // 0–255
|
|
445
|
+
// Sample CustomDepth / CustomStencil nodes in a post-process material for outlines, X-ray, highlight effects.
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Enable: `Project Settings > Rendering > Custom Depth-Stencil Pass > Enabled with Stencil`.
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
## Common Mistakes and Anti-Patterns
|
|
453
|
+
|
|
454
|
+
**Creating MIDs every frame** — Each `CreateDynamicMaterialInstance` call allocates a new GPU resource. Create once in `BeginPlay`, cache, update in `Tick`:
|
|
455
|
+
|
|
456
|
+
```cpp
|
|
457
|
+
// BeginPlay
|
|
458
|
+
CachedMID = MeshComponent->CreateDynamicMaterialInstance(0);
|
|
459
|
+
|
|
460
|
+
// Tick
|
|
461
|
+
if (CachedMID) { CachedMID->SetScalarParameterValue(TEXT("Time"), GetWorld()->TimeSeconds); }
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**Not caching MID as UPROPERTY** — Raw `UMaterialInstanceDynamic*` is invisible to GC and collected on the next GC pass. Use `UPROPERTY() TObjectPtr<UMaterialInstanceDynamic> CachedMID;`.
|
|
465
|
+
|
|
466
|
+
**Wrong parameter names** — Names are case-sensitive exact matches. `"basecolor"`, `"Base Color"`, and `"Base_Color"` all silently fail if the material uses `"BaseColor"`.
|
|
467
|
+
|
|
468
|
+
**Render target resolution** — Match resolution to use: 256–512 for minimap/security camera, 512 max for mirrors; use planar reflections for large mirrors. Full-screen: use `bMainViewResolution` on `USceneCaptureComponent2D`.
|
|
469
|
+
|
|
470
|
+
**Reading render target pixels per frame** — `ReadRenderTargetPixel` stalls the GPU pipeline. Never call per frame. Use `FRHIGPUTextureReadback` for async non-stalling reads.
|
|
471
|
+
|
|
472
|
+
**MIDs on replicated actors** — MIDs are client-local. Do not replicate the MID pointer. Replicate the scalar/vector values and re-apply via `OnRep` functions on each client.
|
|
473
|
+
|
|
474
|
+
**Post-process bOverride not set** — Every `FPostProcessSettings` field requires its paired `bOverride_*` bool set to `true`. Setting a value without the override is a silent no-op.
|
|
475
|
+
|
|
476
|
+
**Nanite translucency fallback** — Translucent materials on Nanite meshes revert the full mesh to non-Nanite rendering. Split into separate opaque and translucent components.
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
## Required Build.cs Dependencies
|
|
481
|
+
|
|
482
|
+
```csharp
|
|
483
|
+
PublicDependencyModuleNames.AddRange(new string[]
|
|
484
|
+
{
|
|
485
|
+
"Engine", // Materials, render targets, UTextureRenderTarget2D
|
|
486
|
+
"RenderCore", // Low-level render utilities
|
|
487
|
+
"RHI", // RHI types (EPixelFormat, etc.)
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
// For UKismetRenderingLibrary:
|
|
491
|
+
// Already available via "Engine" — no separate module needed.
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
## Related Skills
|
|
497
|
+
|
|
498
|
+
- `/ue-cpp-foundations` — UObject management, UPROPERTY, TObjectPtr, garbage collection
|
|
499
|
+
- `/ue-actor-component-architecture` — setting up components (UDecalComponent, USceneCaptureComponent2D, UPostProcessComponent)
|
|
500
|
+
- `/ue-niagara-effects` — particle materials use MIDs; parameter passing into Niagara from C++
|
|
501
|
+
- `/ue-project-context` — engine version, target platforms, rendering feature flags
|
|
502
|
+
- `/ue-naming-conventions` — asset prefixes and Content folder layout for these assets
|
|
503
|
+
|
|
504
|
+
## Reference Files
|
|
505
|
+
|
|
506
|
+
- `references/material-parameter-reference.md` — material parameter types and their C++/Blueprint setters
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## Checklist
|
|
511
|
+
|
|
512
|
+
Validate before considering the work done:
|
|
513
|
+
|
|
514
|
+
- [ ] Material instances are used for variation instead of duplicated materials
|
|
515
|
+
- [ ] Instruction count and texture samplers stay within the platform budget
|
|
516
|
+
- [ ] Dynamic material instances are created once and cached, not per frame
|
|
517
|
+
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
518
|
+
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
519
|
+
|
|
520
|
+
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
521
|
+
|
|
522
|
+
## Next Steps
|
|
523
|
+
|
|
524
|
+
- `/perf-profile` — measure the GPU cost of the change
|
|
525
|
+
- `/code-review` — architectural and quality review of the change
|
|
526
|
+
- `/commit` — conventional commit once the change is verified
|