UE4变体研究 源码剖析
在编辑器打开时,会从资源包中LoadPackage,我们这里只关心的是材质问题。每一个Obj,都会调用自己的Obj->ConditionalPostLoad()
这里已经是在加载的后端了,在这里面会调用子类的PostLoad()
|
|
我们只看 UMaterial::PostLoad,如果调用到这里,也就是说我们加载的是一个材质。这是一个非常长的函数。就不在这里展开了。
这里会调用他父类的PostLoad
,而UMaterial
的父类就是UMaterialInterface
,而他们的区别,和主要的成员分析见Unreal Material类的关系
在UMaterialInterface::PostLoad()
中又会调用UMaterial::CacheResourceShadersForRendering
- Cache resource shaders for rendering.
- If a matching shader map is not found in memory or the DDC, a new one will be compiled.(关于什么是DDC,听过很多次)
- The results will be applied to this FMaterial in the renderer when they are finished compiling.
- Note: This modifies material variables used for rendering and is assumed to be called within a FMaterialUpdateContext!
|
|
这里是只对我们将渲染到的level进行cache,在cooked build中,没有着色器编译,但这仍然是注册加载的shadermap(啥?) CacheShadersForResources这是最主要的函数,我们将要进去,看它是如何进行cache,并且看它都cache的什么东西。
|
|
从上面可以看出,我们最终的cache还是要在回到FMaterialResource身上,这里只是做了保护而已,所以继续往下。
|
|
这里我们终于来到了一个新的天地,因为我们终于不在Umaterial里面了,而是在FMaterialResource的父类FMaterial里面,
这里主要有两个重要函数
一个是FMaterialResource::GetShaderMapId ,另一个是CacheShaders
FMaterialResource::GetShaderMapId
首先就是调用父类的FMaterial::GetShaderMapId(Platform, OutId);这里最终得到的是FMaterialShaderMapId 关于这个结构体和其他相关结构体的内容可以参见Material相关类 GetShaderMapId:
|
|
最开始做的判断是是否已经加载了这个material的shadermap,如果有的话我们还要判断是在哪个线程中就从GameThreadShaderMap获取还是RenderingThreadShaderMap获取。
GetDependentShaderAndVFTypes
否则的话,我们就需要进行ShaderMap的填充,GetDependentShaderAndVFTypes就是填充的关键。
- 对所有的VertexFactoryType进行判断
- 这个顶点工厂必须是使用在Material里的
- 从每一个FShaderType中得到FMeshMaterialShaderType,如果FMeshMaterialShaderType不是空&&FMeshMaterialShaderType可以cache这个VertexFactoryType,那么我们就允许增加这个AddUnique(ShaderType),并且在最后的时候会增加这个VertexFactoryType
- 从每一个FShaderPipelineType判断是否用于meshmaterial,并且要判断FShaderPipelineType里面所有的shadertype的,如果它里面的所有的shader都通过判断,那么我们就增加这个FShaderPipelineType
- 对所有的FShaderType进行判断
- 和上面的一样,不过判断条件VertexFactoryType改为了null
- 对所有的FShaderPipelineType进行判断
- 同上 其实我们只是对判断依据感兴趣而已。
todo:判断条件是传进来的函数指针,还没有搞清楚来源 这样,我们就讨论完了GetShaderMapId
FMaterialShaderMapId::SetShaderDependencies
下面的函数时FMaterialShaderMapId::SetShaderDependencies,主要就是记录它的hash值,然后记录下来,这里的疑问就出来了。
当我们的FMaterial::GetShaderMapId分析完后,我们就要回到 FMaterialResource::GetShaderMapId里面
|
|