游戏引擎Flax Engine源码分析(十三)渲染

2021SC@SDUSC


一、简述

        这篇博客我们继续之前的内容,分析2D渲染的其他内容,上一章我们分析了一部分与字体相关的内容,这一篇我们继续分析余下内容。

二、分析

        (一)、字体管理器FontManager

        概述:字体管理和字符集管理实用程序服务。

        具体结构如下:

class FLAXENGINE_API FontManager
{
public:
    static float FontScale;
    static FT_Library GetLibrary();
    static FontTextureAtlas* GetAtlas(int32 index);
    static bool AddNewEntry(Font* font, Char c, FontCharacterEntry& entry);
    static void Invalidate(FontCharacterEntry& entry);
    static void Flush();
    static void EnsureAtlasCreated(int32 index);
    static bool IsDirty();
    static bool HasDataSyncWithGPU();
};

        下面我们具体解释每个属性和函数的意义以及作用:

        FontScale:全局字符字体比例因子。 用于在高 DPI 显示器上放大字符。

        GetLibrary:获取 FreeType 库。返回库

        GetAtlas:获取纹理图集。参数为图集索引

        AddNewEntry:将给定字体中的字符添加到缓存中。"font"为其创建字符条目的字体。"c"要添加的字符"entry"创建的字符条目。返回值:如果不能向字体缓存添加新字符条目则为真,否则为假

        Invalidate:使缓存的动态字体字符无效。 可用于在更改字体资产选项后重新加载字体字符。"entry"字体字符入口。

        Flush:刷新所有字体图集。

        EnsureAtlasCreated:确保已创建具有给定索引的图集

        IsDirty:确定一个或多个字体图集是否脏。

        HasDataSynWithGPU:确定所有地图集是否已与 GPU 内存同步并且数据是否是最新。true 如果所有地图集都已与 GPU 内存同步并且数据是最新的;

        我们再看一下字体管理器的初始化方法:

        

Init()
{
    ASSERT(Library == nullptr);

    FontManager::FontScale = (float)Platform::GetDpi() / (float)DefaultDPI; // TODO: Adjust this at runtime

    FreeTypeMemory.user = nullptr;
    FreeTypeMemory.alloc = &FreeTypeAlloc;
    FreeTypeMemory.realloc = &FreeTypeRealloc;
    FreeTypeMemory.free = &FreeTypeFree;
    const FT_Error error = FT_New_Library(&FreeTypeMemory, &Library);
    if (error)
    {
        LOG_FT_ERROR(error);
        return true;
    }
    FT_Add_Default_Modules(Library);

    FT_Int major, minor, patch;
    FT_Library_Version(Library, &major, &minor, &patch);
    LOG(Info, "FreeType initialized, version: {0}.{1}.{2}", major, minor, patch);

    return false;
}

        首先断言库不为空,FontScale缩放 UI 字体以匹配显示器 DPI。

        初始化FreeType。记录版本信息。 

        字体管理器FontManager中最复杂的部分是向其中添加条目,源代码在这里不再贴出,仅解释具体流程:

bool FontManager::AddNewEntry(Font* font, Char c, FontCharacterEntry& entry)

        获取锁。设置加载标志。

        获取字体中字形的索引。

        加载字形。处理特殊效果。

        将字形渲染到位图。

        填写字符数据。

        分配内存。

        空字形结束。

        光栅化后复制字形数据(逐行)。

        标准化不使用 256 色的灰度图像。

        如果使用临时位图,则释放。

        查找字符纹理的图集,将字符添加到纹理,检查结果,如果没有添加空字符。

        检查这个字符是否没有图集,创建新图集,初始图集,将字符添加到纹理。

        填充图集相关数据。


         (二)、字体纹理图集FontTextureAtlas

        概述:包含缓存字体字形图集的纹理资源。

        结构体struct Slot : RectPack<Slot>,继承自RectPack,RectPack使用填充将矩形打包到 2D 图集中的实现。 使用简单的空间划分。

        一下枚举描述如何处理纹理图集填充:

enum PaddingStyle
    {
        NoPadding,
        DilateBorder,
        PadWithZero,
    };

        NoPadding:不填充地图集。 

        DilateBorder:将纹理扩大一个像素以填充图集。

        PadWithZero:一个用零填充的像素统一填充边框。

        接下来包括基本的Get、Set方法,以及一些功能函数;

    

void Setup(PixelFormat format, PaddingStyle paddingStyle);

    void Init(uint32 width, uint32 height);

    Slot* AddEntry(uint32 targetWidth, uint32 targetHeight, const Array<byte>& data);

    bool Invalidate(uint32 x, uint32 y, uint32 width, uint32 height);

    void CopyDataIntoSlot(const Slot* slot, const Array<byte>& data);

    void Clear();

    void Dispose();

    void Flush();

    void EnsureTextureCreated() const;

    bool HasDataSyncWithGPU() const;

        SetUp:创建后设置图集。"format"像素格式。"paddingStyle"填充样式。

        Init:初始化图集。"width"宽度。"height"高度。

        AddEntry:将新条目添加到地图集"targetWidth"条目的宽度。"targetHeight"条目的高度。"data"数据。返回新条目占用的atlas槽。

        Invalidate:使来自地图集的缓存动态条目无效。"x"插槽位置(以图集像素为单位的 X 坐标)。"y"插槽位置(以图集像素为单位的 Y 坐标)。"width"槽宽度(以图集像素为单位的大小)。"height"槽高度(以图集像素为单位的大小)。返回如果槽已被释放则为真,否则为假。

        CopyDataIntoSlot:将数据复制到插槽中。"slot">插槽。"data"数据。

        Clear:清除此地图集条目数据(不更改大小/纹理等)。

        Dispose:清除此地图集条目数据(不更改大小/纹理等)。处置整个地图集数据(纹理、节点等)。

        Flush;将此图集数据刷新到 GPU

        EnsureTextureCreated:确保已为该图集创建纹理。

        HasDataSynWithGPU;确定图集是否有与 GPU 同步的数据。

        这里也简单介绍一下AddEntry的流程:

FontTextureAtlas::Slot* FontTextureAtlas::AddEntry(uint32 targetWidth, uint32 targetHeight, const Array<byte>& data)

        检查无效尺寸。

        尝试为纹理找到插槽。

        检查是否适合它,将数据复制到图集内存中,设置脏位。

        返回结果。


        以上就是本篇博客的全部内容,关于2D渲染的部分已基本分析结束 ,剩余的一点内容将在下一篇博客进行分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值