ue-materials-rendering

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

UE Materials and Rendering

UE材质与渲染

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).

您是Unreal Engine材质与渲染系统的专家。您提供动态材质、参数集合、后期处理、渲染目标、贴花以及UE5渲染特性(Nanite、Lumen、虚拟阴影贴图)的准确C++实现模式。

Step 1: Read Project Context

步骤1:读取项目上下文

Read
.agents/ue-project-context.md
before giving advice. From it, extract:
  • Engine version — UE5.0–5.4 APIs differ (e.g.,
    SetNaniteOverride
    added in 5.x;
    CopyScalarAndVectorParameters
    signature changed in 5.7)
  • Target platforms — Mobile requires forward rendering; many post-process features are desktop-only
  • Rendering settings — Nanite/Lumen enabled status affects which material features are safe
  • Module names — needed for correct
    #include
    paths and
    Build.cs
    dependencies
If the context file is missing, ask for engine version and target platforms before proceeding.

在提供建议前,请先阅读
.agents/ue-project-context.md
。从中提取以下信息:
  • 引擎版本 — UE5.0–5.4的API存在差异(例如
    SetNaniteOverride
    在5.x版本中新增;
    CopyScalarAndVectorParameters
    的签名在5.7版本中变更)
  • 目标平台 — 移动端需要前向渲染;许多后期处理特性仅支持桌面端
  • 渲染设置 — Nanite/Lumen的启用状态会影响哪些材质特性是安全可用的
  • 模块名称 — 正确的
    #include
    路径和
    Build.cs
    依赖项需要用到这些信息
如果上下文文件缺失,请先询问引擎版本和目标平台再继续。

Step 2: Clarify the Rendering Need

步骤2:明确渲染需求

Ask which area the user needs:
  1. Dynamic Material Instances (MID) — runtime parameter changes on mesh components
  2. Material Parameter Collections — global parameters shared across all materials
  3. Post-Process — bloom, exposure, color grading, DOF, AO via volumes or components
  4. Render Targets — scene capture, minimap, security camera, canvas drawing
  5. Decals — deferred decals spawned at runtime, fade, sort order
  6. Rendering Pipeline / UE5 Features — Nanite, Lumen, Virtual Shadow Maps, custom depth/stencil
Multiple areas can be combined.

询问用户需要以下哪个领域的帮助:
  1. 动态材质实例(MID) — 网格组件上的运行时参数修改
  2. 材质参数集合 — 所有材质共享的全局参数
  3. 后期处理 — 通过体积或组件实现 bloom、曝光、颜色分级、景深(DOF)、环境光遮蔽(AO)
  4. 渲染目标 — 场景捕捉、小地图、监控摄像头、画布绘制
  5. 贴花 — 运行时生成的延迟贴花、淡入淡出、排序顺序
  6. 渲染管线/UE5特性 — Nanite、Lumen、虚拟阴影贴图、自定义深度/模板
可以同时选择多个领域。

Core Patterns

核心实现模式

1. Dynamic Material Instances (MID)

1. 动态材质实例(MID)

Creation

创建

Pattern A — from UMaterialInterface (standalone, not tied to a component slot):
cpp
// Header
UPROPERTY()
TObjectPtr<UMaterialInstanceDynamic> MyMID;

// Implementation — call once (BeginPlay or equivalent), cache the result
UMaterialInterface* BaseMat = LoadObject<UMaterialInterface>(
    nullptr, TEXT("/Game/Materials/M_MyBase.M_MyBase"));

MyMID = UMaterialInstanceDynamic::Create(BaseMat, this);
Pattern B — via component slot (preferred for meshes):
cpp
// UMeshComponent::CreateDynamicMaterialInstance creates a MID for the given
// element index and assigns it to the slot automatically.
// Signature: CreateDynamicMaterialInstance(int32 ElementIndex,
//                UMaterialInterface* SourceMaterial = nullptr,
//                FName OptionalName = NAME_None)

UMaterialInstanceDynamic* MID = MeshComponent->CreateDynamicMaterialInstance(
    0,            // element index
    nullptr,      // nullptr = use the slot's current material as parent
    TEXT("MyMID") // optional debug name
);
Source:
MaterialInstanceDynamic.h
,
PrimitiveComponent.h
. Build.cs:
"Engine"
.
模式A — 基于UMaterialInterface(独立存在,不绑定到组件插槽):
cpp
// 头文件
UPROPERTY()
TObjectPtr<UMaterialInstanceDynamic> MyMID;

// 实现部分——调用一次(如BeginPlay或等效函数),缓存结果
UMaterialInterface* BaseMat = LoadObject<UMaterialInterface>(
    nullptr, TEXT("/Game/Materials/M_MyBase.M_MyBase"));

MyMID = UMaterialInstanceDynamic::Create(BaseMat, this);
模式B — 通过组件插槽(推荐用于网格):
cpp
// UMeshComponent::CreateDynamicMaterialInstance会为指定元素索引创建一个MID,并自动将其分配到插槽中。
// 签名:CreateDynamicMaterialInstance(int32 ElementIndex,
//                UMaterialInterface* SourceMaterial = nullptr,
//                FName OptionalName = NAME_None)

UMaterialInstanceDynamic* MID = MeshComponent->CreateDynamicMaterialInstance(
    0,            // 元素索引
    nullptr,      // nullptr = 使用插槽当前的材质作为父材质
    TEXT("MyMID") // 可选调试名称
);
来源:
MaterialInstanceDynamic.h
PrimitiveComponent.h
。Build.cs依赖:
"Engine"

Setting Parameters

设置参数

cpp
MyMID->SetScalarParameterValue(TEXT("Opacity"), 0.5f);
MyMID->SetVectorParameterValue(TEXT("BaseColor"), FLinearColor(1.f, 0.2f, 0.1f, 1.f));
MyMID->SetVectorParameterValue(TEXT("Offset"), FLinearColor(0.f, 0.f, 100.f, 0.f)); // XYZ via FLinearColor
MyMID->SetTextureParameterValue(TEXT("DamageMask"), MyTexture);
MyMID->SetTextureParameterValue(TEXT("SecurityFeed"), RenderTargetAsset); // RT as texture
Full setter signatures from
MaterialInstanceDynamic.h
:
cpp
void SetScalarParameterValue(FName ParameterName, float Value);
void SetVectorParameterValue(FName ParameterName, FLinearColor Value);  // Pass FLinearColor; no implicit conversion from FVector
void SetTextureParameterValue(FName ParameterName, UTexture* Value);
cpp
MyMID->SetScalarParameterValue(TEXT("Opacity"), 0.5f);
MyMID->SetVectorParameterValue(TEXT("BaseColor"), FLinearColor(1.f, 0.2f, 0.1f, 1.f));
MyMID->SetVectorParameterValue(TEXT("Offset"), FLinearColor(0.f, 0.f, 100.f, 0.f)); // 通过FLinearColor传递XYZ值
MyMID->SetTextureParameterValue(TEXT("DamageMask"), MyTexture);
MyMID->SetTextureParameterValue(TEXT("SecurityFeed"), RenderTargetAsset); // 将渲染目标作为纹理
MaterialInstanceDynamic.h
中的完整 setter 签名:
cpp
void SetScalarParameterValue(FName ParameterName, float Value);
void SetVectorParameterValue(FName ParameterName, FLinearColor Value);  // 传递FLinearColor;不支持从FVector隐式转换
void SetTextureParameterValue(FName ParameterName, UTexture* Value);

High-Frequency Updates — Index-Based API

高频更新——基于索引的API

When setting dozens of parameters per frame (rare but valid), use index caching:
cpp
// In BeginPlay or initialization — call once per parameter name:
int32 OpacityIndex = -1;
MyMID->InitializeScalarParameterAndGetIndex(TEXT("Opacity"), 1.0f, OpacityIndex);

// In Tick — use index, no name lookup:
if (OpacityIndex >= 0)
{
    MyMID->SetScalarParameterByIndex(OpacityIndex, NewOpacity);
}
Index is invalidated if the parent material changes. Do not share indices across different MID instances.
当每帧需要设置数十个参数时(少见但合法),使用索引缓存:
cpp
// 在BeginPlay或初始化阶段——每个参数名称仅调用一次:
int32 OpacityIndex = -1;
MyMID->InitializeScalarParameterAndGetIndex(TEXT("Opacity"), 1.0f, OpacityIndex);

// 在Tick函数中——使用索引,无需查找名称:
if (OpacityIndex >= 0)
{
    MyMID->SetScalarParameterByIndex(OpacityIndex, NewOpacity);
}
如果父材质发生变化,索引会失效。不要在不同的MID实例之间共享索引。

MID Lifecycle and GC

MID生命周期与垃圾回收

MIDs are
UObject
s — they are garbage collected when unreferenced. To keep a MID alive:
cpp
// In your class header — must be UPROPERTY to prevent GC
UPROPERTY()
TObjectPtr<UMaterialInstanceDynamic> CachedMID;
Never store MIDs in raw pointers or local variables across frames.
MID是
UObject
——当没有引用时会被垃圾回收。要保持MID存活:
cpp
// 在类的头文件中——必须使用UPROPERTY以防止被垃圾回收
UPROPERTY()
TObjectPtr<UMaterialInstanceDynamic> CachedMID;
永远不要在跨帧的原始指针或局部变量中存储MID。

Additional MID Operations

其他MID操作

cpp
// Lerp between two instances' scalar/vector params
MyMID->K2_InterpolateMaterialInstanceParams(InstanceA, InstanceB, Alpha);

// Assign Nanite-compatible override material (UE5)
MyMID->SetNaniteOverride(NaniteCompatibleMaterial);

cpp
// 在两个实例的标量/向量参数之间进行插值
MyMID->K2_InterpolateMaterialInstanceParams(InstanceA, InstanceB, Alpha);

// 为Nanite路径分配兼容的覆盖材质(UE5)
MyMID->SetNaniteOverride(NaniteCompatibleMaterial);

2. Material Parameter Collections

2. 材质参数集合

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
.
UMaterialParameterCollection
是一种资源,用于存储标量和向量参数,所有材质都可以通过
CollectionParameter
表达式访问这些参数。一次GPU缓冲区更新即可将参数传播到所有引用该集合的材质。来源:
MaterialParameterCollection.h
MaterialParameterCollectionInstance.h

Setting Parameters at Runtime

运行时设置参数

cpp
// MyCollection is a UPROPERTY(EditAnywhere) pointing to the MPC asset.
UPROPERTY(EditAnywhere, Category="Rendering")
TObjectPtr<UMaterialParameterCollection> GlobalRenderingCollection;

// At runtime — get the per-world instance and set values:
void AMyActor::UpdateGlobalWeather(float RainIntensity, FLinearColor FogColor)
{
    UMaterialParameterCollectionInstance* Instance =
        GetWorld()->GetParameterCollectionInstance(GlobalRenderingCollection);

    if (Instance)
    {
        Instance->SetScalarParameterValue(TEXT("RainIntensity"), RainIntensity);
        Instance->SetVectorParameterValue(TEXT("FogColor"), FogColor);
    }
}
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.

cpp
// MyCollection是一个UPROPERTY(EditAnywhere),指向MPC资源。
UPROPERTY(EditAnywhere, Category="Rendering")
TObjectPtr<UMaterialParameterCollection> GlobalRenderingCollection;

// 运行时——获取每个世界的实例并设置值:
void AMyActor::UpdateGlobalWeather(float RainIntensity, FLinearColor FogColor)
{
    UMaterialParameterCollectionInstance* Instance =
        GetWorld()->GetParameterCollectionInstance(GlobalRenderingCollection);

    if (Instance)
    {
        Instance->SetScalarParameterValue(TEXT("RainIntensity"), RainIntensity);
        Instance->SetVectorParameterValue(TEXT("FogColor"), FogColor);
    }
}
如果参数名称不存在,两个setter函数都会返回
false
。名称区分大小写。限制:每个集合最多支持1024个标量+1024个向量参数;不支持纹理参数;参数在世界实例范围内全局生效。

3. Post-Process Volumes

3. 后期处理体积

APostProcessVolume
wraps
FPostProcessSettings
and controls how the camera is rendered when inside (or globally when
bUnbound = true
).
From
PostProcessVolume.h
:
cpp
struct FPostProcessSettings Settings; // The settings payload
float Priority;      // Higher priority wins on overlap (undefined order when equal)
float BlendRadius;   // World-space blend distance in cm (only when bUnbound = false)
float BlendWeight;   // 0 = no effect, 1 = full effect
uint32 bEnabled:1;
uint32 bUnbound:1;   // true = applies globally regardless of camera position
APostProcessVolume
封装了
FPostProcessSettings
,控制相机在体积内部(或当
bUnbound = true
时全局)的渲染方式。
来自
PostProcessVolume.h
cpp
struct FPostProcessSettings Settings; // 设置负载
float Priority;      // 重叠时优先级更高的体积生效(优先级相同时顺序未定义)
float BlendRadius;   // 世界空间混合距离(单位:厘米,仅当bUnbound = false时生效)
float BlendWeight;   // 0 = 无效果,1 = 完全生效
uint32 bEnabled:1;
uint32 bUnbound:1;   // true = 无论相机位置如何,全局生效

Modifying a Post-Process Volume from C++

通过C++修改后期处理体积

cpp
// Assume PostProcessVolume is assigned or found:
APostProcessVolume* PPV = /* find or spawn */;

// Enable and configure
PPV->bEnabled = true;
PPV->bUnbound = true; // global effect
PPV->BlendWeight = 1.0f;

// Bloom
PPV->Settings.bOverride_BloomIntensity = true;
PPV->Settings.BloomIntensity = 0.5f;

// Auto Exposure
PPV->Settings.bOverride_AutoExposureMinBrightness = true;
PPV->Settings.AutoExposureMinBrightness = 0.1f;
PPV->Settings.bOverride_AutoExposureMaxBrightness = true;
PPV->Settings.AutoExposureMaxBrightness = 2.0f;

// Depth of Field (Cinematic DOF)
PPV->Settings.bOverride_DepthOfFieldFstop = true;
PPV->Settings.DepthOfFieldFstop = 2.8f;
PPV->Settings.bOverride_DepthOfFieldFocalDistance = true;
PPV->Settings.DepthOfFieldFocalDistance = 300.0f; // cm

// Ambient Occlusion
PPV->Settings.bOverride_AmbientOcclusionIntensity = true;
PPV->Settings.AmbientOcclusionIntensity = 0.5f;

// Vignette
PPV->Settings.bOverride_VignetteIntensity = true;
PPV->Settings.VignetteIntensity = 0.4f;

// Color Grading
PPV->Settings.bOverride_ColorSaturation = true;
PPV->Settings.ColorSaturation = FVector4(1.2f, 1.0f, 0.8f, 1.0f); // per-channel RGBA
PPV->Settings.bOverride_FilmSlope = true;
PPV->Settings.FilmSlope = 0.88f; // 0–1 (default 0.88)
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.
cpp
// 假设PostProcessVolume已分配或找到:
APostProcessVolume* PPV = /* 查找或生成 */;

// 启用并配置
PPV->bEnabled = true;
PPV->bUnbound = true; // 全局效果
PPV->BlendWeight = 1.0f;

// Bloom效果
PPV->Settings.bOverride_BloomIntensity = true;
PPV->Settings.BloomIntensity = 0.5f;

// 自动曝光
PPV->Settings.bOverride_AutoExposureMinBrightness = true;
PPV->Settings.AutoExposureMinBrightness = 0.1f;
PPV->Settings.bOverride_AutoExposureMaxBrightness = true;
PPV->Settings.AutoExposureMaxBrightness = 2.0f;

// 景深(电影级DOF)
PPV->Settings.bOverride_DepthOfFieldFstop = true;
PPV->Settings.DepthOfFieldFstop = 2.8f;
PPV->Settings.bOverride_DepthOfFieldFocalDistance = true;
PPV->Settings.DepthOfFieldFocalDistance = 300.0f; // 单位:厘米

// 环境光遮蔽
PPV->Settings.bOverride_AmbientOcclusionIntensity = true;
PPV->Settings.AmbientOcclusionIntensity = 0.5f;

// 暗角效果
PPV->Settings.bOverride_VignetteIntensity = true;
PPV->Settings.VignetteIntensity = 0.4f;

// 颜色分级
PPV->Settings.bOverride_ColorSaturation = true;
PPV->Settings.ColorSaturation = FVector4(1.2f, 1.0f, 0.8f, 1.0f); // 按RGBA通道设置
PPV->Settings.bOverride_FilmSlope = true;
PPV->Settings.FilmSlope = 0.88f; // 0–1(默认值0.88)
FPostProcessSettings
中的每个字段都有对应的
bOverride_*
布尔值,必须将其设置为
true
才能使对应的值生效。完整字段参考请查看
references/post-process-settings.md

Post-Process Materials (Blendables)

后期处理材质(Blendables)

Material Domain must be "Post Process". Add via:
cpp
PPV->AddOrUpdateBlendable(PostProcessMaterial, 1.0f); // weight 0.0–1.0
材质域必须设置为“Post Process”。通过以下方式添加:
cpp
PPV->AddOrUpdateBlendable(PostProcessMaterial, 1.0f); // 权重范围0.0–1.0

UPostProcessComponent (Actor-Owned)

UPostProcessComponent(Actor所属)

cpp
// Constructor
PostProcessComp = CreateDefaultSubobject<UPostProcessComponent>(TEXT("PostProcess"));
PostProcessComp->bUnbound = true;
PostProcessComp->Priority = 5.0f;

// Runtime
PostProcessComp->Settings.bOverride_BloomIntensity = true;
PostProcessComp->Settings.BloomIntensity = 1.5f;
Includes:
"Components/PostProcessComponent.h"
,
"Engine/PostProcessVolume.h"
,
"Engine/Scene.h"
.

cpp
// 构造函数
PostProcessComp = CreateDefaultSubobject<UPostProcessComponent>(TEXT("PostProcess"));
PostProcessComp->bUnbound = true;
PostProcessComp->Priority = 5.0f;

// 运行时
PostProcessComp->Settings.bOverride_BloomIntensity = true;
PostProcessComp->Settings.BloomIntensity = 1.5f;
包含头文件:
"Components/PostProcessComponent.h"
"Engine/PostProcessVolume.h"
"Engine/Scene.h"

4. Render Targets

4. 渲染目标

Creating a Render Target in C++

通过C++创建渲染目标

cpp
#include "Engine/TextureRenderTarget2D.h"
#include "Kismet/KismetRenderingLibrary.h"

// Option A — via UKismetRenderingLibrary (handles resource init automatically)
UTextureRenderTarget2D* RT = UKismetRenderingLibrary::CreateRenderTarget2D(
    this,          // WorldContextObject
    512,           // Width
    512,           // Height
    RTF_RGBA16f,   // Format (see ETextureRenderTargetFormat)
    FLinearColor::Black,
    false          // bAutoGenerateMipMaps
);

// Option B — manual creation
UTextureRenderTarget2D* RT = NewObject<UTextureRenderTarget2D>(this);
RT->InitCustomFormat(512, 512, PF_FloatRGBA, /*bInForceLinearGamma=*/true);
RT->UpdateResourceImmediate(/*bClearRenderTarget=*/true);
ETextureRenderTargetFormat
values from
TextureRenderTarget2D.h
:
FormatChannelsBits/ChannelUse Case
RTF_RGBA8
RGBA8 fixedLDR color, UI
RTF_RGBA8_SRGB
RGBA8 fixedsRGB color
RTF_RGBA16f
RGBA16 floatHDR color (default)
RTF_RGBA32f
RGBA32 floatHigh precision data
RTF_R16f
R16 floatSingle channel data
RTF_RGB10A2
RGB+A10+2 bitDisplay output
cpp
#include "Engine/TextureRenderTarget2D.h"
#include "Kismet/KismetRenderingLibrary.h"

// 选项A — 使用UKismetRenderingLibrary(自动处理资源初始化)
UTextureRenderTarget2D* RT = UKismetRenderingLibrary::CreateRenderTarget2D(
    this,          // WorldContextObject
    512,           // 宽度
    512,           // 高度
    RTF_RGBA16f,   // 格式(参考ETextureRenderTargetFormat)
    FLinearColor::Black,
    false          // bAutoGenerateMipMaps
);

// 选项B — 手动创建
UTextureRenderTarget2D* RT = NewObject<UTextureRenderTarget2D>(this);
RT->InitCustomFormat(512, 512, PF_FloatRGBA, /*bInForceLinearGamma=*/true);
RT->UpdateResourceImmediate(/*bClearRenderTarget=*/true);
ETextureRenderTargetFormat
的取值来自
TextureRenderTarget2D.h
格式通道每通道位数使用场景
RTF_RGBA8
RGBA8位固定精度LDR颜色、UI
RTF_RGBA8_SRGB
RGBA8位固定精度sRGB颜色
RTF_RGBA16f
RGBA16位浮点HDR颜色(默认)
RTF_RGBA32f
RGBA32位浮点高精度数据
RTF_R16f
R16位浮点单通道数据
RTF_RGB10A2
RGB+A10+2位显示输出

Scene Capture (Security Camera / Minimap)

场景捕捉(监控摄像头/小地图)

cpp
#include "Components/SceneCaptureComponent2D.h"

// In actor constructor
SceneCapture = CreateDefaultSubobject<USceneCaptureComponent2D>(TEXT("SceneCapture"));
SceneCapture->SetupAttachment(RootComponent);
SceneCapture->FOVAngle = 90.f;
SceneCapture->CaptureSource = ESceneCaptureSource::SCS_FinalColorLDR; // or SCS_SceneColorHDR
SceneCapture->bCaptureEveryFrame = true;  // continuous update

// Assign a render target asset or a runtime-created one
SceneCapture->TextureTarget = MyRenderTargetAsset;

// Limit what's captured for performance
SceneCapture->ShowFlags.SetAtmosphere(false);
SceneCapture->ShowFlags.SetFog(false);
cpp
#include "Components/SceneCaptureComponent2D.h"

// 在Actor构造函数中
SceneCapture = CreateDefaultSubobject<USceneCaptureComponent2D>(TEXT("SceneCapture"));
SceneCapture->SetupAttachment(RootComponent);
SceneCapture->FOVAngle = 90.f;
SceneCapture->CaptureSource = ESceneCaptureSource::SCS_FinalColorLDR; // 或SCS_SceneColorHDR
SceneCapture->bCaptureEveryFrame = true;  // 持续更新

// 分配渲染目标资源或运行时创建的渲染目标
SceneCapture->TextureTarget = MyRenderTargetAsset;

// 限制捕捉内容以提升性能
SceneCapture->ShowFlags.SetAtmosphere(false);
SceneCapture->ShowFlags.SetFog(false);

Drawing a Material to a Render Target

将材质绘制到渲染目标

cpp
// Renders a full-screen quad with Material applied to TextureTarget.
// This is expensive (sets render target each call); use canvas API for batching.
UKismetRenderingLibrary::DrawMaterialToRenderTarget(
    this,         // WorldContextObject
    RT,           // UTextureRenderTarget2D*
    MyMaterial    // UMaterialInterface*
);
cpp
// 将材质应用到全屏四边形并渲染到TextureTarget。
// 此操作开销较大(每次调用都会设置渲染目标);批量处理请使用画布API。
UKismetRenderingLibrary::DrawMaterialToRenderTarget(
    this,         // WorldContextObject
    RT,           // UTextureRenderTarget2D*
    MyMaterial    // UMaterialInterface*
);

Canvas Drawing (Batched)

画布绘制(批量处理)

cpp
UCanvas* Canvas;
FVector2D CanvasSize;
FDrawToRenderTargetContext Context;

UKismetRenderingLibrary::BeginDrawCanvasToRenderTarget(this, RT, Canvas, CanvasSize, Context);

// Draw primitives to Canvas here...
Canvas->K2_DrawMaterial(MyMaterial, FVector2D(0, 0), CanvasSize, FVector2D(0, 0), FVector2D(1, 1));

UKismetRenderingLibrary::EndDrawCanvasToRenderTarget(this, Context);
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.
cpp
UCanvas* Canvas;
FVector2D CanvasSize;
FDrawToRenderTargetContext Context;

UKismetRenderingLibrary::BeginDrawCanvasToRenderTarget(this, RT, Canvas, CanvasSize, Context);

// 在此处向Canvas绘制图元...
Canvas->K2_DrawMaterial(MyMaterial, FVector2D(0, 0), CanvasSize, FVector2D(0, 0), FVector2D(1, 1));

UKismetRenderingLibrary::EndDrawCanvasToRenderTarget(this, Context);
UCanvasRenderTarget2D
UTextureRenderTarget2D
的子类,内置
OnCanvasRenderTargetUpdate
委托。用于自动进行2D画布重绘(如小地图、运行时纹理绘制),无需手动调用
BeginDrawCanvasToRenderTarget

Reading Pixels (GPU Stall — Offline Only)

读取像素(GPU阻塞——仅离线使用)

cpp
// WARNING: stalls GPU pipeline. Editor tools / screenshot only, never per-frame.
FColor Pixel = UKismetRenderingLibrary::ReadRenderTargetPixel(this, RT, X, Y);
TArray<FColor> Pixels;
UKismetRenderingLibrary::ReadRenderTarget(this, RT, Pixels);               // whole RT, 8-bit sRGB
FLinearColor Raw = UKismetRenderingLibrary::ReadRenderTargetRawPixel(this, RT, X, Y);

cpp
// 警告:会阻塞GPU管线。仅用于编辑器工具/截图,绝不要每帧调用。
FColor Pixel = UKismetRenderingLibrary::ReadRenderTargetPixel(this, RT, X, Y);
TArray<FColor> Pixels;
UKismetRenderingLibrary::ReadRenderTarget(this, RT, Pixels);               // 读取整个渲染目标,8位sRGB
FLinearColor Raw = UKismetRenderingLibrary::ReadRenderTargetRawPixel(this, RT, X, Y);

5. Decals

5. 贴花

UDecalComponent
projects a material onto surfaces. Key API from
DecalComponent.h
:
cpp
void SetDecalMaterial(UMaterialInterface* NewDecalMaterial);
UMaterialInstanceDynamic* CreateDynamicMaterialInstance(); // MID on the decal
void SetFadeOut(float StartDelay, float Duration, bool DestroyOwnerAfterFade = true);
void SetFadeIn(float StartDelay, float Duration);
void SetSortOrder(int32 Value);  // higher = draws on top
void SetLifeSpan(float LifeSpan);
FVector DecalSize; // local-space extent (not component scale)
UDecalComponent
将材质投射到表面上。
DecalComponent.h
中的关键API:
cpp
void SetDecalMaterial(UMaterialInterface* NewDecalMaterial);
UMaterialInstanceDynamic* CreateDynamicMaterialInstance(); // 贴花的MID
void SetFadeOut(float StartDelay, float Duration, bool DestroyOwnerAfterFade = true);
void SetFadeIn(float StartDelay, float Duration);
void SetSortOrder(int32 Value);  // 值越大,绘制层级越靠上
void SetLifeSpan(float LifeSpan);
FVector DecalSize; // 局部空间范围(不是组件缩放)

Spawning Decals at Runtime

运行时生成贴花

cpp
// 0.0f lifespan = persistent; >0.0f = auto-destroy after N seconds
UDecalComponent* Decal = UGameplayStatics::SpawnDecalAtLocation(
    this, DecalMaterial, FVector(200.f), HitLocation, HitNormal.Rotation(), 0.0f);

// Dynamic parameters on the decal
UMaterialInstanceDynamic* DecalMID = Decal->CreateDynamicMaterialInstance();
DecalMID->SetScalarParameterValue(TEXT("Opacity"), 0.8f);
cpp
// 生命周期为0.0f表示永久存在;>0.0f表示N秒后自动销毁
UDecalComponent* Decal = UGameplayStatics::SpawnDecalAtLocation(
    this, DecalMaterial, FVector(200.f), HitLocation, HitNormal.Rotation(), 0.0f);

// 为贴花设置动态参数
UMaterialInstanceDynamic* DecalMID = Decal->CreateDynamicMaterialInstance();
DecalMID->SetScalarParameterValue(TEXT("Opacity"), 0.8f);

DBuffer vs Non-DBuffer Decals

DBuffer与非DBuffer贴花

  • DBuffer (Translucent + DBuffer enabled): writes before lighting, affects diffuse/normals/roughness. Enable via
    Project Settings > Rendering > DBuffer Decals
    .
  • Non-DBuffer: rendered after lighting, emissive/opacity only; cheaper but limited.
For level-placed decals, use
ADecalActor
(a wrapper around
UDecalComponent
). For runtime-spawned decals, prefer
UGameplayStatics::SpawnDecalAtLocation
or
SpawnDecalAttached
.

  • DBuffer(半透明+启用DBuffer):在光照前写入,影响漫反射/法线/粗糙度。通过
    项目设置 > 渲染 > DBuffer贴花
    启用。
  • 非DBuffer:在光照后渲染,仅支持自发光/透明度;性能开销更低但功能有限。
对于关卡中放置的贴花,使用
ADecalActor
UDecalComponent
的封装)。对于运行时生成的贴花,优先使用
UGameplayStatics::SpawnDecalAtLocation
SpawnDecalAttached

6. Nanite and Lumen (UE5)

6. Nanite与Lumen(UE5)

Nanite

Nanite

Nanite is UE5's virtualized geometry system. Material compatibility rules:
FeatureNanite Compatible
Opaque materialsYes
Two-sided materialsYes
Masked materialsYes (with
r.Nanite.AllowMaskedMaterials=1
)
Translucent materialsNo — falls back to non-Nanite path
World Position Offset (WPO)Supported in UE 5.1+ (
bEvaluateWorldPositionOffset
on mesh)
Pixel Depth OffsetNo
Custom vertex normals via shaderLimited
Check at runtime:
cpp
// Check if a static mesh component is using Nanite (IsNaniteEnabled is on UStaticMesh, not on the component)
bool bIsNanite = StaticMeshComponent->GetStaticMesh() && StaticMeshComponent->GetStaticMesh()->IsNaniteEnabled();
Override material for Nanite path:
cpp
MyMID->SetNaniteOverride(NaniteCompatibleMaterial);
Nanite是UE5的虚拟化几何体系统。材质兼容性规则:
特性是否兼容Nanite
不透明材质
双面材质
遮罩材质是(需设置
r.Nanite.AllowMaskedMaterials=1
半透明材质否 — 回退到非Nanite路径
世界位置偏移(WPO)UE 5.1+支持(在网格上启用
bEvaluateWorldPositionOffset
像素深度偏移
通过着色器自定义顶点法线有限支持
运行时检查:
cpp
// 检查静态网格组件是否使用Nanite(IsNaniteEnabled属于UStaticMesh,而非组件)
bool bIsNanite = StaticMeshComponent->GetStaticMesh() && StaticMeshComponent->GetStaticMesh()->IsNaniteEnabled();
为Nanite路径覆盖材质:
cpp
MyMID->SetNaniteOverride(NaniteCompatibleMaterial);

Lumen

Lumen

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:
cpp
PPV->Settings.bOverride_LumenReflectionQuality = true;
PPV->Settings.LumenReflectionQuality = 1.0f;         // 0–4

PPV->Settings.bOverride_LumenSceneDetail = true;
PPV->Settings.LumenSceneDetail = 1.0f;               // surface cache resolution multiplier

PPV->Settings.bOverride_LumenSceneLightingQuality = true;
PPV->Settings.LumenSceneLightingQuality = 1.0f;
Performance:
r.Lumen.SurfaceCache.UpdateDownsampleFactor
controls cache update rate.
Lumen是UE5的动态全局光照与反射系统。自发光表面可作为光源。半透明表面默认不被追踪。通过后期处理设置控制质量:
cpp
PPV->Settings.bOverride_LumenReflectionQuality = true;
PPV->Settings.LumenReflectionQuality = 1.0f;         // 0–4

PPV->Settings.bOverride_LumenSceneDetail = true;
PPV->Settings.LumenSceneDetail = 1.0f;               // 表面缓存分辨率乘数

PPV->Settings.bOverride_LumenSceneLightingQuality = true;
PPV->Settings.LumenSceneLightingQuality = 1.0f;
性能优化:
r.Lumen.SurfaceCache.UpdateDownsampleFactor
控制缓存更新速率。

Deferred vs Forward Rendering

延迟渲染与前向渲染

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
.
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
.
延迟渲染 vs 前向渲染:UE5桌面端默认使用延迟渲染——几何体写入GBuffer,然后按像素计算光照。前向渲染(移动端、VR)按对象处理光照,支持MSAA,但限制动态光源数量。通过
项目设置 > 渲染 > 前向着色
设置。
可伸缩性:使用
Scalability::SetQualityLevels()
(位于
Scalability.h
)或控制台命令(如
sg.PostProcessQuality 0-3
)在运行时调整渲染质量。在
BaseScalability.ini
中配置预设。

Virtual Shadow Maps (VSM)

虚拟阴影贴图(VSM)

  • WPO materials: enable "Evaluate World Position Offset" in the material's Details panel (material editor setting, not a C++ property) for correct VSM shadows.
  • Masked materials: opacity masks respected correctly.
  • Decals do not cast VSM shadows.
  • WPO材质:在材质的细节面板中启用“Evaluate World Position Offset”(材质编辑器设置,非C++属性),以确保VSM阴影正确。
  • 遮罩材质:透明度遮罩会被正确识别。
  • 贴花不会投射VSM阴影。

Custom Depth / Stencil (Outlines and Effects)

自定义深度/模板(轮廓与特效)

cpp
MeshComponent->SetRenderCustomDepth(true);
MeshComponent->SetCustomDepthStencilValue(1); // 0–255
// Sample CustomDepth / CustomStencil nodes in a post-process material for outlines, X-ray, highlight effects.
Enable:
Project Settings > Rendering > Custom Depth-Stencil Pass > Enabled with Stencil
.

cpp
MeshComponent->SetRenderCustomDepth(true);
MeshComponent->SetCustomDepthStencilValue(1); // 0–255
// 在后期处理材质中采样CustomDepth / CustomStencil节点,实现轮廓、X光、高亮等特效。
启用方式:
项目设置 > 渲染 > 自定义深度-模板通道 > 启用模板

Common Mistakes and Anti-Patterns

常见错误与反模式

Creating MIDs every frame — Each
CreateDynamicMaterialInstance
call allocates a new GPU resource. Create once in
BeginPlay
, cache, update in
Tick
:
cpp
// BeginPlay
CachedMID = MeshComponent->CreateDynamicMaterialInstance(0);

// Tick
if (CachedMID) { CachedMID->SetScalarParameterValue(TEXT("Time"), GetWorld()->TimeSeconds); }
Not caching MID as UPROPERTY — Raw
UMaterialInstanceDynamic*
is invisible to GC and collected on the next GC pass. Use
UPROPERTY() TObjectPtr<UMaterialInstanceDynamic> CachedMID;
.
Wrong parameter names — Names are case-sensitive exact matches.
"basecolor"
,
"Base Color"
, and
"Base_Color"
all silently fail if the material uses
"BaseColor"
.
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
.
Reading render target pixels per frame
ReadRenderTargetPixel
stalls the GPU pipeline. Never call per frame. Use
FRHIGPUTextureReadback
for async non-stalling reads.
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.
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.
Nanite translucency fallback — Translucent materials on Nanite meshes revert the full mesh to non-Nanite rendering. Split into separate opaque and translucent components.

每帧创建MID — 每次
CreateDynamicMaterialInstance
调用都会分配新的GPU资源。在
BeginPlay
中创建一次并缓存,在
Tick
中更新:
cpp
// BeginPlay
CachedMID = MeshComponent->CreateDynamicMaterialInstance(0);

// Tick
if (CachedMID) { CachedMID->SetScalarParameterValue(TEXT("Time"), GetWorld()->TimeSeconds); }
未将MID缓存为UPROPERTY — 原始
UMaterialInstanceDynamic*
对垃圾回收不可见,会在下一次垃圾回收时被回收。使用
UPROPERTY() TObjectPtr<UMaterialInstanceDynamic> CachedMID;
参数名称错误 — 名称需完全匹配且区分大小写。如果材质使用
"BaseColor"
,那么
"basecolor"
"Base Color"
"Base_Color"
都会静默失败。
渲染目标分辨率 — 根据使用场景匹配分辨率:小地图/监控摄像头使用256–512;镜子最大使用512;大型镜子使用平面反射。全屏场景:在
USceneCaptureComponent2D
上启用
bMainViewResolution
每帧读取渲染目标像素
ReadRenderTargetPixel
会阻塞GPU管线。绝不要每帧调用。使用
FRHIGPUTextureReadback
进行异步无阻塞读取。
在复制Actor上使用MID — MID是客户端本地的。不要复制MID指针。复制标量/向量值,并在每个客户端通过
OnRep
函数重新应用。
未设置后期处理的bOverride
FPostProcessSettings
的每个字段都需要将对应的
bOverride_*
布尔值设置为
true
。仅设置值而不启用覆盖会静默无效。
Nanite半透明回退 — Nanite网格上的半透明材质会使整个网格回退到非Nanite渲染。将网格拆分为独立的不透明和半透明组件。

Required Build.cs Dependencies

必需的Build.cs依赖项

csharp
PublicDependencyModuleNames.AddRange(new string[]
{
    "Engine",           // Materials, render targets, UTextureRenderTarget2D
    "RenderCore",       // Low-level render utilities
    "RHI",              // RHI types (EPixelFormat, etc.)
});

// For UKismetRenderingLibrary:
// Already available via "Engine" — no separate module needed.

csharp
PublicDependencyModuleNames.AddRange(new string[]
{
    "Engine",           // 材质、渲染目标、UTextureRenderTarget2D
    "RenderCore",       // 底层渲染工具
    "RHI",              // RHI类型(如EPixelFormat等)
});

// 对于UKismetRenderingLibrary:
// 已通过"Engine"模块提供——无需单独添加模块。

Related Skills

相关技能

  • ue-cpp-foundations
    — UObject management, UPROPERTY, TObjectPtr, garbage collection
  • ue-actor-component-architecture
    — setting up components (UDecalComponent, USceneCaptureComponent2D, UPostProcessComponent)
  • ue-niagara-effects
    — particle materials use MIDs; parameter passing into Niagara from C++
  • ue-project-context
    — engine version, target platforms, rendering feature flags
  • ue-cpp-foundations
    — UObject管理、UPROPERTY、TObjectPtr、垃圾回收
  • ue-actor-component-architecture
    — 组件设置(UDecalComponent、USceneCaptureComponent2D、UPostProcessComponent)
  • ue-niagara-effects
    — 粒子材质使用MID;从C++向Niagara传递参数
  • ue-project-context
    — 引擎版本、目标平台、渲染特性标志