首页 > 其他分享 >享元模式学习笔记

享元模式学习笔记

时间:2022-08-28 18:23:08浏览次数:77  
标签:享元 对象 模式 实例 笔记 GPU 每棵 数据

引用

微信读书——游戏编程模式

前言

“使用共享以高效地支持大量的细粒度对象。”
迷雾升起,一片雄伟、古老而茂盛的森林在眼前展现。数不尽的远古铁杉迎面扑来,宛如一座绿色的大教堂。漫天树叶像是褪色的巨大玻璃穹顶,将阳光滤碎成细密的水雾。透过高大树干的间隙,你能感到这庞大的森林往远方渐逝。这是每一个游戏开发者都梦寐以求的超现实游戏场景,这样的游戏场景通常会使用一个模式来实现,它有个很低调的名字:享元模式。

森林之树

数以千计的树木,每一棵树木又包含着成千上万的多边形。即便你有足够的内存来存储这片森林,为了在屏幕上面渲染出森林,所有的数据也必须按照一定的方式进行组织并沿着总线从CPU传送到GPU里去。
每一棵树都有一些与之关联的数据:

  1. 一个多边形网格:它定义了树干、树枝和树叶的几何描述。
  2. 树皮和树叶的纹理。·树在森林中的位置以及朝向。
  3. 调节参数:如大小、颜色等,以使每棵树看起来都不一样。

如果你想用代码表述上面的特征,那么将得到类似如下的结构:

class Tree
{
    private:
        Mesh mesh_;
        Texture bark_;
        Texture leaves_;
        Vector position_;
        double height_;
        double thickness_;
        Color barkTint_;
        Color leafTint_;
};

这里的数据量很大,尤其是网格和纹理。想要将包含整片森林的对象数据在一帧内传给GPU几乎是不可能的。好在,有一个老办法可以解决这个问题。

如果你让美工为整片森林的每棵树单独制作独立的模型,那要么你是疯子,要么你就是个亿万富豪。

我们可以将对象分割成两个独立的类。首先,我们将所有树木通用的数据放到一个单独的类中:

class TreeModel
{
    private:
        Mesh mesh_;
        Texture bark_;
        Texture leaves_;
};

整个游戏只需要一份这样的数据,因为没有理由为相同的网格和纹理分配成千上万份内存。然后,游戏世界中每一颗树的实例都有一个指向共享的TreeModel的引用。Tree类中的其他数据成员用来形成树木之间的差异:

class Tree
{
    private:
        TreeModel* model_;
        Vector position_;
        double height_;
        double thickness_;
        Color barkTint_;
        Color leafTint_;
};

为了最大程度地减少发送到GPU上的数据量,我们希望只发送一次共享数据——TreeModel。然后我们再单独地将每棵树实例的特有数据——位置、颜色和缩放比推送到GPU。最后,我们告诉GPU,“使用那个共享的模型来渲染每个实例”。

享元模式

享元(Flyweight),顾名思义,一般来说当你有太多对象并考虑对其进行轻量化时它便能派上用场。
在实例绘制时,在总线上往GPU传输每棵树的数据所花费的时间,与这些数据所占用的内存都是问题所在,但解决这两个问题的基本思想是一致的。
享元模式通过将对象数据切分成两种类型来解决问题。

  1. 第一种类型数据是那些不属于单一实例对象并且能够被所有对象共享的数据。GoF将其称为内部状态(the intrinsic state),但我更喜欢将它认为是“上下文无关”的状态。在本例中,这指的便是树木的几何形状和纹理数据等。
  2. 其他数据便是外部状态(the extrinsic state),对于每一个实例它们都是唯一的。在本例中,指的是每棵树的位置、缩放比例和颜色。就像上面的示例代码一样,这个模式通过在每一个对象实例之间共享内部状态数据来节省内存。

总结

享元模式的精髓在于“享”,把一个对象的公共资源抽象成一个实例,并分享出去,让所有对象都可以公用,从而减少计算量,但也正是如此享元对象一般总是不可变。

标签:享元,对象,模式,实例,笔记,GPU,每棵,数据
From: https://www.cnblogs.com/948245132ljx/p/16633314.html

相关文章

  • Fiddler学习笔记--基础了解(7)
    首次打开Fiddler默认是不会捕获HTTPS,需要配置后方可捕获HTTPStools--FiddlerOptions--HTTPS,然后将界面选项全部勾选上如果我们有远程监控需求,需要切换值connections,......
  • delphi TdxBarManager学习笔记
    一.WholeRow工具显示模式WholeRow:true工具栏单独在一行显示,不管你有几个内含元素默认为WholeRow:false,即同一行内可以排列多个工具栏,像下图就同时排列了三个工具栏......
  • MySQL Replication -- 无损半同步模式下的主从数据不一致问题
    无损半同步复制基础不管是无损半同步(losslesssemi-syncreplication)还是增强半同步,说的都是AFTER_SYNC模式的半同步复制,针对参数rpl-semi-sync-master-wait-point,官方......
  • 【C++-笔记】override与final说明符
    在effectiveC++中提到C++没有Java那样的finalclasses的禁止派生的机制,遂想到在C++Primer中好像提到过final说明符,正好就连带着override说明符一起复习一下了。简介首......
  • 【算法笔记】一文解决数组类型算法题(1)
    本文主要介绍数据结构中的数组,以及LeetCode题库下面相关题型的分类和解法套路。数组理论概述定义数组是存储在一块连续内存上的,由相同元素集合组成的数据结构。利用索......
  • web应用模式和api接口
    web应用模式:前后端不分离(客户端看到的内容和所有界面效果都是由服务端提供出来的)  2.前后端分离(把前端的界面效果(html,css,js分离到另一个服务端,python服务......
  • 单例模式的介绍
     单例模式是设计模式中常用的设计模式之一,它提供一种创建对象的方式。这种模式仅涉及一个单一的类,该类负责创建自身的对象(下面称对象为实例),同时确保只有一个对象被创......
  • 论文笔记-Multi-Adversarial Domain Adaptation
    摘要文章提出了一种多对抗域自适应(MADAMulti-AdversarialDomainAdaptation)方法,它能够捕捉多模式结构以基于多个域鉴别器实现不同数据的细粒度对齐。ps:其实就......
  • 数据库学习笔记 (本数据库学习笔记以SQL sever 2019 为例进行学习) 20220824 第二节课
    什么是数据模型?数据模型:是对现实世界数据特征的抽象,他是用来描述数据、组织数据和对数据进行操作的。在数据库中用数据模型这个工具来抽象、表示和处理现实世界中的数据......
  • REDIS-读书笔记
    1Redis的概念:Redis是一种key-value类型的内存数据库,可以用于保存string,list,set,sortedset,hash等多种数据结构。由于整个数据库统统加载在内存中进行操作,所以性能也非常出......