找回密码
 立即注册
查看: 148|回复: 1

大象无形UE笔记十四:渲染系统(二)

[复制链接]
发表于 2023-3-24 16:16 | 显示全部楼层 |阅读模式
概述

  接上一节:大象无形UE笔记十三:渲染系统(一)
  本节主要探讨一下材质与shader相关,对应原书11.3.2,11.5等节,不过原书提及较为简略,这里我会拓展一下着重分享一些书上并未提及的内容。
  由于UE5.0的复杂性,这节继续在UE4.27的基础上分析虚幻引擎的材质与shader。
开启shader代码调试功能

  修改配置

  在上一节,我们已经安装过了RenderDoc插件,已经可以在游戏中接帧分析一帧中渲染所做的事情。那么我们怎么能在RenderDoc截帧中看到具体的shader代码呢,我们需要修改UnrealEgine/Engine/Config/目录的ConsoleVariables.ini 文件,主要修改如下配置:
r.Shaders.AllowCompilingThroughWorkers=0
r.Shaders.Optimize=0
r.Shaders.KeepDebugInfo=1
r.DisableEngineAndAppRegistration=1


然后我们再次启动编辑器时会发现比较慢。这是因为我们刚才改了Shader要保持调试信息,所有要重新生成一次所有的shader,这个时候如果发现内存占用非常大的话,可以参照如下文章:
UE4编译shader内存占用过大问题分析
简单来说就是修改 FShaderCompilingManager::ReleaseJob 函数,增加一行:
Job->PendingShaderMap.SafeRelease();


截取一帧

现在我们编译并打开UE4编辑器,进入游戏,按 ~ 唤出命令控制台输入框,输入“renderdoc.CaptureFrame”,截取一帧试试:


我们可以在RenderDoc的左栏展开 PostProcessing 然后点击倒数第二的Tonemap 1288x614里面的DrawIndexed(3)



我们从Texture Viewer视图可以看到这个pass,基本上就是渲染出最终结果图:


实时修改Shader代码

我们可以点击 "Pipeline State",然后点击“Pixel Shader”,点击“Edit”,如下图:


然后我们可以看到这个pass的像素着色器代码:


我们可以在MainPS(...)函数的代码的OutColor = TonemapCommonPS(...);代码的下面增加一行:
OutColor = OutColor * float4(0.2, 0.4, 0.6, 1.0);
然后我们点击左上角的“Apply changes”应用修改,并切回“Texture View”查看shader修改结果:




我们可以看到renderdoc里面的渲染效果已经实时修改了。看起来比原图更暗蓝了一些,就像太阳还没升起来的清晨一般。而且我们可以通过renderdoc快速修改shader代码以查看效果了,特别棒!
我们先回退这个修改。 我们接下来再继续深入研究一下更多shader与材质相关的知识!
渲染Pass分类

  Mesh Pass

  我们在 renderdoc 的截帧中可以看到,有些DrawCall传入的Index比较多,比如在PrePass 中绘制桌子时的DrawIndexed(12960), 以及在BassPass中绘制桌子的DrawIndexed(12960),这两个都是Mess Pass,因为它把整个桌子的Mesh顶点数据都传进来绘制了,我们也可以在Mesh View中看到这个桌子的Mesh几何造型信息:


  我们可以得出,在PrePass,以及ShadowDepths,BassPass中,使用的大部分都是 Mesh Pass,即把整个Mesh的3D几何体信息绘制到屏幕上。
Global Pass

  我们再来看看renderdoc 的截帧,我们可以看到,在AO,Lights,以及PostProcessing中的DrawCall,很多只有3个Index,调用的是DrawIndexed(3),即一个屏幕空间的三角形。这个就是Global Pass。我们可以展开 DiffuseIndirectAndAO,以及Lights->DirectLighting->ShadowdLights->StandardDeferredLight。以及PostProcessing -> ComposeSeqaratedTranslucency看到它们的几何体:


Pass总结

  所以我们在渲染中有两种不同的pass,一种是3D多边形空间的Mess Pass,以及屏幕空间的 Global Pass。其中PrePass和BasePass等大部分都是Mess Pass。而光照,后处理等大部分都是 Global Pass。


材质节点图与shader代码

  材质节点图

  我们知道在新的3D可编程渲染管线中,要渲染物体到屏幕中,需要调用Vertex Shader和Pixel Shader等代码,那么虚幻引擎的材质节点图是怎么生成Vertex Shader和Pixel Shader代码呢?我们先来打开一个M_TableRound的材质节点图来看看:


  上图就是M_TableRound的材质节点图。它就是截帧中在BassPass中渲染桌子的3D几何信息到多个不同的RenderTarget中,以便实现后面的延时光照的,如下图:


  我们先理解一下这个M_TableRound的材质节点图。首先我们可以把预览材质效果的默认的球体改成我们的桌子。 我们现在内容浏览器点击StarterContent/Props/里面的SM_TableRound,然后再点击预览窗口底下的“茶壶”按钮,就可以看到材质预览变成了我们的桌子了:


我们从材质节点图中可以看到,有一个红绿图纹理节点,它的绿色通道区域是表示桌子的金属的脚:


  我们先来看下面的两个节点。我们桌面的区域的粗糙度RoughtnessTop为0.1086,而桌脚的粗糙度RoughnessBottom为0.3115,也就是说桌面光滑一些。在下面的Lerp节点中,对RoughtnessTop与RoughnessBottom进行了混合。当红绿图的绿色通道为0时,即使用RoughtnessTopy(0.1086),当绿色通道为1时,则使用RoughnessBottom(0.3115)。
我们再来看看金属度,桌面的金属度为0,而桌脚的金属度为1,我们是用一个Lerp(0, 1,)节点,来对它们进行混合计算的:



    最后我们来看基础颜色,这里我们桌面的颜色ColorTop是橙色,然后桌脚的颜色ColorBottom是白色,我们也是在一个Lerp节点通过红绿图的绿色通道的区域,对两个颜色进行混合,然后我们还需要乘以一下红绿图红色通道让它桌脚的颜色更有层次感。


最后,我们还有一张法线贴图,直接连上Normal的输入即可:


  在这里我们可以大概得出一个结论,材质节点图只是用来获取PBR光照所需要的“基础颜色”,“金属度”,“粗糙度”和“Normal”等输入参数,因为每个不同的3D对象,它的“基础颜色”等属性存放的地方可能不一样。所以需要用一个材质节点图来快速区分一下不同资源的各个属性的获取方法。比如除了桌子的桌面和桌脚是用固定的颜色之外,很多时候可能“基础颜色”也可能使用一张diffuse纹理贴图来存放。同样,金属度和粗糙度也可能使用单独的mask贴图来存放。所以我们需要一个材质节点图来区分这些模型的不同。
  shader代码

  那么这些模型如何在BassPass中渲染到6个不同的RenderTarget呢?它的PixelShader的入口函数MainPS()又在哪里呢?
在我们的UnrealEngine的Engine\Shaders\Private目录下有很多 *.usf ,*.ush文件,其中usf后缀名是表示(Unreal Shader File)的意思,而ush表示(Unreal Shader header)即头文件的意思。MainPS()函数可以在PixelShaderOutputCommon.ush中找到,另外,BasePass的很多shader代码放在BasePassPixelShader.usf文件中。



也就是说,我们最终的Shader代码,是由 材质节点图 + BasePassPixelShader.usf 等shader代码共同生成的。其中材质节点图主要用来获取不同美术资源的“基础颜色”,“粗糙度”等的属性。而usf的shader代码主要用来处理渲染到6个不同RenderTarget以提供给延迟光照用。即:


完整shader代码

我们可以在RenderDoc截帧中看到这个代码是如何组合的,首先我们选中左边的BasePass中的M_TableRound,并选择右边Pipeline State 的 PS, 然后点击 Edit:


我们把打开的shader代码拉到靠近最下面,可以看到MainPS()入口函数,我们看到MainPS()调用了FPixelShaderInOut_MainPS()函数,而这个函数调用了CalcMaterialParametersEx()函数,进而调用了CalcPixelMaterialInputs()函数。我们从CalcPixelMaterialInputs()函数看到了材质节点图的生成代码:


  所以我们的材质节点图是通过生成CalcPixelMaterialInputs()函数的shader代码最终嵌入到完整的shader代码中的。
总结

  好的,我们的材质与shader这节就分享到这里了。下一节会继续分享UE4的渲染相关,敬请期待!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2023-3-24 16:16 | 显示全部楼层
写的好棒[爱]
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-4-30 12:07 , Processed in 0.700308 second(s), 28 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表