Unreal Engine Shader 开发技巧
- 作者:admin
- /
- 时间:4月23日
- /
- 浏览:584 次
- /
- 分类:厚积薄发
【USparkle专栏】如果你深怀绝技,爱“搞点研究”,乐于分享也博采众长,我们期待你的加入,让智慧的火花碰撞交织,让知识的传递生生不息!
每次稍微改一下引擎的Shader源码,随便修改一行USH文件,引擎都要十几分钟编译Shader,非常影响开发效率,后来开始尝试在RenderDoc里开发Shader,任何USH文件都是秒编译,修改马上就能看到,确实很方便,只恨之前不早早养成这个习惯。
而且Unreal Engine即使不使用引擎源码,也可以直接打开引擎的ShaderDebug功能,直接修改Shader源码。
一、打开Shader调试
修改源码中的配置文件以调试着色器源码ConsoleVariables.ini。
打开ShaderDevelopmentMode时,Shader编译报错不会直接Crash引擎,改一改还能重新编译:
r.ShaderDevelopmentMode=1
打开Shaders.Optimize和Shaders.Symbols可以在Debugger中显示Shader源码:
r.Shaders.Optimize=0
r.Shaders.Symbols=1
更加硬核一点,如果需要使用类似GLSLC命令行来手动编译Shader,那么加上“-g”就可以保留Shader源码:
glslc -g base.frag -o base_frag.spv
在UE5.2之后,可以在[Platform]Engine.ini定义配置,详情见:《Shader Debugging Workflows》。
比如:
;DefaultEngine.ini
[ShaderCompiler]
r.Shaders.Symbols=1
r.Shaders.GenerateSymbols=1
[ShaderCompiler_BuildMachine]
r.Shaders.WriteSymbols=1
r.Shaders.WriteSymbols.Zip=1
二、Shader开发流程
在引擎里搭一个简单测试场景,然后RenderDoc截一帧,记得先打开RenderDoc插件:

命令行:renderdoc.CaptureFrame
如果需要开发和调试GlobalShader或者ComputerShader,这个Shader不是每帧都会被调用或者正常的Capture都无法捕获到,那么就需要在代码里手动捕获:
#include "RenderCaptureInterface.h"
...
// 在GameThread中创建FScopedCapture然后持续监听叫“Xk-MyDrawCallName”的Event,
// 一旦RenderThread开始绘制,就会捕获到这个DrawCall。
RenderCaptureInterface::FScopedCapture RenderCapture(true, TEXT("Xk-MyDrawCallName"));
ENQUEUE_RENDER_COMMAND(MyCustomGlobalShader)([](FRHICommandListImmediate& RHICmdList)
{
TRACE_CPUPROFILER_EVENT_SCOPE(MyCustomGlobalShader_Render);
FRDGBuilder GraphBuilder(RHICmdList, RDG_EVENT_NAME("Xk-MyDrawCallName"));
// Do something...
GraphBuilder.Execute();
});
...
这里创建的RenderCaptureInterface::FScopedCapture,第一个参数是是否开启Capture,第二个参数是需要捕获的DrawCall的EventName,一旦这个DrawCall开始绘制,就会自动被RenderDoc截帧并打开软件。
找到要渲染的物体,我想直接改它的Shader源码,需要先定位到这个DrawCall:

Find the DrawCall
然后去Pipeline State这个窗口,选择需要修改的Shader类型,这里想要修改Vertex Shader,点击Edit。注意,在Vertex Shader Edit窗口,修改Pixel Shader的文件,是不生效的:

然后找到你要修改的文件,比如LocalVertexFactory.ush,直接在RenderDoc写代码,修改完点击Apply changes,修改就直接应用到Shader上了,注意Errors窗口的编译报错:

Shader修改了,Apply changes之后,在Texture Viewer里可以直接查看结果:

Texture Viewer
因为我改了Vertex Shader,所以改变的是顶点的数值,直接去Mesh Viewer中查看下变化,鼠标右键可以直接选择顶点,挨个检查数值:

Mesh Viewer
当渲染都正确之后,把RenderDoc里修改的代码部分,拷贝到引擎的Shader源码里,再重新编译一下引擎检查一下结果:

Unreal Engine Viewport
三、截取其他应用程序
- 在Tools->Settings里开启Global Process Hook:

Tools-Settings
- 指定应用程序启动路径,开启Global Hook:

Enable Global Hook
- 手动启动应用程序,在File->Attach to Running Instance里重新挂载程序:

File-Attach to Running Instance
- From now on,应该可以正常截帧了:

Capture Frame
- 如果你发现RenderDoc无法正常挂载需要截获的程序,那么有可能是你的电脑开启了安全启动(Secure Boot),你需要重启电脑,进入BIOS/UEFI设置:在计算机启动时,你通常需要按下某个特定的键(如F2、F10、F12、Delete或Esc)来进入BIOS/UEFI设置。在BIOS/UEFI设置中,找到“安全启动”或“Secure Boot”选项。这个选项通常位于“启动”、“安全”或“高级”菜单下,然后禁用它。
四、小记
实际使用RenderDoc开发Shader后,发现真的香,之前写Shader需要一遍一遍的编译引擎,非常痛苦,尤其是去修改那几个通用的USH文件,还是在RenderDoc一次写完,然后把代码写回引擎更快。唯一的问题就是RenderDoc的IDE非常简陋。
快捷键【Ctrl+Shift+,】,打开GPU Visualizer,渲染管线的RenderPass,去找源码中对应的代码:

引擎基本架构方便理解引擎代码层级:
工具层(Tool Layer)
地形Landscape工具、植被Foliage工具等
功能层(Function Layer)
多线程,GameThread Tick,RenderThread Submit,RHIThread Submit等
资源层(Resource Layer)
UObject、UStaticMesh、UTexture、USound等
核心层(Core Layer)
数学库FMath,数据结构,内存管理,引擎基础
平台层(Platform/RHI Layer)
操作系统、GraphicsAPI、硬件架构
主要渲染管线入口
Console & PC Renderer入口:
void FDeferredShadingSceneRenderer::Render(FRDGBuilder& GraphBuilder)
{
}
Mobile Renderer入口:
void FMobileSceneRenderer::Render(FRDGBuilder& GraphBuilder)
{
//...
if (bDeferredShading)
{
RenderDeferred(GraphBuilder, SortedLightSet, ViewFamilyTexture, SceneTextures);
}
else
{
RenderForward(GraphBuilder, ViewFamilyTexture, SceneTextures);
}
//...
}
Mobile Forward Shading入口:
void FMobileSceneRenderer::RenderForward(FRDGBuilder& GraphBuilder, FRDGTextureRef ViewFamilyTexture, FSceneTextures& SceneTextures)
{
}
Mobile Deferred Shading入口:
void FMobileSceneRenderer::RenderDeferred(FRDGBuilder& GraphBuilder, const FSortedLightSetSceneInfo& SortedLightSet, FRDGTextureRef ViewFamilyTexture, FSceneTextures& SceneTextures)
{
}
这是侑虎科技第1800篇文章,感谢作者徐門子美供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)
作者主页:https://www.zhihu.com/people/BloodyGuys
再次感谢徐門子美的分享,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)