UE4 Shader&绘制过程笔记

  • Post author:
  • Post category:其他


先声明这是一篇记录自己学习的笔记,原文链接:


虚幻4渲染编程(Shader篇)【第十卷:绘制策略】 – 知乎 (zhihu.com)

正如作者所说,部分内容有一点过时,但我觉得对于把握UE的shader一些基本原理,数据传输,存取等还是很有帮助的,所以我们不要把版本放在心上,大胆的了解学习UE中对渲染的处理逻辑。

现在正式开始:


Shader


的生成:


1. Shader一定是在使用之前就编译好的(未来不知道会怎样),从某种角度上说shader可以认为是预编译好的资源,不同的程序不同的环境平台我们需要不同的Shader,也就是说我们一个效果会有很多个shader,要用的时候需要根据不同条件(Level&Macros)去取对应的出来;

2. Shader C++类和Shader一定要区分开。Shader C++类是在CPU端管理控制shader的,shader是在GPU上跑的;

3. Shader的定义,编译,使用是三个分开的过程,不能混在一起看作是一套连贯的线性过程。

UE4的shader C++类型:

Material Shader:允许多份实例,给单个模型用

Mesh Material Shader:允许多份实例,给单个模型用

例如:材质编辑器负责填充一个叫Material Template的模板,Compile的时候,材质编辑器可视化节点便会填充这个MaterialTemplate.usf生成一个函数库HLSL Code。这还没完,compile操作会根据材质编辑器里的各种宏,各种绘制状态,游戏的高中低配分级等条件,编译出很多份Shader,放在FMaterial的

ShaderMap

中。有一个宏,材质编辑器就会编译出两份shader,有两个宏,就会编译出4个,呈指数型上涨。

这些宏由:Common.usf传递


绘制需要对Shader


做两件事:将Shader


编译&


将ShaderCode


放到ShaderMap


中(有很多种类,可理解为一个容器)

Global Shader:只允许存在一份,给全局场景用(Scene Render)

使用

IMPLEMENT_MATERIAL_SHADER_TYPE

等宏实现C++ shader与shader的绑定,其实里边调用的还是

IMPLEMENT_SHADER_TYPE

这个宏会把shader文件路径(可能是虚拟路径),类型等于C++的Shader类型进行绑定,结果存到ShaderMap:


IMPLEMENT_SHADER_TYPE


(,


FLensDistortionUVGenerationVS/*Shader C++


类名,决定类型


*/


,


TEXT


(


“/Plugin/LensDistortion/Private/UVGeneration.usf”


),


TEXT


(


“MainVS”


),

SF_Vertex

)

有了这种绑定就能够通过shader C++类找到ShaderMap获得对应的shadercode

在书写shader C++类的时候可能还使用SetDefault为shader压入过一些宏,这样子就可能使用这种宏来控制渲染的线路,这个宏在shader编译的时候是通过MaterialEnvironment传递的


DrawingPolicy


数据管理:这个过程已经被MeshDrawPipeline取代了

虽然被取代了但是还是可以了解一下,新的Pipeline更加简洁

1.StaticMesh(绘制状态不发生改变,而非静止):DrawList

将模型资源放入场景=》RenderScene:: AddPrimitive函数=》Scene->AddPrimitiveSceneInfo_RenderThread=》FPrimitiveSceneInfo::AddToScene函数=》PrimitiveSceneInfo::AddStaticMeshes函数=》FStaticMesh::AddToDrawLists函数=》根据情况把FStaticMesh加入到各个DrawingPolicyFactory(组织数据)=》各个DrawingPolicyFactory::AddStaticMesh函数=》FScene::DrawList=》在StaticMeshDrawList中完成添加和link

静态模型Draw的时候就直接调用DrawList进行绘制,在DrawList里的DrawingPolicy就已经初始化好了。

StaticDrawList里面储存了DrawingPolicy:

a).DrawingPolicy可以用来在ShaderMap中查找到对应的shader,于是我们绘制时需要使用的shader有了;

b).模型资源放入场景=》DrawingPolicyFactory创建一个batchmesh=》DrawingPolicyFactory创建数个DrawingPolicy分享这个batchmesh=》sort这些DrawingPolicy,绘制时直接取出(SortBasePassStaticData)

2.DynamicMesh

创建DrawingPolicy=》初始化(从MaterialShaderMap拿出Sahder)=》Draw=》RHIComList调用底层

使用shader实际就是将shader取出参与绘制,这个过程没有与shader对象完全写死,而是分离开,方便shader与不同的绘制场景进行组合,重利用,极大地提高了自由度,这部分对shader的使用进行组织和利用的代码就称为DrawingPolicy(负责DrawCall)和DrawingPolicyFactory(组织数据)——参考GlobalShader


UE4


整个绘制过程:

Editor阶段:准备渲染资源,模型贴图动画的导入,场景的搭建(场景的搭建过程其实是DrawList的构建过程,各种LightMap,SH的烘焙过程等等)

Runtime阶段:SceneRender类=》CreateSceneRenderer=》Render=》SceneContex(GBuffer)=》InitView(抽取各种渲染数据:GetDynamicData等)=》各种Pass(如BassPass:写Gbuffer——区分静态与动态模型,分配渲染顺序,调用DrawList,DrawingPolicy)



版权声明:本文为weixin_44212242原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。