ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

makepad 中 sdfer 库的 SDF 生成算法:从 Valve 暴力搜索到 ESDT 亚像素距离变换

makepad 中 sdfer 库的 SDF 生成算法:从 Valve 暴力搜索到 ESDT 亚像素距离变换 前端UI组件3D渲染跨平台游戏开发【免费下载链接】makepadMakepad is a creative software development platform for Rust that compiles to wasm/webGL, osx/metal, windows/dx11 linux/opengl项目地址https://gitcode.com/gh_mirrors/ma/makepad点击查看免费下载导读本文讲解 makepad 仓库内libs/sdfer库的核心内容一种基于位图暴力搜索的 SDF有符号距离场生成算法以及一种面向运行时按需转换场景的 ESDT欧几里得亚像素距离变换算法。你将掌握两种算法的原理、API 与参数语义并通过draw/src/text/sdfer.rs看到它们如何在 makepad 的文本渲染管线中落地为理解字体放大抗锯齿、平滑缩放与矢量纹理渲染提供可直接查阅的实现级依据。一、库概览两个 SDF 生成算法libs/sdfer是一个独立的 Rust crate仓库内版本为 0.2.1见 Cargo.toml其入口在 lib.rs通过include_str!将 README 直接作为 crate 级文档并对外暴露两个算法模块sdfer::bruteforce_bitmap基于位图、搜索“最近反色像素”的暴力算法sdfer::esdtRust 移植的 ESDTEuclidean Subpixel Distance Transform欧几里得亚像素距离变换算法。同时img.rs 提供算法共用的基础数据结构Unorm80~255 均匀映射的[0,1]像素值、Image2dT二维图像容器、Bitmap按 8x8 位块压缩的位图、NDCursor系列游标。makepad 的文本渲染管线正是通过 draw/src/text/sdfer.rs 调用esdt::glyph_to_sdf完成覆盖率图到 SDF 的转换这一点在第四节详述。二、算法一bruteforce_bitmap —— 被 Valve 推广的暴力搜索该算法在 bruteforce_bitmap.rs 中实现。README 明确指出它是“最常被实现、但也是最朴素低效”的算法其知名度主要来自 Valve 在 2007 年 SIGGRAPH 上的论文Improved Alpha-Tested Magnification for Vector Textures and Special Effects——该论文提出了在 3D 环境中用 2D 纹理 SDF 渲染文字或任意矢量形状的经典方案。算法原理对输出 SDF 的每个像素取输入位图中对应位置为中心在一个边长 2×spread 的方形邻域内逐一检查“与中心像素颜色相反”的像素找到其中与中心欧氏距离最近者把该距离归一化后写入 SDF若中心像素在形状内部inside true距离取负号距离除以spread并 clamp 到[0, 1]最终通过Unorm8::encode((signed_dist 1.0) / 2.0)把[-1, 1]映射回[0, 1]的 8 位无符号归一化值对应源码bruteforce_bitmap.rs中sdf函数的signed_dist与编码两段。函数签名与约束pub fn sdf(bitmap: Bitmap, sdf_size: usize, spread: usize) - Image2dUnorm8源码中的关键实现事实bruteforce_bitmap.rs输入要求bitmap的宽高以及sdf_size都必须是 2 的幂assert!强制否则直接 panic降采样scale w.max(h) / sdf_size输出尺寸为w / scale × h / scalespread会先乘以scale再参与搜索因此spread是以最终 SDF 像素为单位的“羽化半径”复杂度代价每个输出像素都要扫描一个最大(2*spread1)^2的窗口而像素级精度又不足以表达亚像素细节导致必须依赖远超输出尺寸的大图。README 给出了 Valve 论文中的典型例子从 4096×4096 输入降到 64×64 输出。这正是它“贵得让人无法接受”prohibitively expensive的原因也是 README 建议将 ESDT 作为更优选的动机来源。源码中还留有FIXME(eddyb)注释提示可以改用螺旋搜索spiral search或更聪明的位块访问方式来优化说明当前实现是最直接的朴素写法。三、算法二esdt —— 欧几里得亚像素距离变换这是本库的主推算法。README 说明其来源它是 use-gpu/glyph npm 包中原始 JS 实现的 Rust 移植算法思想由 acko.net 的 Subpixel Distance Transform 博客文章 阐述——即对经典 EDT欧几里得距离变换进行改进以更好地利用字形灰度抗锯齿栅格化中编码的逐像素覆盖率信息。为什么它比暴力搜索实用输入输出 1:1不需要放大输入图像SDF 像素与输入像素一一对应近似线性复杂度README 说明它“大致随输出像素数量线性扩展”因此对于“运行时按需的字形→SDF 转换”远比多数算法可行典型应用场景README 原话避免滚动/平移时文字像素对齐pixel-snapping的瑕疵在需要更大栅格化之前提供一定程度的平滑双指缩放按需生成 SDF 以节约显存与时间。README 中留下一行FIXME(eddyb) write an explanation of pros-vs-cons, especially for ESDT即原作者也计划补写更详细的优劣势对比读者可将其作为阅读源码时的背景提示。核心 API 与 Params 参数表入口函数为esdt::glyph_to_sdfesdt.rspub fn glyph_to_sdf( glyph: mut Image2dUnorm8, impl AsMut[Unorm8] AsRef[Unorm8], params: Params, reuse_bufs: OptionReusableBuffers, ) - (Image2dUnorm8, ReusableBuffers)Params各字段及其默认值源码impl Default for Params中给出字段默认值类型语义pad4usize输出 SDF 四周的留白像素数输出尺寸 输入尺寸 2×padradius3.0f32SDF 的羽化半径归一化距离编码时的缩放分母cutoff0.25f32距离编码偏移量配合 radius 决定 SDF 中实体/边缘的分布solidifytruebool是否先执行“固化半透明区域”预处理solidify_alpha修复抗锯齿模糊边缘preprocessfalsebool是否执行亚像素偏移松弛relax步骤true时质量略升、速度略降postprocess—未实现bool源码中标注FIXME(eddyb) implement当前版本不可用输出编码公式glyph_to_esdt内部esdt.rs先分别对“外侧”outer和“内侧”inner距离场求欧氏距离再按符号合成有符号距离let outer ((xo[i].powi(2) yo[i].powi(2)).sqrt() - 0.5).max(0.0); let inner ((xi[i].powi(2) yi[i].powi(2)).sqrt() - 0.5).max(0.0); let d if outer inner { outer } else { -inner }; Unorm8::encode(1.0 - (d / radius cutoff))当preprocess false时paint_into_distance_field还会把原灰度覆盖率的非实体像素非纯黑/纯白重新“画”回 SDF 中从而保留灰度抗锯齿信息见 esdt.rs。内部流程solidify → 亚像素偏移 → 1D/2D ESDT从源码结构看glyph_to_sdf依次经历以下阶段均位于 esdt.rssolidify_alpha默认开启将 alpha 与四邻域接近且既不黑也不白的像素标记出来向 4 邻域扩散并重新归一化 alpha用于消除半透明噪声区域构建内外掩码alpha≥254 的像素视为实体innertrue, outerfalse并“修正糟糕光栅化器的舍入”将 254~255 统一为 255生成亚像素偏移对非实体像素用 3x3 邻域的双线性加权ll/rr/tt/bb估算边界法线方向把“像素中心到最近边界”的向量存入xo/yo对纯白像素则向其纯黑相邻像素写入 ±0.4999 的偏移可选 relaxpreprocess以xo为输入、xi为输出对相邻偏移做带法线方向保持的混合源码注释指出“略微提升质量但拖慢速度”ESDT 扫描esdt_outer_and_inner对内外两张位图分别执行esdt——先按列做 1D 变换再按行做 1D 变换esdt.rs1D 变换esdt1d基于 Felzenszwalb Huttenlocher 的经典距离变换论文源码注释给出了参考出处利用 Voronoi 临界最小值CriticalMinimum含索引、Voronoi 阈值、平方距离、平行/垂直亚像素偏移线性扫描完成。ReusableBuffers运行时按需转换的关键设计esdt::ReusableBuffers是一个不透明结构esdt.rs缓存 2D 缓冲outer/inner位图与xo/yo/xi/yi四个Vecf32和 1D 缓冲critical_minima列表避免每次 SDF 计算都重新分配。配合glyph_to_sdf返回更新后的ReusableBuffers调用方可以“取出→用完→归还”这正是 makepad 文本管线连续转换大量字形时控制内存抖动的手段。测试用例精确到浮点tests/edge-cases.rs 中的simple_3x3测试给出了一个可直接验证的端到端样例输入 3×3 覆盖图中心 0.90、四邻 0.85、四角 0.00pad1其余参数默认输出 SDF 的 3×3 中心区域应精确等于预期浮点矩阵如中心1.0、四邻0.8980392。该测试同时示范了Image2d::from_storage与Unorm8::encode/decode的用法可作为读者接入库时的最小可运行范例。四、在 makepad 文本渲染中的落地libs/sdfer并非孤立工具makepad 的绘制库在 draw/src/text/sdfer.rs 中将其接入字形渲染管线结构体Sdfer持有Settings { padding, radius, cutoff }与一个Optionsdfer::esdt::ReusableBufferscoverage_to_sdf把渲染器产生的覆盖率子图SubimageR逐像素转为Image2dUnorm8调用esdt::glyph_to_sdf并严格校验输出尺寸等于输入尺寸加两倍 paddingassert_eq!转换完成后通过take()/Some(...)模式归还ReusableBuffers供下一字形复用输出再回写为SubimageMutR供后续着色器采样。也就是说makepad 实际采用的正是 README 所强调的“按需运行时字形→SDF”路线pad/radius/cutoff三个参数在渲染层仍以Settings形式暴露给上层配置。另外仓库还包含一个独立的 MSDF 多通道 SDF 实现 draw/src/text/msdfer.rs直接使用sdfer::Unorm8编码距离它走的是“字形轮廓 → 多通道颜色着色 伪距离”路线与sdfer库的单通道栅格化路线互为补充可供对高质量拐角渲染感兴趣的读者对照阅读。五、许可与贡献约定README 明确说明sdfer仅采用 MIT 许可LICENSE-MIT亦可参见 http://opensource.org/licenses/MIT而不是常见的“MIT Apache-2.0”双许可主要原因正是 ESDT 算法实现src/esdt.rs移植自 MIT 许可的use-gpu/glyphnpm 包 JS 代码。贡献条款约定除非明确另行声明任何有意为本 crate 提交的贡献都将按 MIT 许可授权无附加条款或条件。若你的项目同样依赖该 crate需要注意这一单许可约束。六、选型小结结合 README 与源码两条路径的适用边界可以概括为bruteforce_bitmap实现直观、适合教学与验证性实验但像素级精度决定了它需要超大输入图成本随 SDF 尺寸与 spread 迅速膨胀不适合运行时频繁转换esdt输入输出 1:1、复杂度近似线性配合ReusableBuffers缓冲复用适合字形等“灰度覆盖率图 → SDF”的运行时按需转换这也是 makepad 文本渲染实际采用的方案见 draw/src/text/sdfer.rs。如果你需要在项目内快速复刻一套 SDF 管线可以直接阅读 libs/sdfer/tests/edge-cases.rs 的调用方式起步再按 libs/sdfer/src/esdt.rs 中Params的默认值调节pad/radius/cutoff以满足不同渲染距离与羽化需求。赞分享前端UI组件3D渲染跨平台游戏开发【免费下载链接】makepadMakepad is a creative software development platform for Rust that compiles to wasm/webGL, osx/metal, windows/dx11 linux/opengl项目地址https://gitcode.com/gh_mirrors/ma/makepad点击查看免费下载相关推荐Hello 算法重识搜索算法——从暴力搜索到自适应搜索的系统化选型指南Hello 算法重识搜索算法——从暴力搜索到自适应搜索的系统化选型指南 在《Hello 算法》hello algo中搜索一章开篇即抛出核心问题如何教程文档示例工程教育3步掌握回溯算法从暴力搜索到剪枝优化3步掌握回溯算法从暴力搜索到剪枝优化 你是否曾面对复杂问题时感到无从下手比如如何在国际象棋棋盘上放置8个皇后而不互相攻击或者如何找出所有可能的密码组合这教程文档示例工程教育深入 ccv 数值算法库ccv_numeric.c 的线搜索最优化、FFT 卷积与线性时间距离变换深入 ccv 数值算法库ccv_numeric.c 的线搜索最优化、FFT 卷积与线性时间距离变换 本篇技术指南围绕 ccv 的数值算法模块 lib/ccv_计算机视觉深度学习上一篇G-Helper终极指南如何为你的华硕笔记本解锁完整性能控制下一篇终极免费Switch模拟器Ryujinx在PC上畅玩4100款任天堂游戏的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表