UE5中添加自定义ViewMode
在UE5中,通过定制ViewMode(如Lighting Only)可以实现不同的渲染调试工具。以下是步骤介绍和代码示例:
目标
我们将通过学习并修改UE5的Lighting Only
工具,从源码入手,实现以下自定义ViewMode:
- Diffuse Only
- Specular Only
- Direct Lighting Only
- Indirect Lighting Only
此外,还可以添加新的ViewPort控件显示调试信息。
步骤
1. 定义自定义ViewMode
文件:EngineBaseTypes.h
在此文件中找到Lighting Only
定义片段:
1
2
/** Lit wo/ materials. */
VMI_LightingOnly = 5 UMETA(DisplayName = "Lighting Only"),
然后添加自定义ViewMode的定义:
1
2
3
4
5
6
7
8
9
// Custom View Mode
/** Diffuse Only */
VMI_DiffuseOnly = 30 UMETA(DisplayName = "Diffuse Only"),
/** Specular Only */
VMI_SpecularOnly = 31 UMETA(DisplayName = "Specular Only"),
/** Direct Lighting Only */
VMI_DirectLightingOnly = 32 UMETA(DisplayName = "Direct Lighting Only"),
/** Indirect Lighting Only */
VMI_IndirectLightingOnly = 33 UMETA(DisplayName = "Indirect Lighting Only"),
2. 设置显示标志
文件:ShowFlagsValues.inl
在ShowFlagsValues.inl文件中,我们可以看到如下代码行:
1
SHOWFLAG_FIXED_IN_SHIPPING(0, LightingOnlyOverride, SFG_Hidden, NSLOCTEXT("UnrealEd", "LightingOnlyOverrideSF", "Lighting Only"))
注释写道:
1
needed for VMI_LightingOnly, Whether to override material diffuse with constants, used by the Lighting Only viewmode.
译为: VMI_LightingOnly需要,是否使用常量替代材质漫反射,仅照明视图模式使用。
类推, 在后方添加:
1
2
3
4
5
6
7
8
9
// Custom View Mode
/** Diffuse Only */
SHOWFLAG_FIXED_IN_SHIPPING(0, DiffuseOnlyOverride, SFG_Hidden, NSLOCTEXT("UnrealEd", "DiffuseOnlyOverrideSF", "Diffuse Lighting Only"))
/** Specular Only */
SHOWFLAG_FIXED_IN_SHIPPING(0, SpecularOnlyOverride, SFG_Hidden, NSLOCTEXT("UnrealEd", "SpecularOnlyOverrideSF", "Specular Lighting Only"))
/** Direct Lighting Only */
SHOWFLAG_FIXED_IN_SHIPPING(0, DirectLightingOnlyOverride, SFG_Hidden, NSLOCTEXT("UnrealEd", "DirectLightingOnlyOverrideSF", "Direct Lighting Only"))
/** Indirect Lighting Only */
SHOWFLAG_FIXED_IN_SHIPPING(0, IndirectLightingOnlyOverride, SFG_Hidden, NSLOCTEXT("UnrealEd", "IndirectLightingOnlyOverrideSF", "Indirect Lighting Only"))
注意: ShowFlagsValues.inl 会被ShowFlags.h中的struct FEngineShowFlags类使用。生成一个成员属性。
3. 查找并返回自定义ViewMode
文件:ShowFlags.cpp
在FindViewMode
函数中找到以下代码行:
1
2
3
4
else if (EngineShowFlags.LightingOnlyOverride)
{
return VMI_LightingOnly;
}
然后为每个自定义ViewMode添加判断语句:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
else if (EngineShowFlags.DiffuseOnlyOverride)
{
return VMI_DiffuseOnly;
}
else if (EngineShowFlags.SpecularOnlyOverride)
{
return VMI_SpecularOnly;
}
else if (EngineShowFlags.DirectLightingOnlyOverride)
{
return VMI_DirectLightingOnly;
}
else if (EngineShowFlags.IndirectLightingOnlyOverride)
{
return VMI_IndirectLightingOnly;
}
在EngineShowFlagOverride函数中
1
2
Some view modes want some features off or on (no state)
某些视图模式需要关闭或打开某些功能(无状态)
添加:
注意:此处有问题未解决
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
if (ViewModeIndex == VMI_DiffuseOnly)
{
EngineShowFlags.SetDiffuse(true);
EngineShowFlags.SetSpecular(false);
EngineShowFlags.SetMaterials(true);
}
if (ViewModeIndex == VMI_SpecularOnly)
{
EngineShowFlags.SetSpecular(true);
EngineShowFlags.SetDiffuse(false);
EngineShowFlags.SetMaterials(true);
}
if (ViewModeIndex == VMI_DirectLightingOnly)
{
EngineShowFlags.SetDirectLighting(true);
EngineShowFlags.(false);
EngineShowFlags.SetMaterials(false);
}
if (ViewModeIndex == VMI_lndirectLightingOnly)
{
EngineShowFlags.(true);
EngineShowFlags.SetDirectLighting(false);
EngineShowFlags.SetMaterials(false);
}
4. 应用视图模式
在ApplyViewMode
函数中,通过switch
语句控制自定义模式的后处理效果。添加如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
// 开启后处理
case VMI_DiffuseOnly:
bPostProcessing = true;
break;
case VMI_SpecularOnly:
bPostProcessing = true;
break;
case VMI_DirectLightingOnly:
bPostProcessing = true;
break;
case VMI_lndirectLightingOnly:
bPostProcessing = true;
break;
然后,在switch
语句末尾添加以下判断:
1
2
3
4
EngineShowFlags.SetDiffuseOnlyOverride(ViewModeIndex == VMI_DiffuseOnly);
EngineShowFlags.SetSpecularOnlyOverride(ViewModeIndex == VMI_SpecularOnly);
EngineShowFlags.SetDirectLightingOnlyOverride(ViewModeIndex == VMI_DirectLightingOnly);
EngineShowFlags.SetIndirectLightingOnlyOverride(ViewModeIndex == VMI_IndirectLightingOnly);
5. 显示自定义ViewMode名称
文件:ViewModeNames.cpp
在FillViewModeDisplayNames
函数中,添加以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Custom View Mode
else if (ViewModeIndex == VMI_DiffuseOnly)
{
ViewModeDisplayNames.Emplace(LOCTEXT("UViewModeUtils_VMI_DiffuseOnly", "Diffuse Only"));
}
else if (ViewModeIndex == VMI_SpecularOnly)
{
ViewModeDisplayNames.Emplace(LOCTEXT("UViewModeUtils_VMI_SpecularOnly", "Specular Only"));
}
else if (ViewModeIndex == VMI_DirectLightingOnly)
{
ViewModeDisplayNames.Emplace(LOCTEXT("UViewModeUtils_VMI_DirectLightingOnly", "Direct Lighting Only"));
}
else if (ViewModeIndex == VMI_IndirectLightingOnly)
{
ViewModeDisplayNames.Emplace(LOCTEXT("UViewModeUtils_VMI_IndirectLightingOnly", "Indirect Lighting Only"));
}
6. 绑定命令
文件:EditorViewportCommands.h
在FEditorViewportCommands
类中添加如下定义:
1
2
3
4
5
/** Custom View Mode */
TSharedPtr< FUICommandInfo > DiffuseOnlyMode;
TSharedPtr< FUICommandInfo > SpecularOnlyMode;
TSharedPtr< FUICommandInfo > DirectLightingOnlyMode;
TSharedPtr< FUICommandInfo > IndirectLightingOnlyMode;
在EditorViewportCommands.cpp
中,RegisterCommands
函数中注册命令:
1
2
3
4
UI_COMMAND(DiffuseOnlyMode, "Diffuse Only View Mode", "Diffuse Only Mode", EUserInterfaceActionType::RadioButton, FInputChord());
UI_COMMAND(SpecularOnlyMode, "Specular Only View Mode", "Specular Only Mode", EUserInterfaceActionType::RadioButton, FInputChord());
UI_COMMAND(DirectLightingOnlyMode, "Direct Lighting Only View Mode", "Direct Lighting Only Mode", EUserInterfaceActionType::RadioButton, FInputChord());
UI_COMMAND(IndirectLightingOnlyMode, "Indirect Lighting Only View Mode", "Indirect Lighting Only Mode", EUserInterfaceActionType::RadioButton, FInputChord());
7. 绑定Viewport命令
文件:SEditorViewport.cpp
在BindCommands
函数中绑定各ViewMode:
1
2
3
4
MAP_VIEWMODE_ACTION(Commands.DiffuseOnlyMode, VMI_DiffuseOnly);
MAP_VIEWMODE_ACTION(Commands.SpecularOnlyMode, VMI_SpecularOnly);
MAP_VIEWMODE_ACTION(Commands.DirectLightingOnlyMode, VMI_DirectLightingOnly);
MAP_VIEWMODE_ACTION(Commands.IndirectLightingOnlyMode, VMI_IndirectLightingOnly);
8. 添加ViewPort菜单
文件:SEditorViewportViewMenu.cpp
在FillViewMenu
函数中添加菜单项:
1
2
3
4
Section.AddMenuEntry(BaseViewportActions.DiffuseOnlyMode, UViewModeUtils::GetViewModeDisplayName(VMI_DiffuseOnly));
Section.AddMenuEntry(BaseViewportActions.SpecularOnlyMode, UViewModeUtils::GetViewModeDisplayName(VMI_SpecularOnly));
Section.AddMenuEntry(BaseViewportActions.DirectLightingOnlyMode, UViewModeUtils::GetViewModeDisplayName(VMI_DirectLightingOnly));
Section.AddMenuEntry(BaseViewportActions.IndirectLightingOnlyMode, UViewModeUtils::GetViewModeDisplayName(VMI_IndirectLightingOnly));