游戏编程模式之享元模式

使用共享模式以高效地支持大量的细粒度对象。
(摘自《游戏编程模式》)

  该如何介绍共享模式呢?其实,“共享”一词就给出了答案。顾名思义,共享是指将一份作为共有部分供大多数运用。其实,我个人认为它的本质就是抽象化,即将一组对象的公共部分抽象起来并作为一个实例,这一实例将存储于所有对象中,供其使用。这样的抽象化使得重复的数据大大减少,从而提高了程序的运行效率。

简单的例子

  在某个战争游戏中,我们需要将成千上万的士兵渲染至同屏中。使用享元模式便可以提高其运行效率,首先我们要做的就是找出士兵模型的共同点,例子如下:

  • Mesh 网格
  • Animation 动画
  • Weapon 手持的武器
  • Attack Target 攻击目标

  我们需要将上述的共同点封装成一个类。并在士兵类中添加全局实例的指针——这就使得同一类士兵将公用一个SoldierModel实例。

class SoldierModel
{
    public:
        Mesh mesh;
        Animtion playAnim;
        WeaponType wp;
        GameObject attackTarget;
}

class Soldier
{
    private:
        SoldierModel* sm;
    
        Vector3 position;
        //...
}

  这就是享元模式。在此例子中,由于士兵的规模和公共部分数据较少,因此运行效率提升将不会那么直观。在《游戏编程模式》一书提到的森林渲染的例子将能更直观的体验到享元模式的魅力。


森林之树

  在森林场景中,需要进行大量树的渲染。关于树的数据需要载入内存,这对内存是一大考验;除此之外,渲染树的数据也需要从CPU传递至GPU并在GPU进行图形绘制,而我们都知道,I/O一直是制约软件运行效率的一个最重要的因素。因此,在编程中,减少硬件与硬件之间传输数据量成为重中之重。
  享元模式就成了很好的工具,我们可以将树分成两个独立的部分,并将所有数目通用的数据放到一个单独的类中。
  在CPU向GPU传输数据这一过程中,无论是Direct3D还是OpenGL,都支持实例绘制,即传输两组数据——通用数据和差异化数据即可。


总结

  享元模式关键字在于享,把一个对象的公共数据资源抽离成一个实例,因此所有的对象都可以公用这一个实例,减少了计算量。

原文地址:https://www.cnblogs.com/ZhuSenlin/p/15424685.html