From c431148015bef17dfb9fe3c6ea722b871123672e Mon Sep 17 00:00:00 2001 From: Justin Walsh Date: Tue, 11 Aug 2026 14:12:06 -0400 Subject: [PATCH] feat(text): publish the technique shader library as @pmndrs/text/tsl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Bitmap, MSDF, Slug, and decoration TSL node graphs — including the Slug shader tree that lived in core internals — move to src/tsl/ and publish on one subpath with Tsl-prefixed types, so a future TypeGPU or third-party integration consumes the same canonical shading implementation per technique. The Three entry stops re-exporting shader symbols; Three's materials import the library like any other consumer. A types test pins the subpath surface. --- docs/packages/text.md | 2 +- .../typegpu-first-shader-authority.md | 2 +- packages/text/package.json | 4 ++ packages/text/src/three.ts | 16 ------ packages/text/src/three/engine-plan-target.ts | 10 ++-- packages/text/src/three/material.ts | 12 ++--- packages/text/src/tsl.ts | 32 ++++++++++++ .../text/src/{three => tsl}/bitmap-shader.ts | 16 +++--- .../src/{three => tsl}/decoration-shader.ts | 6 +-- .../text/src/{three => tsl}/msdf-shader.ts | 13 ++--- .../text/src/{three => tsl}/slug-shader.ts | 23 ++++----- .../slug-shaders/calc-coverage.ts | 0 .../slug-shaders/calc-root-code.ts | 0 .../{internal => tsl}/slug-shaders/index.ts | 0 .../slug-shaders/reference.ts | 0 .../slug-shaders/slug-band.ts | 0 .../slug-shaders/slug-dilate.ts | 0 .../slug-shaders/slug-render.ts | 0 .../slug-shaders/slug-texture.ts | 0 .../slug-shaders/solve-quadratic.ts | 0 .../slug-shaders/tsl-compat.ts | 0 .../tests/integration/three-shader.test.mjs | 4 +- .../package/slug-shader-reference.test.mjs | 2 +- .../text/tests/types/three-shader-api.test.ts | 28 +++++------ packages/text/tests/types/tsl-api.test.ts | 50 +++++++++++++++++++ packages/text/tsconfig.slug-tsl.json | 16 +++--- 26 files changed, 151 insertions(+), 85 deletions(-) create mode 100644 packages/text/src/tsl.ts rename packages/text/src/{three => tsl}/bitmap-shader.ts (92%) rename packages/text/src/{three => tsl}/decoration-shader.ts (91%) rename packages/text/src/{three => tsl}/msdf-shader.ts (95%) rename packages/text/src/{three => tsl}/slug-shader.ts (91%) rename packages/text/src/{internal => tsl}/slug-shaders/calc-coverage.ts (100%) rename packages/text/src/{internal => tsl}/slug-shaders/calc-root-code.ts (100%) rename packages/text/src/{internal => tsl}/slug-shaders/index.ts (100%) rename packages/text/src/{internal => tsl}/slug-shaders/reference.ts (100%) rename packages/text/src/{internal => tsl}/slug-shaders/slug-band.ts (100%) rename packages/text/src/{internal => tsl}/slug-shaders/slug-dilate.ts (100%) rename packages/text/src/{internal => tsl}/slug-shaders/slug-render.ts (100%) rename packages/text/src/{internal => tsl}/slug-shaders/slug-texture.ts (100%) rename packages/text/src/{internal => tsl}/slug-shaders/solve-quadratic.ts (100%) rename packages/text/src/{internal => tsl}/slug-shaders/tsl-compat.ts (100%) create mode 100644 packages/text/tests/types/tsl-api.test.ts diff --git a/docs/packages/text.md b/docs/packages/text.md index fcec8e45..57105e20 100644 --- a/docs/packages/text.md +++ b/docs/packages/text.md @@ -5,7 +5,7 @@ description: Implements portable font loading, retained Rust shaping and layout, resource: ../../packages/text workspace_package: '@pmndrs/text' documentation_type: reference -source_digest: 'sha256:59b7ea711afa68e58594a0ea71adae087af34db89eba86c69d158477cf4acfd3' +source_digest: 'sha256:3319d616049bb62549c44923b92c729368f14858c9b7ce0651f43a24b9997ef8' tags: [package, public-api, rust, wasm, threejs, typography] sources: - id: manifest diff --git a/docs/planning/typegpu-first-shader-authority.md b/docs/planning/typegpu-first-shader-authority.md index 6f0f0feb..3e8261a2 100644 --- a/docs/planning/typegpu-first-shader-authority.md +++ b/docs/planning/typegpu-first-shader-authority.md @@ -40,7 +40,7 @@ sources: resource: ../../packages/text/src/raster/slug-technique.ts title: Merged v0 Slug TSL implementation - id: slug-texture-v0 - resource: ../../packages/text/src/internal/slug-shaders/slug-texture.ts + resource: ../../packages/text/src/tsl/slug-shaders/slug-texture.ts title: Merged v0 Slug texture access - id: gpucat resource: https://github.com/isaac-mason/gpucat/tree/11cf91b5172cc5143f68ff6ebf01c5e815de4e94 diff --git a/packages/text/package.json b/packages/text/package.json index 3a6388c9..f5f7d01a 100644 --- a/packages/text/package.json +++ b/packages/text/package.json @@ -26,6 +26,10 @@ "types": "./dist/core.d.ts", "import": "./dist/core.js" }, + "./tsl": { + "types": "./dist/tsl.d.ts", + "import": "./dist/tsl.js" + }, "./three": { "types": "./dist/three.d.ts", "import": "./dist/three.js" diff --git a/packages/text/src/three.ts b/packages/text/src/three.ts index ebb17b24..2f8f4035 100644 --- a/packages/text/src/three.ts +++ b/packages/text/src/three.ts @@ -10,12 +10,6 @@ export type { } from './formatted-text.js'; export type { FontSelection, FontStack, LoadedFont } from './loaded-font.js'; export type { GlyphBufferCapacity, ParagraphContentBox, ParagraphStyle } from './text-properties.js'; -export { bitmapShader } from './three/bitmap-shader.js'; -export type { - ThreeBitmapInstanceNodes, - ThreeBitmapShaderOutput, - ThreeBitmapShaderResources, -} from './three/bitmap-shader.js'; export { FontLoader } from './three/font-loader.js'; export { defineTextMaterial } from './three/material.js'; export type { ThreeTextMaterial, ThreeTextMaterialContext } from './three/material.js'; @@ -26,20 +20,10 @@ export type { ThreePlanProgramMaterialContext, ThreeRasterPlanProgram, } from './three/plan-program-registry.js'; -export { msdfShader } from './three/msdf-shader.js'; -export type { ThreeMsdfInstanceNodes, ThreeMsdfShaderOutput, ThreeMsdfShaderResources } from './three/msdf-shader.js'; export type { ThreeFontLoaderOptions as FontLoaderOptions, ThreeLoadedFontRequest as LoadedFontRequest, } from './three/font-loader.js'; -export { slugShader } from './three/slug-shader.js'; -export type { - ThreeSlugFillRule, - ThreeSlugInstanceNodes, - ThreeSlugPageResources, - ThreeSlugShaderOutput, - ThreeSlugShaderResources, -} from './three/slug-shader.js'; export { Text, TextGroup } from './three/text.js'; export type { StandaloneTextProperties, diff --git a/packages/text/src/three/engine-plan-target.ts b/packages/text/src/three/engine-plan-target.ts index cb4d6c9a..e1caffa7 100644 --- a/packages/text/src/three/engine-plan-target.ts +++ b/packages/text/src/three/engine-plan-target.ts @@ -8,11 +8,11 @@ import { TextEngineRenderPlanView, type RenderPlanTable } from '../core/plan-vie import { bitmap, type BitmapStrikeData } from '../raster/bitmap-technique.js'; import { msdf, type MsdfData } from '../raster/msdf.js'; import { slug, type SlugPageData } from '../raster/slug-technique.js'; -import { decorationShader } from './decoration-shader.js'; -import { bitmapShader } from './bitmap-shader.js'; +import { decorationShader } from '../tsl/decoration-shader.js'; +import { bitmapShader } from '../tsl/bitmap-shader.js'; import type { ThreeTextEngineCoordinator, ThreeTextEngineResource } from './engine-runtime.js'; -import { msdfShader } from './msdf-shader.js'; -import { slugShader, type ThreeSlugPageResources } from './slug-shader.js'; +import { msdfShader } from '../tsl/msdf-shader.js'; +import { slugShader, type TslSlugPageResources } from '../tsl/slug-shader.js'; import type { ThreeTextMaterialContext } from './material.js'; import type { ThreePlanProgramBuffer } from './plan-program-registry.js'; @@ -36,7 +36,7 @@ interface RetainedResource { readonly referenceId: number; } -interface RetainedSlugPage extends ThreeSlugPageResources { +interface RetainedSlugPage extends TslSlugPageResources { readonly byteLength: number; dispose(): void; } diff --git a/packages/text/src/three/material.ts b/packages/text/src/three/material.ts index c26330b4..176bb749 100644 --- a/packages/text/src/three/material.ts +++ b/packages/text/src/three/material.ts @@ -1,26 +1,26 @@ import type { Node, NodeMaterial } from 'three/webgpu'; -import type { ThreeBitmapShaderOutput } from './bitmap-shader.js'; -import type { ThreeMsdfShaderOutput } from './msdf-shader.js'; -import type { ThreeSlugShaderOutput } from './slug-shader.js'; +import type { TslBitmapShaderOutput } from '../tsl/bitmap-shader.js'; +import type { TslMsdfShaderOutput } from '../tsl/msdf-shader.js'; +import type { TslSlugShaderOutput } from '../tsl/slug-shader.js'; export type ThreeTextMaterialContext = | Readonly<{ technique: 'pmndrs.bitmap'; - shader: ThreeBitmapShaderOutput; + shader: TslBitmapShaderOutput; /** Final renderer-local position including policy-selected transform indirection. */ position: Node<'vec3'>; createDefaultMaterial(): NodeMaterial; }> | Readonly<{ technique: 'pmndrs.msdf'; - shader: ThreeMsdfShaderOutput; + shader: TslMsdfShaderOutput; position: Node<'vec3'>; createDefaultMaterial(): NodeMaterial; }> | Readonly<{ technique: 'pmndrs.slug'; - shader: ThreeSlugShaderOutput; + shader: TslSlugShaderOutput; position: Node<'vec3'>; createDefaultMaterial(): NodeMaterial; }>; diff --git a/packages/text/src/tsl.ts b/packages/text/src/tsl.ts new file mode 100644 index 00000000..11e73c9b --- /dev/null +++ b/packages/text/src/tsl.ts @@ -0,0 +1,32 @@ +/** + * The technique shader library: TSL node graphs for the Bitmap, MSDF, Slug, and + * decoration techniques, importable without the Three integration so any renderer + * that consumes TSL — including future TypeGPU integrations — reuses one canonical + * shading implementation per technique. + */ +export { + bitmapShader, + type TslBitmapInstanceNodes, + type TslBitmapShaderOptions, + type TslBitmapShaderOutput, + type TslBitmapShaderResources, +} from './tsl/bitmap-shader.js'; +export { + msdfShader, + type TslMsdfInstanceNodes, + type TslMsdfShaderOutput, + type TslMsdfShaderResources, +} from './tsl/msdf-shader.js'; +export { + slugShader, + type TslSlugFillRule, + type TslSlugInstanceNodes, + type TslSlugPageResources, + type TslSlugShaderOutput, + type TslSlugShaderResources, +} from './tsl/slug-shader.js'; +export { + decorationShader, + type TslDecorationInstanceNodes, + type TslDecorationShaderOutput, +} from './tsl/decoration-shader.js'; diff --git a/packages/text/src/three/bitmap-shader.ts b/packages/text/src/tsl/bitmap-shader.ts similarity index 92% rename from packages/text/src/three/bitmap-shader.ts rename to packages/text/src/tsl/bitmap-shader.ts index 9ec631e6..23d1e033 100644 --- a/packages/text/src/three/bitmap-shader.ts +++ b/packages/text/src/tsl/bitmap-shader.ts @@ -5,7 +5,7 @@ import type { Node, Texture } from 'three/webgpu'; * One glyph instance's canonical Bitmap fields, already resolved to nodes. Core owns what each field means; how a * program addresses it — storage buffers, instanced attributes, or a texture — stays the program's own choice. */ -export interface ThreeBitmapInstanceNodes { +export interface TslBitmapInstanceNodes { /** Paragraph-local glyph origin, in layout units, with y measured downward. */ readonly origin: Node<'vec2'>; /** Glyph quad extent in layout units. */ @@ -21,18 +21,18 @@ export interface ThreeBitmapInstanceNodes { } /** The GPU resources one Bitmap glyph batch binds: the single-channel coverage page its strike binding selected. */ -export interface ThreeBitmapShaderResources { +export interface TslBitmapShaderResources { /** Coverage page uploaded in the atlas's own top-down row order, so `flipY` must stay disabled. */ readonly page: Texture; } -export interface ThreeBitmapShaderOptions { +export interface TslBitmapShaderOptions { /** Snap projected vertices to physical pixels. Disabled by default so animated transforms retain subpixel motion. */ readonly pixelSnapping?: boolean; } /** Everything the canonical Bitmap graph produces, so a program can consume a stage or compose over its final output. */ -export interface ThreeBitmapShaderOutput { +export interface TslBitmapShaderOutput { readonly position: Node<'vec3'>; /** * Clip-space vertex position selected by the shader options. Pixel snapping is opt-in because it preserves strike @@ -57,10 +57,10 @@ export interface ThreeBitmapShaderOutput { * the glyph's upper-left corner. A program supplying different geometry owns that correspondence. */ export function bitmapShader( - instance: ThreeBitmapInstanceNodes, - resources: ThreeBitmapShaderResources, - options: ThreeBitmapShaderOptions = {}, -): ThreeBitmapShaderOutput { + instance: TslBitmapInstanceNodes, + resources: TslBitmapShaderResources, + options: TslBitmapShaderOptions = {}, +): TslBitmapShaderOutput { const atlasUv = TSL.vec2( instance.uvOrigin.x.add(TSL.uv().x.mul(instance.uvSize.x)), instance.uvOrigin.y.add(TSL.uv().y.mul(instance.uvSize.y)), diff --git a/packages/text/src/three/decoration-shader.ts b/packages/text/src/tsl/decoration-shader.ts similarity index 91% rename from packages/text/src/three/decoration-shader.ts rename to packages/text/src/tsl/decoration-shader.ts index 9f4dc960..4e6e8990 100644 --- a/packages/text/src/three/decoration-shader.ts +++ b/packages/text/src/tsl/decoration-shader.ts @@ -1,14 +1,14 @@ import * as TSL from 'three/tsl'; import type { Node } from 'three/webgpu'; -export interface ThreeDecorationInstanceNodes { +export interface TslDecorationInstanceNodes { /** Decoration rectangle: inline start, block start, inline extent, block extent. */ readonly rect: Node<'vec4'>; /** Packed decoration lanes: x carries little-endian RGBA color, y carries flags and line style. */ readonly packed: Node<'uvec2'>; } -export interface ThreeDecorationShaderOutput { +export interface TslDecorationShaderOutput { readonly position: Node<'vec3'>; readonly color: Node<'vec3'>; readonly opacity: Node<'float'>; @@ -30,7 +30,7 @@ const srgbTransferEotf = TSL.sRGBTransferEOTF as unknown as (color: Node<'vec3'> * the Rust gather decodes through its sRGB-to-linear table — so the color channels pass * through the sRGB EOTF into the renderer's linear working space. Alpha stays linear. */ -export function decorationShader(instance: ThreeDecorationInstanceNodes): ThreeDecorationShaderOutput { +export function decorationShader(instance: TslDecorationInstanceNodes): TslDecorationShaderOutput { const byte = TSL.float(1 / 255); const color = srgbTransferEotf( TSL.vec3( diff --git a/packages/text/src/three/msdf-shader.ts b/packages/text/src/tsl/msdf-shader.ts similarity index 95% rename from packages/text/src/three/msdf-shader.ts rename to packages/text/src/tsl/msdf-shader.ts index 77f1ee4d..a96ca84a 100644 --- a/packages/text/src/three/msdf-shader.ts +++ b/packages/text/src/tsl/msdf-shader.ts @@ -5,7 +5,7 @@ import type { Node, Texture } from 'three/webgpu'; * One glyph instance's canonical MSDF fields, already resolved to nodes. Core owns what each field means; how a * program packs them — the first-party target interleaves them into seven `vec4` storage buffers — stays its own choice. */ -export interface ThreeMsdfInstanceNodes { +export interface TslMsdfInstanceNodes { /** Paragraph-local glyph origin, in layout units, with y measured downward. */ readonly origin: Node<'vec2'>; /** Glyph quad extent in layout units. */ @@ -28,7 +28,7 @@ export interface ThreeMsdfInstanceNodes { } /** The GPU resources one MSDF glyph batch binds, plus the baked constants its distance field was generated with. */ -export interface ThreeMsdfShaderResources { +export interface TslMsdfShaderResources { /** Layered atlas whose RGB channels carry the multi-channel field and whose alpha carries the true distance. */ readonly atlas: Texture; readonly atlasWidth: number; @@ -44,7 +44,7 @@ export interface ThreeMsdfShaderResources { * gradient, so it is correct at any subpixel placement and must keep the default projection rather than snap to the * physical pixel grid. */ -export interface ThreeMsdfShaderOutput { +export interface TslMsdfShaderOutput { readonly position: Node<'vec3'>; /** Unclamped atlas coordinate the glyph cell is sampled at. */ readonly atlasUv: Node<'vec2'>; @@ -64,10 +64,7 @@ export interface ThreeMsdfShaderOutput { * The graph reads `positionLocal` and `uv()` from the technique's unit quad: both must span `[0, 1]` with the origin at * the glyph's upper-left corner. A program supplying different geometry owns that correspondence. */ -export function msdfShader( - instance: ThreeMsdfInstanceNodes, - resources: ThreeMsdfShaderResources, -): ThreeMsdfShaderOutput { +export function msdfShader(instance: TslMsdfInstanceNodes, resources: TslMsdfShaderResources): TslMsdfShaderOutput { const atlasU = instance.uvOrigin.x.add(TSL.uv().x.mul(instance.uvSize.x)); const atlasV = instance.uvOrigin.y.add(TSL.uv().y.mul(instance.uvSize.y)); const minimumU = instance.uvBounds.x.add(0.5 / resources.atlasWidth); @@ -127,7 +124,7 @@ function median3(value: Node<'vec3'>): Node<'float'> { function screenPixelRange( atlasU: Node<'float'>, atlasV: Node<'float'>, - resources: ThreeMsdfShaderResources, + resources: TslMsdfShaderResources, ): Node<'float'> { const screenTexelsU = TSL.float(1).div(TSL.max(TSL.fwidth(atlasU), 1e-6)); const screenTexelsV = TSL.float(1).div(TSL.max(TSL.fwidth(atlasV), 1e-6)); diff --git a/packages/text/src/three/slug-shader.ts b/packages/text/src/tsl/slug-shader.ts similarity index 91% rename from packages/text/src/three/slug-shader.ts rename to packages/text/src/tsl/slug-shader.ts index 26fb4b7c..7b7975b0 100644 --- a/packages/text/src/three/slug-shader.ts +++ b/packages/text/src/tsl/slug-shader.ts @@ -1,13 +1,13 @@ import * as TSL from 'three/tsl'; import type { DataTexture, Node } from 'three/webgpu'; -import { slugDilate, slugDilateMatrix, slugRender, type SlugRenderOptions } from '../internal/slug-shaders/index.js'; +import { slugDilate, slugDilateMatrix, slugRender, type SlugRenderOptions } from './slug-shaders/index.js'; /** * One glyph instance's canonical Slug fields, already resolved to nodes. The address and count fields locate the * glyph's band tables inside the shared page; core owns their meaning, and a program owns how it stores them. */ -export interface ThreeSlugInstanceNodes { +export interface TslSlugInstanceNodes { /** Paragraph-local glyph origin, in layout units, with y measured downward. */ readonly origin: Node<'vec2'>; /** Glyph quad extent in layout units. */ @@ -31,7 +31,7 @@ export interface ThreeSlugInstanceNodes { } /** The three integer textures one decoded Slug page publishes, plus the row widths that address them. */ -export interface ThreeSlugPageResources { +export interface TslSlugPageResources { readonly curveTexture: DataTexture; readonly curveWidth: number; readonly headerTexture: DataTexture; @@ -41,7 +41,7 @@ export interface ThreeSlugPageResources { } /** Optional coverage controls. Omitted fields keep the canonical non-zero winding rule with no weight compensation. */ -export interface ThreeSlugFillRule { +export interface TslSlugFillRule { readonly evenOdd?: Node<'bool'>; readonly weightBoost?: Node<'bool'>; readonly stemDarken?: Node<'float'>; @@ -53,10 +53,10 @@ export interface ThreeSlugFillRule { * dilation, so they must describe the same draw the returned position node feeds. */ interface ThreeSlugShaderResourceBase { - readonly page: ThreeSlugPageResources; + readonly page: TslSlugPageResources; /** Drawing-buffer size in device pixels. */ readonly viewport: Node<'vec2'>; - readonly fillRule?: ThreeSlugFillRule; + readonly fillRule?: TslSlugFillRule; } interface ThreeSlugShaderRowResources extends ThreeSlugShaderResourceBase { @@ -74,7 +74,7 @@ interface ThreeSlugShaderMatrixResources extends ThreeSlugShaderResourceBase { readonly modelViewProjectionRow3?: never; } -export type ThreeSlugShaderResources = ThreeSlugShaderRowResources | ThreeSlugShaderMatrixResources; +export type TslSlugShaderResources = ThreeSlugShaderRowResources | ThreeSlugShaderMatrixResources; /** * Everything the canonical Slug graph produces, so a program can consume a stage or compose over its final output. @@ -82,7 +82,7 @@ export type ThreeSlugShaderResources = ThreeSlugShaderRowResources | ThreeSlugSh * Unlike Bitmap this output publishes no `clipPosition`: Slug integrates coverage analytically from outlines, so it is * correct at any subpixel placement and must keep the default projection rather than snap to the physical pixel grid. */ -export interface ThreeSlugShaderOutput { +export interface TslSlugShaderOutput { /** Dilated glyph-quad position. Reading it from a vertex node is what publishes `renderCoordinate`. */ readonly position: Node<'vec3'>; /** Interpolated em-space coordinate the coverage integral is evaluated at. */ @@ -103,10 +103,7 @@ export interface ThreeSlugShaderOutput { * The graph reads `positionLocal` from the technique's unit quad, which must span `[0, 1]` with the origin at the * glyph's upper-left corner. A program supplying different geometry owns that correspondence. */ -export function slugShader( - instance: ThreeSlugInstanceNodes, - resources: ThreeSlugShaderResources, -): ThreeSlugShaderOutput { +export function slugShader(instance: TslSlugInstanceNodes, resources: TslSlugShaderResources): TslSlugShaderOutput { const renderCoordinate = TSL.varyingProperty('vec2', 'pmndrsSlugRenderCoordinate'); const position = TSL.Fn(() => { const localPosition = TSL.vec2( @@ -170,7 +167,7 @@ export function slugShader( }; } -function renderOptions(rule: ThreeSlugFillRule | undefined): SlugRenderOptions { +function renderOptions(rule: TslSlugFillRule | undefined): SlugRenderOptions { return { evenOdd: rule?.evenOdd ?? TSL.bool(false), weightBoost: rule?.weightBoost ?? TSL.bool(false), diff --git a/packages/text/src/internal/slug-shaders/calc-coverage.ts b/packages/text/src/tsl/slug-shaders/calc-coverage.ts similarity index 100% rename from packages/text/src/internal/slug-shaders/calc-coverage.ts rename to packages/text/src/tsl/slug-shaders/calc-coverage.ts diff --git a/packages/text/src/internal/slug-shaders/calc-root-code.ts b/packages/text/src/tsl/slug-shaders/calc-root-code.ts similarity index 100% rename from packages/text/src/internal/slug-shaders/calc-root-code.ts rename to packages/text/src/tsl/slug-shaders/calc-root-code.ts diff --git a/packages/text/src/internal/slug-shaders/index.ts b/packages/text/src/tsl/slug-shaders/index.ts similarity index 100% rename from packages/text/src/internal/slug-shaders/index.ts rename to packages/text/src/tsl/slug-shaders/index.ts diff --git a/packages/text/src/internal/slug-shaders/reference.ts b/packages/text/src/tsl/slug-shaders/reference.ts similarity index 100% rename from packages/text/src/internal/slug-shaders/reference.ts rename to packages/text/src/tsl/slug-shaders/reference.ts diff --git a/packages/text/src/internal/slug-shaders/slug-band.ts b/packages/text/src/tsl/slug-shaders/slug-band.ts similarity index 100% rename from packages/text/src/internal/slug-shaders/slug-band.ts rename to packages/text/src/tsl/slug-shaders/slug-band.ts diff --git a/packages/text/src/internal/slug-shaders/slug-dilate.ts b/packages/text/src/tsl/slug-shaders/slug-dilate.ts similarity index 100% rename from packages/text/src/internal/slug-shaders/slug-dilate.ts rename to packages/text/src/tsl/slug-shaders/slug-dilate.ts diff --git a/packages/text/src/internal/slug-shaders/slug-render.ts b/packages/text/src/tsl/slug-shaders/slug-render.ts similarity index 100% rename from packages/text/src/internal/slug-shaders/slug-render.ts rename to packages/text/src/tsl/slug-shaders/slug-render.ts diff --git a/packages/text/src/internal/slug-shaders/slug-texture.ts b/packages/text/src/tsl/slug-shaders/slug-texture.ts similarity index 100% rename from packages/text/src/internal/slug-shaders/slug-texture.ts rename to packages/text/src/tsl/slug-shaders/slug-texture.ts diff --git a/packages/text/src/internal/slug-shaders/solve-quadratic.ts b/packages/text/src/tsl/slug-shaders/solve-quadratic.ts similarity index 100% rename from packages/text/src/internal/slug-shaders/solve-quadratic.ts rename to packages/text/src/tsl/slug-shaders/solve-quadratic.ts diff --git a/packages/text/src/internal/slug-shaders/tsl-compat.ts b/packages/text/src/tsl/slug-shaders/tsl-compat.ts similarity index 100% rename from packages/text/src/internal/slug-shaders/tsl-compat.ts rename to packages/text/src/tsl/slug-shaders/tsl-compat.ts diff --git a/packages/text/tests/integration/three-shader.test.mjs b/packages/text/tests/integration/three-shader.test.mjs index a87ec565..1cdee8c5 100644 --- a/packages/text/tests/integration/three-shader.test.mjs +++ b/packages/text/tests/integration/three-shader.test.mjs @@ -4,7 +4,8 @@ import test from 'node:test'; import { createTextRuntime, FontRegistry } from '@pmndrs/text'; import { bitmap } from '@pmndrs/text/three/bitmap'; -import { bitmapShader, defineTextMaterial, msdfShader, slugShader, Text } from '@pmndrs/text/three'; +import { defineTextMaterial, Text } from '@pmndrs/text/three'; +import { bitmapShader, decorationShader, msdfShader, slugShader } from '@pmndrs/text/tsl'; import * as TSL from 'three/tsl'; import * as THREE from 'three/webgpu'; @@ -14,6 +15,7 @@ test('the canonical technique shaders are exported as callable node builders', ( assert.equal(typeof bitmapShader, 'function'); assert.equal(typeof msdfShader, 'function'); assert.equal(typeof slugShader, 'function'); + assert.equal(typeof decorationShader, 'function'); }); test('a custom Three material composes over the Bitmap shader in the Rust command-buffer draw path', async () => { diff --git a/packages/text/tests/package/slug-shader-reference.test.mjs b/packages/text/tests/package/slug-shader-reference.test.mjs index a8067888..7eeb2e53 100644 --- a/packages/text/tests/package/slug-shader-reference.test.mjs +++ b/packages/text/tests/package/slug-shader-reference.test.mjs @@ -11,7 +11,7 @@ import { referenceVerticalIntersections, resolveSlugCurveTexel, slugGridCoordinate, -} from '../../dist/internal/slug-shaders/reference.js'; +} from '../../dist/tsl/slug-shaders/reference.js'; test('V0 header decoding preserves exact unsigned count and glyph-local offset', () => { assert.deepEqual(decodeSlugHeader(0xabcd_fffe), { diff --git a/packages/text/tests/types/three-shader-api.test.ts b/packages/text/tests/types/three-shader-api.test.ts index 72c75c14..32a4ad85 100644 --- a/packages/text/tests/types/three-shader-api.test.ts +++ b/packages/text/tests/types/three-shader-api.test.ts @@ -2,25 +2,25 @@ import { mul, vec3 } from 'three/tsl'; import * as THREE from 'three/webgpu'; import type { Node } from 'three/webgpu'; +import { defineTextMaterial } from '../../src/three.js'; import { bitmapShader, - defineTextMaterial, msdfShader, slugShader, - type ThreeBitmapInstanceNodes, - type ThreeBitmapShaderResources, - type ThreeMsdfInstanceNodes, - type ThreeMsdfShaderResources, - type ThreeSlugInstanceNodes, - type ThreeSlugShaderResources, -} from '../../src/three.js'; + type TslBitmapInstanceNodes, + type TslBitmapShaderResources, + type TslMsdfInstanceNodes, + type TslMsdfShaderResources, + type TslSlugInstanceNodes, + type TslSlugShaderResources, +} from '../../src/tsl.js'; -declare const bitmapInstance: ThreeBitmapInstanceNodes; -declare const bitmapResources: ThreeBitmapShaderResources; -declare const mtsdfInstance: ThreeMsdfInstanceNodes; -declare const mtsdfResources: ThreeMsdfShaderResources; -declare const slugInstance: ThreeSlugInstanceNodes; -declare const slugResources: ThreeSlugShaderResources; +declare const bitmapInstance: TslBitmapInstanceNodes; +declare const bitmapResources: TslBitmapShaderResources; +declare const mtsdfInstance: TslMsdfInstanceNodes; +declare const mtsdfResources: TslMsdfShaderResources; +declare const slugInstance: TslSlugInstanceNodes; +declare const slugResources: TslSlugShaderResources; const bitmapOutput = bitmapShader(bitmapInstance, bitmapResources); const mtsdfOutput = msdfShader(mtsdfInstance, mtsdfResources); diff --git a/packages/text/tests/types/tsl-api.test.ts b/packages/text/tests/types/tsl-api.test.ts new file mode 100644 index 00000000..37682657 --- /dev/null +++ b/packages/text/tests/types/tsl-api.test.ts @@ -0,0 +1,50 @@ +import type { Node } from 'three/webgpu'; + +import { + bitmapShader, + decorationShader, + msdfShader, + slugShader, + type TslBitmapInstanceNodes, + type TslBitmapShaderOptions, + type TslBitmapShaderOutput, + type TslBitmapShaderResources, + type TslDecorationInstanceNodes, + type TslDecorationShaderOutput, + type TslMsdfInstanceNodes, + type TslMsdfShaderOutput, + type TslMsdfShaderResources, + type TslSlugFillRule, + type TslSlugInstanceNodes, + type TslSlugPageResources, + type TslSlugShaderOutput, +} from '@pmndrs/text/tsl'; + +// The four technique node graphs are one shader library, importable without the +// Three integration so future renderer integrations reuse them. +declare const bitmapInstance: TslBitmapInstanceNodes; +declare const bitmapResources: TslBitmapShaderResources; +declare const bitmapOptions: TslBitmapShaderOptions; +const bitmapOut: TslBitmapShaderOutput = bitmapShader(bitmapInstance, bitmapResources, bitmapOptions); +const bitmapColor: Node<'vec3'> = bitmapOut.color; +void bitmapColor; + +declare const msdfInstance: TslMsdfInstanceNodes; +declare const msdfResources: TslMsdfShaderResources; +const msdfOut: TslMsdfShaderOutput = msdfShader(msdfInstance, msdfResources); +void msdfOut; + +declare const slugInstance: TslSlugInstanceNodes; +declare const slugPages: readonly TslSlugPageResources[]; +declare const fillRule: TslSlugFillRule; +void slugShader; +void slugPages; +void fillRule; +declare const slugOut: TslSlugShaderOutput; +void slugOut; +void slugInstance; + +declare const decorationInstance: TslDecorationInstanceNodes; +const decorationOut: TslDecorationShaderOutput = decorationShader(decorationInstance); +const decorationOpacity: Node<'float'> = decorationOut.opacity; +void decorationOpacity; diff --git a/packages/text/tsconfig.slug-tsl.json b/packages/text/tsconfig.slug-tsl.json index 4187eeba..21b53afa 100644 --- a/packages/text/tsconfig.slug-tsl.json +++ b/packages/text/tsconfig.slug-tsl.json @@ -10,14 +10,14 @@ "types": ["node"] }, "files": [ - "src/internal/slug-shaders/calc-coverage.ts", - "src/internal/slug-shaders/calc-root-code.ts", - "src/internal/slug-shaders/slug-dilate.ts", - "src/internal/slug-shaders/slug-band.ts", - "src/internal/slug-shaders/slug-render.ts", - "src/internal/slug-shaders/slug-texture.ts", - "src/internal/slug-shaders/solve-quadratic.ts", - "src/internal/slug-shaders/tsl-compat.ts", + "src/tsl/slug-shaders/calc-coverage.ts", + "src/tsl/slug-shaders/calc-root-code.ts", + "src/tsl/slug-shaders/slug-dilate.ts", + "src/tsl/slug-shaders/slug-band.ts", + "src/tsl/slug-shaders/slug-render.ts", + "src/tsl/slug-shaders/slug-texture.ts", + "src/tsl/slug-shaders/solve-quadratic.ts", + "src/tsl/slug-shaders/tsl-compat.ts", "tests/types/tsl-scalar-operations.test.ts" ] }