多通道有向距离场图集生成器

这是一个使用 MSDFgen 生成紧凑字体图集的实用工具。

该图集生成器从 TTF 或 OTF 字体文件中加载字形的子集,为每个字形生成距离场,并将它们紧密地打包到图集位图中(如下例所示)。完成的图集和/或其布局元数据可以导出为 Artery Font 文件、纯图像文件、CSV 表格或结构化的 JSON 文件。

Atlas example

字体图集通常存储在纹理内存中,用于在实时渲染环境(如视频游戏)中绘制文本。

图集类型

该图集生成器可以生成以下六种类型的图集。

硬掩码 软掩码 SDF PSDF MSDF MTSDF
Hard mask Soft mask SDF PSDF MSDF MTSDF
通道 1 (1 位) 1 1 1 3 4
抗锯齿 -
可伸缩性 - -
锐角 - - - -
柔和效果 - - - -
硬朗效果 - - -

注释

开始使用

此项目既可以用作库,也可以用作独立的控制台程序。有关如何将其用作库的示例,请参见页面底部。要立即开始使用该程序,可以在 “发布”部分 中下载 Windows 二进制文件。要从源代码构建项目,可以使用包含的 CMake 脚本。在其默认配置中,它需要 vcpkg 作为第三方库依赖项的提供者。如果将环境变量 VCPKG_ROOT 设置为 vcpkg 目录,CMake 配置将负责从 vcpkg 获取所有必需的软件包。

命令行参数

对于独立版本的图集生成器,请使用以下命令行参数。

输入

位图图集类型

-type <type> – 参见 图集类型

<type> 可以是以下之一

图集图像格式

-format <format>

<format> 可以是以下之一

图集尺寸

-dimensions <width> <height> – 设置固定的图集尺寸

或者,如果设置了尺寸约束,则可以自动选择最小可能的尺寸

输出

可以指定以下任意非空子集

字形配置

距离场生成器设置

使用 -help 获取详尽的选项列表。

字符集规范语法

字符集文件是一个文本文件,使用 UTF-8 或 ASCII 编码。字符可以用以下方式表示

条目应以逗号或空格分隔。在引号之间,反斜杠用作转义字符(例如 '\'''\\'"!\"#")。字符出现的顺序不予考虑。

此外,include 指令可用于包含其他字符集文件,并以分层方式组合字符集。它必须写在单独的一行上

@include "base-charset.txt"

字形集规范

字形集规范的语法与字符集的语法基本相同,但仅允许使用数值(十进制和十六进制)。

库用法示例

以下是注释的代码片段,演示了如何将该项目用作库。

一次性生成整个图集

#include <msdf-atlas-gen/msdf-atlas-gen.h>

using namespace msdf_atlas;

bool generateAtlas(const char *fontFilename) {
    bool success = false;
    // Initialize instance of FreeType library
    if (msdfgen::FreetypeHandle *ft = msdfgen::initializeFreetype()) {
        // Load font file
        if (msdfgen::FontHandle *font = msdfgen::loadFont(ft, fontFilename)) {
            // Storage for glyph geometry and their coordinates in the atlas
            std::vector<GlyphGeometry> glyphs;
            // FontGeometry is a helper class that loads a set of glyphs from a single font.
            // It can also be used to get additional font metrics, kerning information, etc.
            FontGeometry fontGeometry(&glyphs);
            // Load a set of character glyphs:
            // The second argument can be ignored unless you mix different font sizes in one atlas.
            // In the last argument, you can specify a charset other than ASCII.
            // To load specific glyph indices, use loadGlyphs instead.
            fontGeometry.loadCharset(font, 1.0, Charset::ASCII);
            // Apply MSDF edge coloring. See edge-coloring.h for other coloring strategies.
            const double maxCornerAngle = 3.0;
            for (GlyphGeometry &glyph : glyphs)
                glyph.edgeColoring(&msdfgen::edgeColoringInkTrap, maxCornerAngle, 0);
            // TightAtlasPacker class computes the layout of the atlas.
            TightAtlasPacker packer;
            // Set atlas parameters:
            // setDimensions or setDimensionsConstraint to find the best value
            packer.setDimensionsConstraint(TightAtlasPacker::DimensionsConstraint::SQUARE);
            // setScale for a fixed size or setMinimumScale to use the largest that fits
            packer.setMinimumScale(24.0);
            // setPixelRange or setUnitRange
            packer.setPixelRange(2.0);
            packer.setMiterLimit(1.0);
            // Compute atlas layout - pack glyphs
            packer.pack(glyphs.data(), glyphs.size());
            // Get final atlas dimensions
            int width = 0, height = 0;
            packer.getDimensions(width, height);
            // The ImmediateAtlasGenerator class facilitates the generation of the atlas bitmap.
            ImmediateAtlasGenerator<
                float, // pixel type of buffer for individual glyphs depends on generator function
                3, // number of atlas color channels
                &msdfGenerator, // function to generate bitmaps for individual glyphs
                BitmapAtlasStorage<byte, 3> // class that stores the atlas bitmap
                // For example, a custom atlas storage class that stores it in VRAM can be used.
            > generator(width, height);
            // GeneratorAttributes can be modified to change the generator's default settings.
            GeneratorAttributes attributes;
            generator.setAttributes(attributes);
            generator.setThreadCount(4);
            // Generate atlas bitmap
            generator.generate(glyphs.data(), glyphs.size());
            // The atlas bitmap can now be retrieved via atlasStorage as a BitmapConstRef.
            // The glyphs array (or fontGeometry) contains positioning data for typesetting text.
            success = myProject::submitAtlasBitmapAndLayout(generator.atlasStorage(), glyphs);
            // Cleanup
            msdfgen::destroyFont(font);
        }
        msdfgen::deinitializeFreetype(ft);
    }
    return success;
}

动态图集

DynamicAtlas 类允许您在需要时“即时”将字形添加到图集中。在此示例中,ImmediateAtlasGenerator 用作底层图集生成器,但这并不是此目的的理想选择,因为它可能会每次都启动新线程。在实践中,您通常会定义自己的图集生成器类,该类可以正确处理您的特定性能和同步要求。

获取 GlyphGeometry 对象可以从前面的示例进行调整。

#include <msdf-atlas-gen/msdf-atlas-gen.h>

using namespace msdf_atlas;

using MyDynamicAtlas = DynamicAtlas<ImmediateAtlasGenerator<float, 3, &msdfGenerator, BitmapAtlasStorage<byte, 3>>>;

const double pixelRange = 2.0;
const double glyphScale = 32.0;
const double miterLimit = 1.0;
const double maxCornerAngle = 3.0;

MyDynamicAtlas atlas;

void addGlyphsToAtlas(GlyphGeometry *glyphs, int count) {
    for (int i = 0; i < count; ++i) {
        // Apply MSDF edge coloring. See edge-coloring.h for other coloring strategies.
        glyphs[i].edgeColoring(&msdfgen::edgeColoringInkTrap, maxCornerAngle, 0);
        // Finalize glyph box size based on the parameters
        glyphs[i].wrapBox(glyphScale, pixelRange/glyphScale, miterLimit);
    }
    // Add glyphs to atlas - invokes the underlying atlas generator
    // Adding multiple glyphs at once may improve packing efficiency.
    MyDynamicAtlas::ChangeFlags change = atlas.add(glyphs, count);
    if (change&MyDynamicAtlas::RESIZED) {
        // Atlas has been enlarged - can be handled here or directly in custom generator class
    }
    // Glyph positioning data is now stored in glyphs.
}

可以作为 dynamicAtlas.atlasGenerator().atlasStorage() 访问图集存储(及其位图)。