UniTextMeshGenerator
Converts positioned glyphs into Unity mesh data for text rendering.
Remarks
ArrayPool<T> for zero allocations Provides callbacks for text modifiers to inject custom processing Typical usage: generator.SetRectOffset(rect); generator.GenerateMeshDataOnly(positionedGlyphs); var renderData = generator.CollectRenderData(); // Use renderData to render each segment generator.ReturnInstanceBuffers();public Color32 DefaultColor{ get; set }Default vertex colour of glyph faces, decoration lines and sprites that inherit the text colour: the red, green and blue of the component colour, always opaque, since the component's alpha applies when the text is drawn.
Whether the colour glyph currently in onGlyph carries a silhouette field for effects to sample; always false for an outline glyph.
Whether the glyph currently in onGlyph draws from a texture outside the atlases, so its face quad carries no atlas pixels a text material could render.
Runs after onMainPassComplete, with every face quad emitted, before triangle materialization.
public OrderedEvent<SubMeshCollectionContext> onCollectSubMeshes{ get }Collects custom render-data segments before the base segments are appended.
public UniTextRenderMode RenderMode{ get; set }Gets or sets the atlas mode (SDF or MSDF) for glyph lookup and material selection.
public Vector3[] Vertices{ get }Gets the vertex position buffer (X, Y, Z coordinates).
public Vector4[] Uvs0{ get }Gets the primary UV buffer (texture coordinates and scale in W component).
public Color32[] Colors{ get }Gets the vertex color buffer.
public Vector4[] Uvs1{ get }Gets the UV1 buffer: x = aspect (glyphW/glyphH) plus, above RowLaneStep, a deform row + 1 (absent = aspect alone), y = faceDilate, z = per-glyph cluster index (monotonic per-line, transform-invariant), w = intra-glyph X fraction (0 on the left edge, 1 on the right — interpolated by GPU).
public Vector4[] Uvs2{ get }Gets the UV2 buffer — the COVERAGE contract (TEXCOORD2).
public Vector4[] Uvs3{ get }Gets the UV3 buffer — the PAINT contract (TEXCOORD3).
[ctor]public UniTextMeshGenerator(UniTextFontProvider fontProvider, UniTextBuffers uniTextBuffers)Initializes a new instance of the UniTextMeshGenerator class.
public static void ScaleGlyphQuad(Vector3[] verts, int baseIdx, float pivotX, float baselineY, float scale, float yOffset = 0f, float xOffset = 0f)Scales four vertices starting at baseIdx around the pen position and baseline, then applies the offsets.
public void ScaleFace(int baseIdx, float pivotX, float baselineY, float scale, float yOffset = 0f, float xOffset = 0f)Scales the current face quad and records the factor into currentGlyphScale. Every per-glyph size change (size tag, small-caps, sub/superscript, ruby, font metric overrides) must pass through here rather than ScaleGlyphQuad directly — a scale the generator does not see leaves paint-layer offset and quad growth stuck at the base size.
Scales a face quad horizontally around the pen position — the fit / justification glyph-compression channel. Deliberately not folded into currentGlyphScale: paint-layer growth stays isotropic while the rendered glyph narrows.
Translates the quad at baseIdx, by whole pixels of its grid when it has one (SnapStep). Every modifier that moves a quad goes through here.
Resets the per-glyph state that onGlyph modifiers read and write — the claim race (fillClaimedThisGlyph/baseFaceClaimed), the claimed claimedFillSequence/claimedFillBlend, and the tier-upgrade currentMaxGlyphExtent. Every emitter of a glyph quad (face, kashida, decoration line) calls this before firing onGlyph.
Records a quad (4 vertices at baseVertexIdx) of the current segment (SDF or color) to be drawn at layer sequence with blend. Triangles are written in sequence order by MaterializeQuadTriangles, so painter order follows the layer stack; glyph-major ranges (paintOrders) group a glyph's quads together first, ordering layers within each glyph. The quad's owning cluster is read from its UV1 z channel (see Uvs1), which duplicate reservation copies from the source face.
public void RequestTierUpgradeIfNeeded(long glyphKey, uint glyphIndex, in GlyphAtlas.GlyphEntry entry, UniTextFont.Core font, long varHash48, int[] ftCoords, float glyphH, float aspect)Raises the current glyph's atlas pad tier when a modifier asked for more outward rim than the tier reserves — the glyph is re-rasterized smaller in its shared tile so the extra distance field (outline / shadow / bold) has room, plus TierSeamMarginNorm of AA-ramp headroom so the effect's outer edge samples inside computed field, not at the tile seam. Only the request is recorded here; the sweep re-rasterizes the tile and re-meshes every consumer of it at the new tier in the same frame (ProcessUpgrades). Grow-only.
public void RequestTileSizeUpgradeIfNeeded(long glyphKey, uint glyphIndex, UniTextFont.Core font, long varHash48, int[] ftCoords)Records a grow-only atlas tile-size upgrade for the current glyph when a resolution modifier asked for more detail / a larger tile than the font default. The sweep relocates the shared tile to the larger class and re-meshes its consumers the same frame (ProcessUpgrades). The glyph's atlas key ignores tile size, so all consumers share one tile at the max requested resolution. Call immediately after onGlyph.
Expands a 4-vertex quad outward: UV0 by delta (atlas-space, normalized by glyph height) and positions by the matching distance through the quad's own map, so the SDF sample stays attached to the geometry whatever size the quad was built or scaled to. On a pixel-grid glyph (SnapStep) the rim reaches the next whole font pixel instead of the requested distance, so no painted pixel is cut by the quad edge. The quad's recorded boundaries hold the result, and its opacity ramp extends over the grown area.
public void SetRectOffset(Rect rect)Sets the layout rectangle for text positioning.
public void GenerateMeshDataOnly(ReadOnlySpan<PositionedGlyph> glyphs, ReadOnlySpan<PositionedGlyph> virtualGlyphs)Generates mesh data (vertices, UVs, colors, triangles) from positioned glyphs. Groups by rendering target: SDF fonts in one segment (Texture2DArray), color separately.
public List<UniTextRenderData> CollectRenderData()Collects raw render data (vertex/UV/triangle array slices + material/order metadata) for every segment produced by the latest mesh generation. Does not build Unity Mesh objects — consumers (canvas UpdateSubMeshes, world batcher) decide what to do with the raw data.
Order for callbacks that complete the glyph quad's intrinsic presentation — a colour assigned outright, an inline sprite's tint and fit to its box — ahead of every default-order callback, so the transforms and colour modulation applied there land on top of it.
Order for callbacks that scale the completed glyph quad's alpha: after every lower order has written its colour, and before GlyphGeometryConsumerOrder derives geometry that inherits it.
public UniTextFont.Core fontCurrent font being processed.
Index of the first vertex of the face quad of the glyph currently being processed. Stable across all onGlyph invocations for a single glyph, even when modifiers append additional geometry that grows vertexCount.
Set during onGlyph by the fill that claims the current glyph's base quad, to its LayerSequence; left at DefaultFillSequence when none does. The face quad is ordered at this sequence, so an explicit fill stacks the glyph at its layer position.
Blend mode paired with claimedFillSequence for the current glyph face.
Added to every layer sequence a modifier captures while it is set, lifting a whole stack — face, stroke, shadow, glow — into a higher band together instead of leaving each layer at its own style-stack position. Zero for shaped text; a virtual-glyph emitter raises it around its own emission and restores it afterwards. A layer folds it in where it captures the sequence, during onGlyph — never where it flushes, by which time the emitter has restored it.
Largest resolution boost (0–2 tile-size classes above the glyph's default) a resolution modifier requested for the current glyph. Reset to 0 before each onGlyph; accumulated via max, read after to request a grow-only atlas tile-size upgrade. See RequestTileSizeUpgradeIfNeeded.
Product of every per-glyph scale applied to the current face quad (size, small-caps, sub/superscript, ruby, font metric overrides) via ScaleFace. Reset to 1 before each onGlyph; GlyphScale reads it back per quad once the glyph completes. Em → pixels for an emitted quad is fontMetricFactor times this: em geometry multiplies by it and absolute (px) geometry divides by it, so a px value keeps a constant on-screen size while the glyph scales.
Reset to false before each onGlyph; a fill layer sets it when it claims (recolours) the glyph's base quad, so later fills on the same glyph stack as duplicates instead of fighting over the base.
Set when a layer other than a fill takes over rendering the current glyph's base face in its own sub-mesh — a MaterialModifier in Replace mode. The base-mesh face quad must then not be recorded (it would sit at the claimed sequence as a transparent placeholder and stop the base mesh from slicing there, breaking layer order). Reset before each onGlyph.
Set when a fill replaces the current glyph's face with a copy it paints itself — a texture fill's sub-mesh quad, a colour glyph's silhouette — so the face is not recorded. A later fill that leaves the glyph's own picture as its paint clears it, and the face is recorded again at that fill's position. Reset before each onGlyph.
Set by a virtual-glyph emitter (decoration line with its own paint) around its onGlyph so the inherited text fill stands down entirely — neither claiming the base nor stacking a duplicate over it. Unlike fillClaimedThisGlyph (which only loses the base race and still overlays), this fully suppresses base fills, letting the line's own paint replace the inherited one (CSS text-decoration-color). Non-base layers (shadow, glow, stroke) are unaffected and still decorate the line.
True when the currently processed glyph is virtual (injected by a modifier — list marker, ellipsis dot — and has no ShapedGlyph behind it).
