import { Mesh, Vector3, Vector2, MeshBasicNodeMaterial } from 'three/webgpu'; import type { BufferGeometry, Camera, ColorRepresentation, Intersection, Material, Object3DEventMap, Raycaster, Renderer, Scene, Side } from 'three/webgpu'; import type { WebGLRenderer } from 'three'; import { GlyphsGeometry } from '../extras/GlyphsGeometry.cjs'; import type { TextColorRanges, TextRenderInfo } from '../extras/TextBuilder.cjs'; import type { FontStyle, FontWeight } from '../extras/FontResolver.cjs'; import type { AnchorXValue, AnchorYValue, PercentageAnchor, TextAlignment, TextOverflowWrap, TextWhiteSpace } from '../extras/Typesetter.cjs'; import type { BidiDirection } from 'bidi-js'; import type { TextNodeSource, TextNodeUniforms } from './TextNode.cjs'; import type { TextColorNodeSource } from './TextColorNode.cjs'; import type { TSLTextureNode, TSLUniformNode } from '../types/tsl.cjs'; export type TextContent = string | number; export type TextLength = number | PercentageAnchor; export type TextClipRect = [minX: number, minY: number, maxX: number, maxY: number]; export type TextSyncCallback = () => void; export interface TextEventMap extends Object3DEventMap { syncstart: {}; synccomplete: {}; } export interface TextBatchVisibilityOwner { _visibilityDirty: boolean; } export interface TextMaterial extends MeshBasicNodeMaterial { _uWallBounds?: TSLUniformNode<'vec2', Vector2>; _uScreenOffset?: TSLUniformNode<'vec2', Vector2>; _screenSpace?: boolean; _textInstance?: Text; _uBillboard?: TSLUniformNode<'float', number>; _isUtsuboText?: boolean; _orientation?: string; _originalSide?: Side; } export interface TextSyncableProperties { font: string | null | undefined; fontSize: number; fontStyle: FontStyle; fontWeight: FontWeight; lang: string | null; letterSpacing: number; lineHeight: 'normal' | number; maxWidth: number; overflowWrap: TextOverflowWrap; text: TextContent; direction: BidiDirection; textAlign: TextAlignment; textIndent: number; whiteSpace: TextWhiteSpace; anchorX: AnchorXValue; anchorY: AnchorYValue; colorRanges: TextColorRanges | null; sdfGlyphSize: number | null; } /** * High-quality SDF-based text rendering with GPU-accelerated glyph generation. * * **Architecture** * - Multi-channel SDF (Signed Distance Field) atlas for sharp text at any scale * - Dynamic glyph packing and layout via `troika-three-text` * - TSL node-based material for advanced effects (outlines, fills) * - Async `sync()` generates glyphs on-demand with automatic atlas management * * **Features** * - Crisp text rendering at any distance/angle * - Fill and outline with independent colors/opacity * - Text alignment, wrapping, and layout control * - Custom positioning/coloring via TSL node hooks * - Efficient instancing for many text instances via `BatchedText` * * **Events** * - `syncstart`: Fired when layout/atlas generation begins * - `synccomplete`: Fired when geometry and material are ready * * ```js * import { Text } from 'three-blocks/experimental/runtime-sdf-text'; * * const text = new Text(); * text.text = 'Hello Three Blocks!'; * text.fontSize = 0.5; * text.color = 0x00ff00; * text.anchorX = 'center'; * text.anchorY = 'middle'; * * // Optional outline * text.outlineWidth = '5%'; * text.outlineColor = 0x000000; * * scene.add(text); * ``` * * @class Text * @extends THREE.Mesh * @tags WebGPU, WebGL * @demo docs/demos/text.html * @short SDF text mesh with async glyph atlas generation (troika) plus outline/fill controls and TSL hooks. * @category Text * @fires syncstart * @fires synccomplete */ declare class Text extends Mesh implements TextNodeSource, TextColorNodeSource { font: TextSyncableProperties['font']; fontSize: TextSyncableProperties['fontSize']; fontStyle: TextSyncableProperties['fontStyle']; fontWeight: TextSyncableProperties['fontWeight']; lang: TextSyncableProperties['lang']; letterSpacing: TextSyncableProperties['letterSpacing']; lineHeight: TextSyncableProperties['lineHeight']; maxWidth: TextSyncableProperties['maxWidth']; overflowWrap: TextSyncableProperties['overflowWrap']; text: TextSyncableProperties['text']; direction: TextSyncableProperties['direction']; textAlign: TextSyncableProperties['textAlign']; textIndent: TextSyncableProperties['textIndent']; whiteSpace: TextSyncableProperties['whiteSpace']; anchorX: TextSyncableProperties['anchorX']; anchorY: TextSyncableProperties['anchorY']; colorRanges: TextSyncableProperties['colorRanges']; sdfGlyphSize: TextSyncableProperties['sdfGlyphSize']; unicodeFontsURL: string | null; color: ColorRepresentation; outlineWidth: TextLength; outlineColor: ColorRepresentation; outlineOpacity: number | null; outlineBlur: TextLength; outlineOffsetX: TextLength; outlineOffsetY: TextLength; fillOpacity: number | null; depthOffset: number; clipRect: TextClipRect | null; orientation: string; gpuAccelerateSDF: boolean; debugSDF: boolean; uniforms: TextNodeUniforms; sdfMap: TSLTextureNode | undefined; _billboarding: boolean; _screenSpace: boolean | undefined; _batchedText: TextBatchVisibilityOwner | null; _visible: boolean; _needsSync: boolean | undefined; _isSyncing: boolean | undefined; _queuedSyncs: (TextSyncCallback | null | undefined)[] | null | undefined; _textRenderInfo: TextRenderInfo | null | undefined; constructor(); patchWebGPU(indices: ArrayLike): [indices: Float32Array, letterIndices: Float32Array]; /** * Trigger asynchronous glyph layout and SDF atlas generation. * Called automatically before render if text properties changed. * * @param {Function} [callback] Called when sync completes. * @param {THREE.WebGPURenderer} [renderer] Renderer for GPU SDF generation. */ sync(callback?: TextSyncCallback | null | undefined, renderer?: Renderer): void; /** * Configure material with TSL nodes for SDF sampling and rendering. * Sets up vertex/fragment shaders for both world-space and screen-space modes. * @param {THREE.Material} material Target material to configure. * @private */ prepareMaterial(material: TextMaterial): void; /** * Pre-render hook: ensures text is synced and material configured. * @param {THREE.WebGPURenderer} renderer * @param {THREE.Scene} scene * @param {THREE.Camera} camera * @param {THREE.BufferGeometry} geometry * @param {THREE.Material} material */ onBeforeRender(renderer: Renderer | WebGLRenderer, _scene: Scene, _camera: Camera, _geometry: BufferGeometry, material: Material): void; /** * Post-render hook: restores material side setting. * @param {THREE.WebGPURenderer} renderer * @param {THREE.Scene} scene * @param {THREE.Camera} camera * @param {THREE.BufferGeometry} geometry * @param {THREE.Material} material */ onAfterRender(_renderer: Renderer | WebGLRenderer, _scene: Scene, _camera: Camera, _geometry: BufferGeometry, material: Material): void; /** * Dispose of geometry resources. */ dispose(): void; /** * Get the computed text layout and SDF atlas information. * @type {Object|null} * @readonly */ get textRenderInfo(): TextRenderInfo | null; /** * Enable yaw-only billboarding so text always faces the camera. * When enabled, text rotates around the Y-axis to face the camera * while remaining upright. * @type {boolean} */ get billboarding(): boolean; set billboarding(value: boolean); /** * Enable screen-space rendering mode where text is positioned in NDC coordinates. * When enabled, text position is mapped from layout coordinates to screen pixels * using the viewport dimensions, useful for DOM-synchronized text overlays. * @type {boolean} */ get screenSpace(): boolean; set screenSpace(value: boolean); /** * Geometry tessellation detail level (1-3). * @type {number} */ get glyphGeometryDetail(): number; set glyphGeometryDetail(detail: number); _prepareForRender(material: TextMaterial): void | Promise; _parsePercent(value: TextLength): number; localPositionToTextCoords(position: Vector2 | Vector3, target?: Vector2): Vector2; worldPositionToTextCoords(position: Vector3, target?: Vector2): Vector2; raycast(raycaster: Raycaster, intersects: Intersection[]): void; copy(source: this): this; clone(): this; } export { Text };