尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Unity TMP_SDF 分析(四)字重阈值、裁剪阈值与顶点输出

Unity TMP_SDF 分析(四)字重阈值、裁剪阈值与顶点输出 Unity TMP_SDF 分析四字重阈值、裁剪阈值与顶点输出适用版本Unity2021.3.23f1c1TextMeshPro3.0.9UGUI1.0.0分析范围项目中的标准Assets/TextMesh Pro/Shaders/TMP_SDF.shader及其关联源码Mobile、SSD、Surface 等变体不直接套用。系列导航第 4/9 篇前置顶点着色器中的屏幕空间缩放下一篇基础片元着色器与GetColor第三篇得到了屏幕空间 SDF 缩放量scale。本篇继续分析顶点着色器后半部分weight、bias、alphaClip、装饰纹理 UV以及写入pixel_t的各项数据。一、相关源码以下为VertShader()后半部分节选Glow 和 Underlay 细节留到后文float weight lerp(_WeightNormal, _WeightBold, bold) / 4.0; weight (weight _FaceDilate) * _ScaleRatioA * 0.5; float bias (.5 - weight) (.5 / scale); float alphaClip 1.0 - _OutlineWidth * _ScaleRatioA - _OutlineSoftness * _ScaleRatioA; #if GLOW_ON alphaClip min( alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB); #endif alphaClip alphaClip / 2.0 - (.5 / scale) - weight; float4 clampedRect clamp(_ClipRect, -2e10, 2e10); float2 maskUV (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); float2 textureUV UnpackUV(input.texcoord1.x); float2 faceUV TRANSFORM_TEX(textureUV, _FaceTex); float2 outlineUV TRANSFORM_TEX(textureUV, _OutlineTex); output.position vPosition; output.color input.color; output.atlas input.texcoord0; output.param float4(alphaClip, scale, bias, weight); output.mask half4( vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) pixelSize.xy)); output.viewDir mul( (float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz); output.textures float4(faceUV, outlineUV);二、选择 Normal 或 Bold 字重float weight lerp(_WeightNormal, _WeightBold, bold) / 4.0;其中bold来自float bold step(input.texcoord1.y, 0);因此bold 0 → weight _WeightNormal / 4 bold 1 → weight _WeightBold / 4_WeightNormal与_WeightBold是材质属性分别控制普通字符和由 Shader 模拟的 Bold 字符所使用的距离阈值偏移。为什么除以4CPU 端TMP_ShaderUtilities.UpdateShaderRatios()在计算可用距离范围时也使用相同的/ 4.0ffloatweightMathf.Max(mat.GetFloat(ID_WeightNormal),mat.GetFloat(ID_WeightBold))/4.0f;所以/4是 TMP 材质字重参数到内部距离场参数的统一尺度换算。三、叠加 Face Dilate 与_ScaleRatioAweight (weight _FaceDilate) * _ScaleRatioA * 0.5;_FaceDilate对普通和 Bold 字重统一施加额外的膨胀或收缩。_ScaleRatioA、_ScaleRatioB、_ScaleRatioC虽然是材质属性但通常由 TMP 的UpdateShaderRatios()计算用来把各类效果限制在字体 Atlas 的有效 SDF Padding 范围内。最后的* 0.5是 Shader 内部距离公式的一部分。与其猜测这是“再次优化精度”更可靠的理解是它把经 Ratio 修正后的字重与 Face Dilate 转换到后续以0.5为基准的 SDF 阈值域。四、_ScaleRatioA的真实作用CPU 端实现如下节选floatscalemat.GetFloat(ID_GradientScale);floatfaceDilatemat.GetFloat(ID_FaceDilate);floatoutlineThicknessmat.GetFloat(ID_OutlineWidth);floatoutlineSoftnessmat.GetFloat(ID_OutlineSoftness);floatweightMathf.Max(mat.GetFloat(ID_WeightNormal),mat.GetFloat(ID_WeightBold))/4.0f;floattMathf.Max(1,weightfaceDilateoutlineThicknessoutlineSoftness);boolisRatioEnabled!mat.shaderKeywords.Contains(RATIOS_OFF);floatratioAisRatioEnabled?(scale-1.0f)/(scale*t):1;mat.SetFloat(ID_ScaleRatio_A,ratioA);其中 C#scale是材质的_GradientScale通常与字体 Atlas Padding 相关。它与第三篇由屏幕尺寸计算的 HLSLscale含义不同名称所在位置含义C#scaleUpdateShaderRatios()材质_GradientScaleHLSLscaleVertShader()/PixShader()屏幕空间 SDF 缩放量ratioA的目的是给以下效果共同分配有限的 SDF 梯度范围Normal/Bold WeightFace DilateOutline WidthOutline Softness效果参数总和增大时t增大ratioA变小从而按比例压缩它们的实际作用范围避免越过 Atlas Padding 所能表达的距离范围。Ratio A 分配 Atlas 的有效距离范围屏幕空间缩放由顶点 Shader 的scale公式处理。若材质启用了RATIOS_OFF关键字则isRatioEnabled为false三个 Ratio 会回到1表示禁用这类安全范围补偿。五、biasAtlas 采样阈值与半过渡补偿float bias (.5 - weight) (.5 / scale);片元着色器随后会计算float sd (bias - c) * scale;其中c是 SDF Atlas 的 Alpha 值。TMP 的字形内部通常具有更高的c因此c bias → sd 0 → 更靠字形内部 c bias → sd 0 → 更靠字形外部1.0.5 - weight0.5是归一化 SDF 的基础边界。weight增大时bias降低较低的 Atlas 值也更容易进入可见过渡区因此字形向外扩张、视觉上变粗。2.0.5 / scale这一项把约半个标准过渡单位的补偿换算回 Atlas 值域使后续sd和GetColor()的抗锯齿过渡随屏幕缩放保持稳定。bias通常位于0.5附近同时包含字重和屏幕尺度补偿。六、alphaClip早期片元丢弃阈值基础计算为float alphaClip 1.0 - _OutlineWidth * _ScaleRatioA - _OutlineSoftness * _ScaleRatioA; alphaClip alphaClip / 2.0 - (.5 / scale) - weight;它通过output.param.x传入片元着色器并用于#ifndef UNDERLAY_ON clip(c - input.param.x); #endifclip(x)在x 0时丢弃当前片元。因此这里丢弃的是c alphaClipOutline 越宽、Softness 越大alphaClip越低Shader 就会保留 Atlas 中离字形更远的像素以便GetColor()计算描边和柔边。alphaClip是安全的早期片元丢弃阈值它最终由片元着色器的clip()执行。它不会修改文本四边形尺寸。最终颜色边界仍由sd、outline、softness和GetColor()决定。开启 Glow 时还会进一步降低阈值保留辉光需要的 Atlas 区域。UNDERLAY_ON会跳过这次 clip因为偏移后的外部 Underlay 可能依赖原字形阈值之外的片元。七、UI 裁剪数据的准备float4 clampedRect clamp(_ClipRect, -2e10, 2e10); float2 maskUV (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); output.mask half4( vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) pixelSize.xy));当前版本中局部变量maskUV后续没有被读取编译器通常会将其消除。真正传给片元着色器的是output.mask.xy相对于裁剪矩形中心的对称坐标。.zw结合 RectMask2D Softness 与屏幕像素尺度得到的过渡斜率。完整推导将在第九篇说明。八、Face/Outline 装饰纹理 UVfloat2 textureUV UnpackUV(input.texcoord1.x); float2 faceUV TRANSFORM_TEX(textureUV, _FaceTex); float2 outlineUV TRANSFORM_TEX(textureUV, _OutlineTex);这条数据链已经在第二篇分析input.texcoord1.x保存PackUV(mappingU, mappingV)。UnpackUV()恢复有限精度的二维映射坐标。TRANSFORM_TEX应用_FaceTex_ST或_OutlineTex_ST的 Tiling/Offset。它们用于_FaceTex和_OutlineTex_MainTexSDF Atlas 使用input.texcoord0。Pack 使用511Unpack 使用1/512解包结果包含固定量化误差。九、pixel_t输出字段output.position vPosition; output.color input.color; output.atlas input.texcoord0; output.param float4(alphaClip, scale, bias, weight); output.mask ...; output.viewDir ...; output.textures float4(faceUV, outlineUV);输出字段内容片元阶段用途position裁剪空间顶点位置光栅化位置colorTMP 顶点颜色Face RGB 与最终 Alpha 调制atlasTEXCOORD0字体图集 UV采样_MainTexparam.xalphaClipAtlas 采样的早期clip()阈值param.yscale把 Atlas 距离换算到屏幕尺度param.zbias字重和半过渡补偿后的边界阈值param.wweightBevel 法线轮廓等后续计算mask矩形中心坐标与软裁剪斜率UNITY_UI_CLIP_RECTviewDir经_EnvMatrix旋转的顶点到摄像机向量Bevel 环境反射textures.xyFace Texture UV采样_FaceTextextures.zwOutline Texture UV采样_OutlineTexviewDir的计算为mul( (float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz)它先得到世界空间中“顶点指向摄像机”的向量再通过环境矩阵旋转用于后续 Cubemap 反射。十、完整关系bold 标记 └─ 选择 _WeightNormal / _WeightBold └─ /4 _FaceDilate └─ × _ScaleRatioA × 0.5 └─ weight ├─ bias 0.5 - weight 0.5/scale └─ alphaClip ... - weight Atlas 与装饰纹理 input.texcoord0 → output.atlas → _MainTex input.texcoord1.x → UnpackUV → _FaceTex / _OutlineTex input.texcoord1.y → bold SDF scale十一、源码索引Assets/TextMesh Pro/Shaders/TMP_SDF.shader顶点输出、bias与alphaClip。Assets/TextMesh Pro/Shaders/TMPro.cgincUnpackUV()与片元颜色函数。Scripts/Runtime/TMP_ShaderUtilities.cs_ScaleRatioA/B/C的计算。Scripts/Editor/TMP_SDFShaderGUI.cs材质面板中的 Weight、Face Dilate 等属性。
返回列表