UE4时代延迟管线对GBuffer的Encode/Decode工作是直接调用shader中的函数来执行的, 如下所示, 这是BasePassPixelShader.usf中的GBuffer Encode:

可以看到调用了EncodeGBuffer()函数, 其定义在DeferredShadingCommon.ush中:

很普通的函数调用,没什么特殊之处. 然而UE5已经放弃了这套系统,并在代码里硬编码:

这个EncodeGBufferToMRT()函数并没有定义在ush/usf文件中, 而是用C++代码在ShaderGenerationUtil.cpp中程序化生成:

不止Encode, Decode也同样改为了程序化生成的方案:

这样的好处显而易见, 相比于用宏控制, C++代码生成更加的灵活可控. 然而缺点也很明显: 难以在C++代码上扩展 修改与调试, 甚至就连UE代码中注释也这样写道:

The problem is it then becomes a nightmare to step through and debug the lines

不过我们还是有办法去绕过这套C++程序化的系统去改东西, 最简单的就是在原本的函数调用之后追加我们自己的处理, 比如Encode:

而对于Decode函数, 发现在C++代码的最后部分额外调用了一个处理函数:

其定义在GBufferHelpers.ush中, 我们也可以在这里对追加我们对gbuffer的自定义内容.

另外,这个文件里还定义了一个计划在程序化Encode之前做处理的函数, 不过还尚未启用, 可以关注一下UE5.1里有没有使用.