Unity TMP_SDF 分析(七)UNDERLAY_ON 与 UNDERLAY_INNER
Unity TMP_SDF 分析七UNDERLAY_ON与UNDERLAY_INNER适用版本Unity2021.3.23f1c1TextMeshPro3.0.9UGUI1.0.0分析范围项目中的标准Assets/TextMesh Pro/Shaders/TMP_SDF.shader及其关联源码Mobile、SSD、Surface 等变体不直接套用。系列导航第 7/9 篇前置GLOW_ON辉光路径下一篇BEVEL_ON法线、光照与反射Underlay 使用一套偏移、膨胀和柔化参数再次采样_MainTexSDF Atlas再把结果合成到 Face/Outline 下方。一、关键字是互斥变体Shader 声明为#pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER材质面板对应三种互斥状态None → 两个关键字都不启用 Normal → UNDERLAY_ON Inner → UNDERLAY_INNERNormal Underlay 的效果示例Inner 模式选择UNDERLAY_INNER变体Normal 与 Inner 是互斥选项。Inner Underlay 会乘(1 - faceColor.a)所以 Face/Outline 完全不透明时效果会被遮住。调低 Face Alpha 后更容易观察效果示例二、完整相关代码顶点着色器准备一套额外参数节选#if (UNDERLAY_ON || UNDERLAY_INNER) float4 underlayColor _UnderlayColor; underlayColor.rgb * underlayColor.a; float bScale scale; bScale / 1 ((_UnderlaySoftness * _ScaleRatioC) * bScale); float bBias (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale); float x -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; float y -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; float2 bOffset float2(x, y); output.texcoord2 float4( input.texcoord0 bOffset, bScale, bBias); output.underlayColor underlayColor; #endif片元着色器根据互斥关键字选择一种合成方式#ifndef UNDERLAY_ON clip(c - input.param.x); #endif #if UNDERLAY_ON float d tex2D( _MainTex, input.texcoord2.xy).a * input.texcoord2.z; faceColor input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a); #endif #if UNDERLAY_INNER float d tex2D( _MainTex, input.texcoord2.xy).a * input.texcoord2.z; faceColor input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a); #endif三、CPU 端_ScaleRatioCTMP_ShaderUtilities.UpdateShaderRatios()的计算如下节选floatscalemat.GetFloat(ID_GradientScale);floatfaceDilatemat.GetFloat(ID_FaceDilate);floatweightMathf.Max(mat.GetFloat(ID_WeightNormal),mat.GetFloat(ID_WeightBold))/4.0f;floatoffsetXmat.GetFloat(ID_UnderlayOffsetX);floatoffsetYmat.GetFloat(ID_UnderlayOffsetY);floatdilatemat.GetFloat(ID_UnderlayDilate);floatsoftnessmat.GetFloat(ID_UnderlaySoftness);floatrange(weightfaceDilate)*(scale-1.0f);floattMathf.Max(1,Mathf.Max(Mathf.Abs(offsetX),Mathf.Abs(offsetY))dilatesoftness);boolisRatioEnabled!mat.shaderKeywords.Contains(RATIOS_OFF);floatratioCisRatioEnabled?Mathf.Max(0,scale-1.0f-range)/(scale*t):1;mat.SetFloat(ID_ScaleRatio_C,ratioC);Ratio C 先扣除 Weight 与 Face Dilate 占用的 Atlas 梯度范围再根据以下 Underlay 参数压缩剩余预算X/Y Offset 中绝对值较大的一个DilateSoftnessRatio C 限制 SDF Padding 使用范围顶点 Shader 的scale负责屏幕尺度换算。四、Underlay 颜色使用预乘 Alphafloat4 underlayColor _UnderlayColor; underlayColor.rgb * underlayColor.a;Shader Pass 使用Blend One OneMinusSrcAlpha所以 Underlay RGB 先乘自身 Alpha后续可以通过加法形式合成underlay base × (1 - underlayAlpha)当前 Shader 的实际表达式还额外乘了(1 - faceColor.a)用来保证 Underlay 位于已生成的 Face/Outline 之下。五、bScaleUnderlay Softnessfloat bScale scale; bScale / 1 ((_UnderlaySoftness * _ScaleRatioC) * bScale);可写为bScale scale / (1 softness × ratioC × scale)Softness 为0时bScale scale。Softness 增大时bScale减小。片元阶段使用atlasAlpha × bScale - bBias生成覆盖率较小的bScale令 Atlas 距离变化斜率更缓Underlay 边缘更柔。这套 Softness 只作用于第二次偏移采样不会直接修改主 Face/Outline 的scale。六、bBiasWeight、Dilate 与柔化后的阈值float bBias (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale);片元阶段组合为float d shiftedAtlasAlpha * bScale; float underlayCoverage saturate(d - bBias);因此bBias是已经转换到d所在尺度的覆盖阈值weight让 Underlay 与主字形的字重基准保持联系。正_UnderlayDilate会降低bBias使d - bBias增大覆盖区域扩张。Softness 已经通过bScale同时影响斜率和阈值。主路径计算sd (bias - c) * scaleUnderlay 路径计算c × bScale - bBias两者使用各自的符号和代数形式。七、Offset 如何变成 Atlas UV 偏移float x -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; float y -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight;_GradientScale / _TextureWidth与_GradientScale / _TextureHeight把材质 Offset 换算为 Atlas UV 尺度Ratio C 负责限制可用范围。代码中的负号表示采样坐标向设置方向的反方向移动视觉上得到的 Underlay 图形会相对原字形向 Offset 指定方向偏移。这与“移动图形”和“反向移动采样点”之间的关系一致。最终传递的数据为input.texcoord2.xy → 偏移后的 Atlas UV input.texcoord2.z → bScale input.texcoord2.w → bBias八、为什么 Normal Underlay 跳过主clip()#ifndef UNDERLAY_ON clip(c - input.param.x); #endif只有UNDERLAY_ON会跳过主 Atlas 的早期 clipNormal Underlay 需要在原字形外侧显示偏移后的形状。当前片元的原始 Atlas 值c可能低于主 Face/Outline 的阈值但偏移 UV 采样却可能命中 Underlay 字形。若先按原始c丢弃这些外部阴影片元就永远无法执行第二次采样。UNDERLAY_INNER只需要原字形内部附近的片元因此它与无 Underlay 情况一样保留这次主clip()。九、Normal Underlay 合成float d tex2D( _MainTex, input.texcoord2.xy).a * input.texcoord2.z; faceColor input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a);拆解为shiftedCoverage saturate(shiftedAtlasAlpha × bScale - bBias) underlayContribution premultipliedUnderlayColor × shiftedCoverage × (1 - baseFaceOutlineAlpha)(1 - faceColor.a)使 Underlay 只填充 Face/Outline 尚未覆盖的部分形成位于文字下方的阴影或外扩底层。十、Inner Underlay 合成faceColor input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a);它由三个遮罩共同决定。1. 偏移字形的反向覆盖1 - saturate(d - bBias)Normal 模式使用偏移字形“被覆盖”的区域Inner 模式反过来选择偏移字形“未覆盖或覆盖较弱”的区域。2. 原始字形内部遮罩saturate(1 - sd)第五篇已经确认sd 0更靠原字形内部内部sd 0时该遮罩通常为1。向外移动、sd增大后逐渐降为0。这一步把反向偏移覆盖限制在原字形内部附近从而形成内部阴影/内凹效果。3. 基础颜色剩余透明度1 - faceColor.a即使前两个遮罩有贡献只要 Face/Outline 已经完全不透明最终 Underlay 仍会被乘为零。这正是降低 Face Alpha 后 Inner Underlay 才明显的原因。十一、两种模式对照项目UNDERLAY_ONUNDERLAY_INNER材质面板NormalInner是否与另一关键字同时启用否否是否跳过主clip(c-alphaClip)是否偏移覆盖saturate(d-bBias)1-saturate(d-bBias)原字形内部遮罩无saturate(1-sd)与 Face 的层级都乘(1-faceColor.a)位于其下常见效果投影、外部底层内阴影、内凹遮罩十二、源码索引Assets/TextMesh Pro/Shaders/TMP_SDF.shaderUnderlay 顶点参数与两种片元合成。Scripts/Runtime/TMP_ShaderUtilities.cs_ScaleRatioC。Scripts/Editor/TMP_SDFShaderGUI.csNone / Normal / Inner 互斥关键字设置。

相关新闻

NXLoader快速上手:把安卓手机变成Switch启动器的终极免费方案

NXLoader快速上手:把安卓手机变成Switch启动器的终极免费方案

NXLoader快速上手:把安卓手机变成Switch启动器的终极免费方案 【免费下载链接】NXLoader My first Android app: Launch Fuse Gele payloads from stock Android (CVE-2018-6242) 项目地址: https://gitcode.com/gh_mirrors/nx/NXLoader NXLoader是一款让安卓…

2026/8/15 19:55:14 阅读更多 →
《算法导论》插入排序算法分析(14-15页)完整解读|算法理论与工程实践深度剖析

《算法导论》插入排序算法分析(14-15页)完整解读|算法理论与工程实践深度剖析

《算法导论》插入排序算法分析(14-15 页)完整解读|算法理论与工程实践深度剖析 摘要 本文基于《算法导论》原书第 2 章 14-15 页的经典理论框架,从算法研究者的视角切入,先拆解 RAM 随机访问机模型下的插入排序复杂度定量推导逻辑;再提供与伪代码严格对齐的 Python、C+…

2026/8/15 19:55:14 阅读更多 →
风控岗应用:OpenClaw 采集公开司法与经营异常数据,自动生成企业风险评估报告

风控岗应用:OpenClaw 采集公开司法与经营异常数据,自动生成企业风险评估报告

一、引言:企业风控为什么需要自动化信息采集与报告生成在企业经营过程中,风险控制岗位承担着一项非常基础但又极其关键的工作,就是在合作、投标、授信、采购、投资、招聘高管、渠道准入等场景下,快速判断一家企业是否值得信任、是…

2026/8/15 19:55:14 阅读更多 →

最新新闻

GitHub Pull Request全流程指南:从Fork到合并的协作开发实践

GitHub Pull Request全流程指南:从Fork到合并的协作开发实践

1. 从“看客”到“贡献者”:为什么你需要了解Pull Request如果你在GitHub上逛过一些开源项目,看到别人提交的代码、修复的Bug,心里可能也痒痒过:“我能不能也参与进去?” 但一想到要面对复杂的Git命令、分支管理&#…

2026/8/16 23:47:03 阅读更多 →
专为加密流量渗透测试打造的Burp插件,一键自动解密报文,让复杂加密接口测试,和明文测试一样简单高效

专为加密流量渗透测试打造的Burp插件,一键自动解密报文,让复杂加密接口测试,和明文测试一样简单高效

0x01 工具介绍 Galaxy、CloudX两款主打加密流量高效测试的Burp插件,完美解决渗透测试中接口加密、自定义算法、动态密钥等测试难题。支持自定义Hook实现流量全自动MITM解密,适配Proxy、Repeater、Intruder等全模块。可无缝联动Sqlmap、Xray等主流安全工…

2026/8/16 23:47:03 阅读更多 →
彻底移除Windows预装应用:PowerShell实战指南

彻底移除Windows预装应用:PowerShell实战指南

1. 项目概述:为什么我们要对系统“预装”组件动手?如果你和我一样,是个对电脑桌面有“洁癖”的资深用户,或者你管理的是一批需要统一、纯净系统镜像的办公电脑,那么Windows 10/11系统里那些删不掉、关不掉的预装应用和…

2026/8/16 23:47:03 阅读更多 →
GNOME Shell扩展实战指南:从效率提升到视觉美化的桌面定制

GNOME Shell扩展实战指南:从效率提升到视觉美化的桌面定制

1. 项目概述:为什么我们需要定制GNOME桌面? 如果你和我一样,每天有超过8小时的时间是在Linux桌面前度过的,那么一个高效、顺眼、符合个人工作流的桌面环境,其重要性不亚于一把趁手的键盘。GNOME作为许多主流Linux发行版…

2026/8/16 23:47:03 阅读更多 →
GNOME Shell扩展终极指南:从原理到实战打造高效Linux桌面

GNOME Shell扩展终极指南:从原理到实战打造高效Linux桌面

1. 项目概述:为什么你需要定制GNOME桌面如果你是一名Linux桌面用户,尤其是选择了Ubuntu、Fedora、RHEL等主流发行版,那么你大概率正在使用GNOME桌面环境。它以其简洁、现代的设计和强大的底层框架赢得了众多用户和开发者的青睐。然而&#xf…

2026/8/16 23:47:03 阅读更多 →
Ubuntu 22.04 Docker安装与镜像加速配置实战指南

Ubuntu 22.04 Docker安装与镜像加速配置实战指南

1. 项目概述:从零到一,搞定Docker环境与镜像加速 如果你是一名开发者,或者正在学习运维、数据科学,甚至是搞点个人项目,那么“Docker”这个词你肯定不陌生。它就像一个标准化的集装箱,把你的应用和它运行所…

2026/8/16 23:46:03 阅读更多 →

日新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/16 0:00:54 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/16 0:00:55 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/16 0:03:55 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/16 0:00:54 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/16 0:00:55 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/16 0:03:55 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/16 6:00:23 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/16 6:00:24 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/16 6:00:27 阅读更多 →