• 关于游戏中的材质系统


    材质,这个词有各行各业都有自己的解释。

    美工把物体贴图和物体颜色,高光等统称为材质。D3D和OPENGL这样的图形接口则把物体表面贴图单独叫做纹理,而把漫反射,高光等叫做材质。

    而在游戏引擎或图形引擎中提到的材质,则与此不同。 引擎中提到的材质不仅上面的的内容。 引擎中所谓的材质,是指物体在渲染时一系列的状态控制。 如,ALPHA混合开关以及ALPHA混合因子、纹理过虑方式,纹理通道状态、纹理矩阵、裁剪模式等,在D3D中,就是SetRenderState,SetTextureStageState,SetSamplerStateState等所控制的。在OPENGL中,则大多数由glEnable所控制。

    我们所提到的材质系统,则是以此为基础展开的。 上面提到的这些因子,组成了我们的材质。 也是我们在渲染一个物体的时候,提交到设备的状态控制值。 一个物体的一次渲染,我们称作一个PASS。于是我们顺其自然地将这个渲染时的材质控制的最小单位命名为Pass,则:

    struct TextureState

    {

        void* Texture;

        int ColorOp;

        int ColorAgr1;

        int ColorAgr2;

        int AlphaOp;

        int AlphaAgr1;

        int AlphaAgr2;

    .....//更多内容

    };

    class CPass

    {

       CColor mAmbient;

       CColor mDiffuse;

       ....更多内容

        bool mAlphaEnable;

        int mScrBlend;

        int mDstBlend;

        int mCullMode;

       TextureState[4] mTextureStates;

      ...更多内容

    };

    当我们渲染一个物体的时候,只需要将这个类里面的状态应用到设备,即可完成对物体的绘制。

    材质系统的基本内容就是这些,这也是最容易做到的事情。

    但是,我们都知道,像D3D或OPENGL这样的图形接口每设置一次GPU状态的时候,都会有一定的开销(通过查看相关文档可以看到某些函数的具体开销值)。而为了保证我们的渲染流畅,我们不得不减少这样的开销。

    很自然地,我们会想到,尽量减少切换。而如何减少切换呢。我们可以记录下自己的硬件状态,在设置下一个的时候,先判断当前硬件状态是否相同,如果相同。则不用再设置。 虽然某些图形接口在其层底做了类似的功能。但我们外部判断一下,也未尝不可。从D3D上来讲,外部判断比让其内部判断效率更佳。需要注意的是,由于我们在自己的程序里做了相同判断。因此,当有另一个程序也修改设备状态的时候,就会产生意想不到的效果。所以,我们应该适当的查询一下设备状态,并更新自己的状态记录表。至于这个查询间隔,就要根据自己的实际情况来测试了。

    通过记录状态的方法来提升的效率是很不明显的,因此,我们需要对材质进行排序,至于怎么排序,这算法上的问题,在此先不作过多解释。 总之,我们将相似的材质排在一起。由于材质很相似,绘完一个再绘下一个的时候,减少了切换,从而大大提升了效率。

    既然已经是涉及到设备了,我们总得考虑一下设备问题。 如果设备不支持我们当前给定的材质状态,怎么办? 返回FALSE不渲染。还是让程序DOWN掉?  对于一些重要的性能,设备不支持让程序DOWN掉是最好的做法,但是,对于像纹理混合通道不足的情况,让其DOWN掉就显得划不来了。毕竟我们设计的游戏程序是想让更多的玩家能玩不是? 这样就会涉及到PASS的拆分问题。

    对于PASS的拆分,OGRE已经做得很好了。根据用户的设备性能,如果不满足,就一直拆分,拆到用户满足为止,最后让一个物体渲染多次,来实现多个纹理通道混合的效果。 而多PASS则是在渲染的时候不得不考虑的地方,毕竟有些物殊效果非得用多PASS不可。

    对于多PASS的设计,我们可以参考OGRE的材质方法或是D3DX的效果框架。我们把完成一个最终效果的方案称作一个渲染技术 Technique ,一个技术可由多个Pass来完成。

    class Technique

    {

    ...更多内容

     vector<CPass*> mPasses;

    };

    这样就满足了我们的需求。  对于同一种效果,我们可以提供多种Technique供程序选择。 而这个选择的条件则可以是根据硬件性能,或是玩家手动选择的配置来实现。

    最后结构如下:

    class CMaterial

    {

    public:

    ...更多内容

    vector<CTechnique*> mRenderTechs

    };

    乱七八糟地说了一通,希望没晕死人!!!

  • 相关阅读:
    Python笔记:日期时间获取与转换
    算法笔记:递归、动态规划
    容器技术介绍:Docker Dockerfile语法与指令
    Netdiscover网络扫描工具
    持续集成:jenkins + pytest + selenium + Git + Allure自动化测试
    MySQL数据库基础入门
    Parameters 至少一个参数没有指定
    C/C++ 延时函数 (标准库)
    TabController控件测试
    contentEditable
  • 原文地址:https://www.cnblogs.com/qilinzi/p/1940516.html
Copyright © 2020-2023  润新知