#distance-field #distance #field #signed #sdf

easy-signed-distance-field

一个简单、纯Rust的符号距离场渲染器

2个版本

0.1.1 2022年8月22日
0.1.0 2022年8月22日

#78 in 渲染

MIT 许可协议

120KB
1K SLoC

Easy signed distance field

Easy signed distance field 是一个简单、纯Rust的符号距离场渲染器。它旨在作为一个简单、更灵活、更完整功能的替代品,替代crates.io上其他sdf包。

Easy signed distance field 目前支持原始线条输入和ttf/otf字体输入。它还支持CPU渲染以供调试。

符号距离场是一种渲染技术,可以生成非常小的符号,可以以牺牲锐角周围质量为代价在更高的分辨率下渲染。该技术还附带“免费”抗锯齿和一些文字效果。

通常,这项技术在游戏中用来创建小字符符号的图集,然后可以在任何分辨率下渲染。渲染是在GPU上的片段着色器上完成的。

要查看实时演示,请访问 https://gabdube.github.io/easy-signed-distance-field/

有关文档,请参阅 https://docs.rs/easy-signed-distance-field/0.1.0/easy_signed_distance_field/

sdf render sdf

功能

默认情况下,此库无依赖项,仅支持从线条集合中进行渲染。可以启用额外功能

  • font:导入字体家族并将字符符号渲染为sdf
  • export:将sdf导出为图像
  • render:(与export一起使用) 将sdf渲染到文件
[features]
default = []
render = []
font = ["ttf-parser"]
export = ["image"]

用法

从线条集合渲染简单的三角形

use easy_signed_distance_field as sdf;

let lines = [
    Line::Line { start: vec2(0.5, 0.0), end: vec2(1.0, 1.0) },
    Line::Line { start: vec2(1.0, 1.0), end: vec2(0.0, 1.0) },
    Line::Line { start: vec2(0.0, 1.0), end: vec2(0.5, 0.0) },
];

let width: u32 = 32;
let height: u32 = 32;
let padding = 2;
let spread = 5.0;
let sdf = sdf::sdf_generate(
    width,
    height,
    padding,
    spread,
    &lines,
);

#[cfg(feature="export")]
sdf::sdf_to_file("test_outputs/triangle.png", &sdf).unwrap();


let render_scale = 512.0 / (size as f32);

#[cfg(feature="render")]
#[cfg(feature="export")]
sdf::sdf_render_to_file("test_outputs/triangle_render.png", render_scale, 0.5, 0.02, &sdf).unwrap();

从字体渲染字符

use std::fs;
use easy_signed_distance_field as sdf;

let font_data = fs::read("./test_fixtures/Questrial-Regular.ttf").expect("Failed to read font file");
let font = sdf::Font::from_bytes(font_data.as_slice(), Default::default()).expect("Failed to parse font file");

let px = 64.0;
let padding = 2;
let spread = 6.0;
let (a_metrics, a_glyph_sdf) = font.sdf_generate(px, padding, spread, 'a').unwrap();

#[cfg(feature="export")]
sdf::sdf_to_file("test_outputs/font_a.png", &a_glyph_sdf).unwrap();

#[cfg(feature="render")]
#[cfg(feature="export")]
sdf::sdf_render_to_file("test_outputs/font_a_render.png", render_scale, 0.5, 0.02, &a_glyph_sdf).unwrap();

将sdf上传到webgl纹理


性能

根据基准测试,生成64px的单个字符的sdf大约需要2ms。在相同分辨率下生成整个字母表(大小写),大约需要66ms。这个时间将根据您的字体/形状的复杂程度而变化。

这意味着如果您打算在实时环境中使用此库(例如,在用户键入时生成sdf),最好在主线程之外运行代码或预先在启动时生成字符。

尽管如此,该算法是单线程的并且非常简单,可能有很多改进的方法。

路线图

该项目是为了用于我的个人项目之一而开发的,因此除非该项目需要,否则不会进行进一步的开发/维护。话虽如此,我不介意合并贡献者的功能,只要在问题部分与我讨论即可,如果这是个大项目。

在某个时候实现多签名距离场(msdf)也是我想添加的功能之一。

添加多线程支持也是我想探索的。尽管如此,这并不是优先事项,因为我打算从wasm中使用它。

直到我(或其他人)在一个严肃的项目中使用它之前,该项目不会达到1.0。在此之前,API可能会发生变化。

许可证

本代码遵循MIT许可证。

致谢

虽然我对数学不是很差,但我不算是一个数学家;这个项目中使用的算法大多数都是由比我更有能力的人创建的。

依赖项

~0–2.7MB
~13K SLoC