Gamebryo材质系统详解(Shader Tree)

接触GB引擎也有大半年了,这段时间一直是在做与渲染相关的内容,所以对GB的材质系统也有了那么点点了解

在这里用口水话来叙述一下它的结构和原理,可能有些地方不详细,甚至会有理解错误的,希望大家多多指教。

其实网上有很多文章都已经介绍过GB的材质系统了,不过我看了下大部分都是直接翻译的GB文档里面的内容,

而我这里是按照我的意思,用我的叙述方式来给大家分享一下,有什么地方说错了的,还希望大家纠正一下,谢谢!

 

Gamebryo材质系统详解(Shader Tree)_第1张图片

先看上图,这是我临时使用简单的UML工具建立的GB材质系统结构图,把主要的元素列出来了,标注了他们的关系(图里只用了继承、依赖、聚合)

下面我们从上到下一个一个的讲解每个类的功能:

NiMaterial

这个类是核心的类,它和NiMaterialLibrary也是唯一暴露了接口(NiMaterial::GetMaterial)给外部逻辑使用的类,其实这个类其他接口我没用过

(除了SetDefaultWorkingDirectory,它是设置ShaderTree生成的Shader文件目录的)。此类中有一个重要的静态成员ms_pkMaterials,所有

的材质被创建之后都会被放在这个数组中。

 

NiMaterialDescriptor

此类在shader tree也是一个非常核心的类,它负责在运行时刻通过获取用户设置的属性(NiProperty),以及而外的数据信息(NiExtraData)来

保存当前状态信息到成员,然后在生成Shader的逻辑过程中获取这些信息来决定Shader tree应该怎么生成,应该使用哪些Shader节点,应该怎么

排列这些节点,并且引擎还会把这些状态信息存入的集合的标识存入一个数组,当下一个物体的状态于当前状态一致的时候就不用再重新生成Shader,

而直接从Cache中获得对应的材质对象。这些渲染状态其实是可以自定义的,并非DX的硬件渲染状态!(我第一次听说这个的时候还以为是DX内置的

渲染状态呢 -。-!)此对象的生成和使用是在NiFragmentMaterial::GenerateDescriptor函数中(再次注明此状态通过物体的属性来决定的)。

 

NiGPUProgramDescriptor

该类其实和NiMaterialDescriptor大同小异,NiMaterialDescriptor是整个完整着色程序所有的渲染状态的集合,而此类只是区分了顶点着色程序和

像素着色程序而已。例如:NiStandardVertexProgramDescriptor和NiStandardPixelProgramDescriptor

 

NiMaterialNode

它是对shader程序的函数进行封装,每个NiMaterialNode就代表一个完整的shader函数,此类中可以定义函数的多个传入参数和传出参数,而它的

子类NiMaterialFragmentNode才可以函数内容、描述,而函数内容则可以指定多个,根据不同的shader版本选择对应的函数内容(这点比较灵活)

 

NiMaterialNodeLibrary

此类是着色程序片段的集合,它代表一个或者多个完整的shader代码的超级集合,其实就是一个“工具箱”,在生成shader的逻辑中通过函数名字来

筛选需要的节点,然后组成一个完成的shader程序。

 

NiMaterialInstance

此类是NiAVObject包装材质的一个中间产物,通过此类可以使用同一个材质实例包装出多个材质对象给物体使用,这样就保证全局只有一个材质对象

 

NiMaterialLibrary

从类名的语义上大家都应该知道它主要是做什么的,它有两个方法非常常用:

GetMaterial:从当前NiMaterial的静态数组中获取材质

CreateMaterial:如果材质不存在,则从材质库(也许是使用DLL来封装的材质库)中创建一个材质

 

NiFragment

此类其实是一个辅助类,它帮助NiMaterial的子类分担部分可独立的工作,并且还会把自己所以来的NiMaterialNodeLibrary拷贝给所帮助的材质类

 

NiTerrainFragmentLighting

它是地形的辅助类,主要负责地形材质的光照部分,例如动态灯光,阴影贴图的着色程序的生成

 

NiFragmentOperations

此类也是地形的辅助类,主要负责地形材质的着色程序中类型转换、简单运算等相关工作

 

NiSingleShaderMaterial

此类是一个特殊的材质对象,它是负责从文件加载shader代码并初始化此对象,它支持NSF、FX、FXL格式文件,而它不是通过文件名

来索引shader的,而是通过文件里面的技术(FX:technique)和实现(NSF:Implementation)来识别的。

 

NiStandardMaterial

其实这个类都没什么将的了,GB文档和网上许多文章都详细讲解了此类,我这里就简单的带过一下,它其实就是使用shader tree封装了

一个标准的、完整的、超大集合功能函数,基本上可以识别引擎里面所有标准的渲染状态(例如:雾NiFogProperty、Alpha混合等等)
此类是可以被扩展的,意思就是在项目中可以替换标准材质,具体方案请联系作者,这里就不多讲了。

 

NiTerrainMaterial,NiWaterMaterial

类似NiStandardMaterial,具体就不多说,其实地形感觉比NiStandardMaterial还要复杂,因为它多了2个辅助类出来,里说负责只是

相对于内容而言,不管它再复杂,它的原理都是一样的,详细就只有靠自己去研究了。

 

NiSpotShadowWriteMaterial

它继承标准材质,也就意味着它包含了标准材质所有的内容和特性,并且它在标准材质的基础上特例化了部分内容。

 

终于表述完了,我相信我描述的应该足够详细了(至少比目前其他的文章要详细点),希望读者看了能帮助你快速理解GB的材质系统,

这里只是描述了GB材质系统的结构和每个元素的功能,下一篇文章准备继续讲解GB材质的工作原理,也就是说材质是怎么被生成出来的,

又是怎么被应用的,最后是怎么运转的!

 

至于上一篇的水还没来得及优化,是因为目前项目还没打算花时间优化,不过它是肯定需要优化的,也有优化的地方,等优化完了再继续详解水吧

 

小弟博客刚开不久,希望大家发表评论支持一下,非常感谢!

 

好了,时间非常晚了,得睡觉了,大家晚安!

你可能感兴趣的:(tree)