游戏编程模式:轻量级(Flyweight)模式(Part II)

2、一千个实例

        为了让我们必须推送给GPU的数据量达到最小,我们想要能够将共享数据——就是TreeModel类——只发送一次。然后,我们单独地传递每一棵树的实例的独特数据——就是它的位置、颜色和缩放。最后,我们告诉GPU,“使用那一个模型来渲染每一个实例。”

        幸运的是,今天的图形API和图形卡正好支持这一点。相关的细节很fiddly,并且超出了本书的范围,但是不论是Direct3D和OpenGL都可以做一种叫做instanced rendering的事情。

        在这两类API中,你都要提供两个数据流(streams of data)。第一个数据流就是那个会被渲染多次的公共数据——就是我们前面的森林例子中的网格和贴图。第二个数据流就是一个列表,它由各个实例及其将要被用于在每次绘制第一部分数据时对其进行变动的参数所组成。只要调用一次draw函数,整片森林就长出来了。

        “这个API直接由图形卡所实现”这一事实意味着轻量级模式可能是唯一一个需要实际的硬件支持的四人帮设计模式。


3、轻量级模式

        现在我们已经有了一个具体的例子了,那么我可以向你介绍这种模式的一般形式了。轻量级,顾名思义,在你拥有一些需要变得更加轻量(lightweight)的对象的时候派上用场,而这通常是因为它们的数量太多了。

        使用instanced rendering的时候,我们要处理的问题,与其说是耗费太多的内存,不如说是耗费太多的时间来将每一棵树送到去往GPU的公交车上,但是基本的思路是一样的。

        该模式解决问题的方式是将一个对象的数据分成两类。第一类数据就是与该对象的单个的实例无关、并且可以被所有对象所共享的东西。四人帮把这叫做内在(intrinsic)状态,但是我喜欢把它想成“与上下文无关”(context-free)的东西。在当前的例子中,这就是树的几何形状和贴图。

        剩下的数据就是外在(extrinsic)状态,就是与实例有关的数据。在当前的例子中,那就是每棵树的位置、缩放和颜色。就像上面的示例代码所显示的那样,这个模式通过在有对象出现的每一个地方共享内在状态的同一份拷贝的方式来节省内存。

        从我们目前看见的东西看来,这很像是基本的资源共享,很难值得被称作是一个模式。其实这失之偏颇,因为在我们的这个例子中,我们可以将被共享的状态分离而得到一个清晰的个体:TreeModel类。

        我发现这个模式在用于没有一个表示被共享对象的良好定义的个体的场合时不太明显(也因此更加聪明)。在这些情形下,感觉上更像是一个对象魔术般地同一时刻出现在多个地方。让我给你们看看另外一个例子。


你可能感兴趣的:(游戏开发,C++,设计模式)