游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3829|回复: 9

关于directx渲染系统设计方案的思考

[复制链接]

9

主题

249

帖子

260

积分

中级会员

Rank: 3Rank: 3

积分
260
发表于 2007-8-19 14:28:00 | 显示全部楼层 |阅读模式
最近,想做一个directx渲染系统,所以设计了如下方案:

1、封装接口中的材质结构如下:

    //! Identify the color of material
    typedef int ID_MATERIAL_COLOR;
    //! Identify the state of material
    typedef int ID_MATERIAL_STATE;
    //! Identify the texture of material
    typedef int ID_MATERIAL_TEXTURE;
    //! Identity the whole material
    typedef int ID_MATERIAL;


    //! Default material ID
    const ID_MATERIAL CONST_DEFAULT_MATERIAL_ID = -1;


    //! Max texture number for one material
    const int CONST_MATERIAL_MAX_TEXTURES = 4;

    //!
    struct SMaterialColor
    {
        SColor diffuse;
        SColor ambient;
        SColor specular;
        SColor emissive;
        float  fPower;
    };

    //!
    struct SMaterialState
    {
        // texture stage state setting ...
        // alpha or not ...
        // ...
    };

    //!
    struct SMaterialTexture
    {
        union
        {
            struct
            {
                ITexture *pTex0;
                ITexture *pTex1;
                ITexture *pTex2;
                ITexture *pTex3;
            };

            ITexture *pTexArray[CONST_MATERIAL_MAX_TEXTURES];
        };
    };


    //!
    struct SMaterial
    {
        ID_MATERIAL_COLOR      colorId;
        ID_MATERIAL_STATE        stateId;
        ID_MATERIAL_TEXTURE  texId;
    };


2、封装directx实现的材质结构如下:

    struct SD3D9MaterialColor
    {
        D3DCOLORVALUE D3DDiffuse;
        D3DCOLORVALUE D3DAmbient;
        D3DCOLORVALUE D3DSpecular;
        D3DCOLORVALUE D3DEmissive;
        float         fPower;
    };

    struct SD3D9MaterialState
    {
    };

    struct SD3D9MaterialTexture
    {
        union
        {
            struct
            {
                IDirect3DBaseTexture9 *pD3DTex0;
                IDirect3DBaseTexture9 *pD3DTex1;
                IDirect3DBaseTexture9 *pD3DTex2;
                IDirect3DBaseTexture9 *pD3DTex3;
            };

            IDirect3DBaseTexture9 *pD3DTexArray[CONST_MATERIAL_MAX_TEXTURES];
        };
    };

    struct SD3D9Material
    {
        SD3D9MaterialColor     *pMColor;
        SD3D9MaterialState      *pMState;
        SD3D9MaterialTexture  *pMTexture;
    };

3、接口IRenderSystem的设计:

      IRenderSystem下添加如下方法:
        //!
        virtual ID_MATERIAL_COLOR registerMaterialColor(SMaterialColor matColor) = 0;

        //!
        virtual ID_MATERIAL_STATE registerMaterialState(SMaterialState matState) = 0;

        //!
        virtual ID_MATERIAL_TEXTURE registerMaterialTexture(SMaterialTexture matTex) = 0;

        //!
        virtual ID_MATERIAL registerMaterial(SMaterial material) = 0;



4、接口IRenderSystem的子类CD3D9RenderSystem对各种材质结构的数组保存形式如下:

        // -- material structure --
        arrayS<SD3D9MaterialColor*>      m_pD3DMaterialColorArrayS;

        arrayS<SD3D9MaterialState*>      m_pD3DMaterialStateArrayS;

        arrayS<SD3D9MaterialTexture*>  m_pD3DMaterialTextureArrayS;

        arrayS<SD3D9Material*>               m_pD3DMaterialArrayS;

5、在CD3D9RenderSystem中添加如下结构,用来临时保存要渲染的数据:

        arrayS<SPrimitiveDataProxy*>  m_pPrimitiveDataProxyArrayS;

      其中,关于SPrimitiveDataProxy结构的定义如下:

    //!
    struct SPrimitiveDataProxy
    {
        ID_MATERIAL      m_iMaterialId;
        EVertexType         m_EVertexType;
        EPrimitiveType    m_EPrimType;
        void*                       m_pVertexData;
        unsigned short*  m_pIndexData;
        unsigned int         m_uiPrimitiveCount;
        unsigned int         m_uiVertexStride;
    };

       并且,m_pPrimitiveDataProxyArrayS的长度和m_pD3DMaterialArrayS的长度保持相等。

6、具体的渲染流程如下:

(1)、定义自己要用的材质SMaterial mat;
(2)、调用接口IRenderSystem的方法ID_MATERIAL registerMaterial(SMaterial material)将自定义的材质mat注册到系统内部,在系统内部,对应的SMaterial结构将被转变为SD3D9Material结构,并存到m_pD3DMaterialArrayS中;(由于该步为预处理,所以效率问题不重要)
(3)、不断重复(1)、(2)步,于是,在预处理阶段就在系统内部建立起了一个保存各类材质的数组m_pD3DMaterialArrayS;
(4)、在系统内部,对m_pD3DMaterialArrayS中的所有元素进行排序,建立一个排序后的索引数组,其中对 SD3D9Material的排序,内部又涉及到SD3D9MaterialTexture、SD3D9MaterialState和SD3D9MaterialColor共3个成员的排序,这里的原则是:排序时SD3D9MaterialTexture的优先级最高,SD3D9MaterialState次之,SD3D9MaterialColor最后;
(5)、此时,到了渲染网格的阶段,每渲染网格时,都会调用IRenderSystem的方法void renderPrimitives(SPrimitiveDataProxy& primDataProxy)将要渲染的数据暂存到m_pPrimitiveDataProxyArrayS中,其中,m_iMaterialId相同的SPrimitiveDataProxy将合并到一起,当如下条件:
                        如:渲染图元的顶点类型或图元类型改变,从而不能进行合并,
                                全局的一些渲染状态已经改变,比如:剪切类型、雾态、等等,
                               directx的present函数被调用,
                               等等,,,
满足时,才真正把渲染数据送到显卡渲染;
(6),,,


                                   以上就是主要的设计思想,不知从合理度、效率等方面考虑,是否可行?

27

主题

179

帖子

259

积分

中级会员

Rank: 3Rank: 3

积分
259
发表于 2007-8-21 01:13:00 | 显示全部楼层

Re:关于directx渲染系统设计方案的思考

考虑的不错,给你加几点:

1. 每个material的id 最好用一个 64位 unsigned int 表示。当然如果你用 128位 unsigned int, 使用__mm128关键字, 也可以。这样可以相对减少排序复杂度。

2. 对于游戏里所有的texture和effect,最好分别有个 texture manager和effect manager, 对于相同的texture和effect,给一个相同的 id: 分别是 texture id 和 effect id。 每个id是个8位的 byte就足够了。同时支持256个effect和texture在内存中差不多是极限。

3. 关于material 的 id, 还需要包含物体的一些信息和到camera的距离,一般来说, 大概的定义如下:
union{
  struct {
    unsigned int    objectType       : 8;
    unsigned int    effectID         : 8;
    unsigned int    textureStage1    : 8;
    unsigned int    textureStage2    : 8;
    unsigned int    textureStage3    : 8;
    unsigned int    textureStage4    : 8;
    unsigned int    distanceToCamera : 8;
    unsigned int    renderstate      : 8;
  }
  unsigned __int64  matId;
}
上面的结构只支持4个texturestage,如果你要支持更多,可以适当的修改。

里边的objectType可以用来区分opaque, transparent 和 hud. 比如opaque 的id 是 1000, transparent是 0100, hud是 0010, 这样排序时候可以保证是先渲染 opaque, 然后transparent,然后是hud.

对于effect 和 texture 哪个放在前面,主要是看哪种资源更换的更频繁。这个需要你具体测试才知道。关于距离的问题,对于opaque,需要做位反操作,因为是从近到远排序。 同时对于transparent的物体,distance可能要和effect或者texture stage 1的位置换以下,因为从远到近排序更重要一些。

还有对于material的内部const value或者render state排列,很多时候是在build time进行的。当然怎么做最后还是你自己决定。

4. 还有看来你目前只考虑了material的系统。也可以算是effect system. 但是effect system的话还是缺少 post effect 的支持。 其次是光靠这里排序是不够的,因为很多effect内部可以改变render states. 因此你还需要增加一个effect states manager,DX里边就有这个, 你用 effect state manager搜下dx文档就知道了。具体结构可以参考 shader X4里边 "tips and tricks for d3dx effects-based renderers".


5. 最后,如果没有scene management, 和 scene graph, 还不能算是完整的render system.

0

主题

228

帖子

285

积分

中级会员

Rank: 3Rank: 3

积分
285
发表于 2007-8-21 13:36:00 | 显示全部楼层

Re:关于directx渲染系统设计方案的思考

写的不错

1367

主题

1993

帖子

2118

积分

金牌会员

Rank: 6Rank: 6

积分
2118
发表于 2007-8-21 19:08:00 | 显示全部楼层

Re:关于directx渲染系统设计方案的思考

up

9

主题

249

帖子

260

积分

中级会员

Rank: 3Rank: 3

积分
260
 楼主| 发表于 2007-8-21 19:46:00 | 显示全部楼层

Re:关于directx渲染系统设计方案的思考

看了aear的指点,有一种柳暗花明又一村的感觉,不过我不明白在材质里保存distanceToCamera 有什么用,而且只有8位,能干啥呢?排序的对象不是几何体吗?distanceToCamera 不是应该在几何体上吗?
         
           就这个问题了,求指点下

9

主题

249

帖子

260

积分

中级会员

Rank: 3Rank: 3

积分
260
 楼主| 发表于 2007-8-26 18:56:00 | 显示全部楼层

Re:关于directx渲染系统设计方案的思考

考虑将视景体的近截面和远截面间的距离减少些,2^8的精度也是不错的

27

主题

179

帖子

259

积分

中级会员

Rank: 3Rank: 3

积分
259
发表于 2007-8-28 02:11:00 | 显示全部楼层

Re:关于directx渲染系统设计方案的思考

距离不需要是真正的距离,只需要能够表示物体的远近关系就够了。因为如果near clipping plane到far clipping plane如果有10000的话,也许你只需要关心前2000的物体排列。2000以为的都不用考虑,因为2000以为你把 distanctToCamera = realDistance * 256 / 2000, 2000以外的统统都是256,这在大部分情况下都够用了。当然你也可以用16位表示。 具体情况具体分析吧。

还有就是这里的排序实际上是每frame都要进行一次的。举个例子: 比如2个物体: A B, 每个物体都有wood 和 glass 2个material ,那么就需要4个material id: A-Wood A-Glass B-Wood B-Glass.然后排列进行渲染。正常排出来顺序是: A-wood b-wood b-glass a-glass,如果glass是透明的,而且A比B近。

9

主题

249

帖子

260

积分

中级会员

Rank: 3Rank: 3

积分
260
 楼主| 发表于 2007-8-28 21:05:00 | 显示全部楼层

Re:关于directx渲染系统设计方案的思考

非常感谢啊

36

主题

1047

帖子

1147

积分

金牌会员

Rank: 6Rank: 6

积分
1147
发表于 2007-8-29 20:33:00 | 显示全部楼层

Re: Re:关于directx渲染系统设计方案的思考

aear: Re:关于directx渲染系统设计方案的思考

考虑的不错,给你加几点:

1. 每个material的id 最好用一个 64位 unsigned int 表示。当然如果你用 128位...

其实使用 d3dx effect 的 state manager 接口并不实用,因为使用 d3dx effect 接口作为材质系统的实现,其本身的排序粒度太大,同时不能做到最小化 effect 之间的状态切换和最小化切换的开销,这种排序方法只能实现针对相同材质的物体不作多余的状态设置,但不能避免不同材质的状态的重复设置,而且最重要的是无法做最小化状态切换的开销,而这往往是影响性能的瓶颈。

9

主题

249

帖子

260

积分

中级会员

Rank: 3Rank: 3

积分
260
 楼主| 发表于 2007-8-30 22:30:00 | 显示全部楼层

Re:关于directx渲染系统设计方案的思考

实践是检验真理的唯一标准!
看来我得加紧编码了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 02:48

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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