Shader System 设计

职责
提供3D世界中几何体的着色服务,这包括:
Ø         着色脚本系统。
使用 FX 脚本描述着色信息,并且统一 FFP PFP管理。
Ø         着色信息的管理。
着色信息的载入、删除、合并等管理操作。
Ø         渲染管理。
系统使用ShaderQueue(着色队列)的数组来组织Geometry的着色数据,ShaderQueue是按照 Render Priority(渲染优先级别)来排序的。每个 ShaderQueue 内部,将Geometry分为 Solid Alpha,其中 Solid Shading ShaderTree 来组织,Alpha Shading ShaderList 来组织。
概念
Ø         The Definition of the Solid / Alpha Geometry
Geometry本身不能决定是否 Solid,而是由用于这个 Geometry 上的 Shader 来决定。如果 Shader 的任何一个 Pass 中含有 AlphaBlendEnable = ture,则称这个 Shader 所关联的 Geometry Alpha Geometry;反之称为 Solid Geometry。由于相同的 Geometry 可以在不同的时间或者触发事件设置不同的 Shader 效果,比如:event1设置为 Solid Shader1event2设置为Alpha Shader2,由于系统依据Shader来决定 Geometry的渲染管理属性,这样就能保证 Geometry 的正确绘制。
着色信息管理策略
Ø         Pass 中的 RenderStateRenderStateGroup
在载入 Shader 时,将 Pass 中的 RenderState 组合成 RenderStateGroup,如果 Pass 中存在多个 RenderStateGroup,则按照 RSCT 排序。
渲染管理策略
Geometry Shading分为3种基本情况:
Ø         Render Priority
Ø         每个几何体都有自己的Render Priority,比如:天空最先、UI最后等等。
Ø         Solid
非透明物体的渲染工作由一个 ShaderTree 来完成,ShaderTree的详细组织方式在下面描述。ShaderTree的最终目的是为了最小化渲染状态改变。
Ø         Alpha
半透明物体的绘制最重要的是保证绘制的正确性,所以要对半透明物体进行从远到近的排序,绘制时也是按照这个顺序。所以半透明物体用一个从远到近排序的ShaderList来组织的。
 
Geometry加入到ShaderQueue的流程:

 
根据GeometryRenderPriority来确定几何体的 所在的ShaderQueue 位置
Alpha Geometry
 
按照由远到近的顺序加入到 Alpha Shader List
 
加入到 Solid Shader Tree 中。
 
Y
N

类层次结构
参看 UML 设计文档。
数据结构
Shader
Ø       Shader描述了如何渲染物体的信息,包括Texture SetupMaterial PropertyRender StateBlend SetupPixel ShaderVertex ShaderRender Target Setup等等。Shader并不直接和Geometry相关联,因为对于同一个Geometry,有可能会用不同的Shader来渲染。
Ø       Shader Tree 是为了 Minimum Shader State Change,树中每一条 Branch都是一个 shader
 
Shader Tree
Data Structure
Ø         ShaderTreeST): node 的容器,它除了遍历树的功能之外还m包含创建 ShaderTreeBranch 的功能。
Ø         ShaderTreeBranchSTB):ShaderTree 的分支,相当于 Pass
Ø         ShaderTreeNodeSTN):用于构成 ST 的主要数据结构,ST中的非叶 STN 存储了一个RenderGroupST中的Leaf STN存储了Batched Geometry。多个Leaf节点可以共享一个Batched Geometry。当遍历ST时遇到Leaf  STN就开始绘制Batched Geometry
Ø         RenderStateRS):渲染状态的封装。
Ø         RenderStateGroupRSP):渲染状态组,将相同概念的渲染状态组合在一起,分组标准参考 D3D10 State Object 中的 RasterizerDepth StencilBlendSampler
Ø         RSCT状态改变开销表,预定义生成。
 
 
The Policy of Build the Solid Shader Tree
在遍历 SG 中,如果一个 geometry 可视,则将累积的 Shader 合并为一个 Shader,在合并的过程中对Pass中的 RenderStateGroup 按照 RSCT 排序,然后将合并后的 Shader 和这个 Geometry 送到 ShaderTree 中构建 STB。在构建 STB过程时,遍历 Shader 中的每个 Pass,按照已经经过 RSCT 排序的 RenderStateGroup 列表依次创建或者插入 STN,当遇到叶节点时,将关联的 Geometry 加入到这个叶节点中。由于 ST Root Leaf 是按照 cost 的大小排序的,这样就能做到最小状态切换。每个 Leaf 和使用这个 shader tree branch geometry 关联,这样每个 leaf 就会有一个 geometry list。这样就完成了一个 ST 的构建工作。
 
Build shader tree pseudo code
 
BuildBranch( const Shader& shader, Geometry* pGeometry )
{
       For each pass in shader
              RenderStateGroupList& rsgs = pass.getRenderStateGroups();
       // 获取 RSG 列表的最大项和 ST 的根节点
RenderStateGroup& rsgRoot = rsgs.first();
ShaderTreeNode* pSTRoot = GetRoot();
// 调用内部的构建 branch的函数
_BuildBranch(pSTRoot, rsgRoot );
       End for
}
 
_BuildBranch ( pSTNodestateGroup )
{
       Bool bInsert = true;
       // 遍历当前 STN 的每个子节点
       For each child in pSTNode
              // 判断是否与当前的 STN RSP相同
              If ( child.context == stateGroup)
                     // 相同则略过当前 STN,如果 RSG 列表还有下一项,则继续递归
                     bInsert = false;
                     if (state.hasNext )
_BuildBranch ( child, stateGroup.next )
                     Else
                            // 当前 RSG 没有下一项,则将当前的 Geometry 加入到当前的 STN 中。
                            AddGeometry( child, pGeometry );
End if
                    
              End if
       End for
// 如果不相同,则插入标志为真
       If ( bInsert )
              // 用当前的 RSG 创建一个 STN并加入到当前的 STN 为子节点
              Create newSTNode with this stateGroup
              pSTNode.AddChild(newSTNode);
              // 如果 RSG 列表还有下一项,则用新创建的 STN 继续递归
              if (stateGroup.hasNext )
                     _BuildBranch (newSTNode, stateGroup.next );
              Else
                     // 当前 RSG 没有下一项,则将当前的 Geometry 加入到当前的 STN 中。
                     AddGeometry(newSTNode, pGeometry );
              End if
       End if
}
Advertisements
此条目发表在DreamEngine 3D 图形引擎开发分类目录。将固定链接加入收藏夹。

One Response to Shader System 设计

  1. ixnehc说道:

    和你干过类似的事情,后来放弃了,感觉这样做意义不大,因为实际上可以共用render state的情况其实挺少的.我现在也在自己写一个3d engine,有机会可以交流交流,msn:ixnehc@hotmail.com

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  更改 )

Google+ photo

You are commenting using your Google+ account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

w

Connecting to %s