CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-three

JavaScript 3D library providing WebGL and WebGPU renderers for creating interactive 3D graphics in web browsers

Pending
Overview
Eval results
Files

tsl.mddocs/

Three Shading Language (TSL)

Three Shading Language (TSL) is a node-based shading system that provides a JavaScript-friendly syntax for creating custom materials and effects. TSL enables developers to write shaders using familiar JavaScript constructs while generating optimized GPU code for both WebGL and WebGPU renderers.

Import: TSL functionality is available via the dedicated TSL build:

import { 
  color, vec3, vec4, float, int, bool,
  uniform, attribute, varying, texture,
  add, mul, sin, cos, normalize, dot,
  mix, smoothstep, clamp, pow
} from 'three/tsl';

Capabilities

Core Node Types

Fundamental building blocks for creating shader node graphs with type-safe operations.

/**
 * Base class for all TSL nodes
 */
abstract class Node {
  /** Node type identifier */
  nodeType: string;
  
  /** Node value type (float, vec3, etc.) */
  type: string | null;
  
  /** Unique identifier for this node */
  uuid: string;
  
  /**
   * Get node hash for caching
   * @returns Hash string
   */
  getHash(): string;
  
  /**
   * Update node before rendering
   * @param frame - Current render frame
   */
  update(frame: NodeFrame): void;
  
  /**
   * Build node for specific renderer  
   * @param builder - Node builder context
   * @returns Generated code string
   */
  build(builder: NodeBuilder): string;
  
  /**
   * Analyze node dependencies
   * @param builder - Node builder context
   */
  analyze(builder: NodeBuilder): void;
  
  /**
   * Generate code for this node
   * @param builder - Node builder context
   * @returns Generated shader code
   */
  generate(builder: NodeBuilder): string;
}

/**
 * Create uniform input node
 * @param value - Uniform value (number, Vector3, Color, etc.)
 * @returns Uniform node
 */
declare function uniform(value: any): UniformNode;

/**
 * Create vertex attribute input node
 * @param name - Attribute name in geometry
 * @param type - Attribute data type
 * @returns Attribute node
 */
declare function attribute(name: string, type?: string): AttributeNode;

/**
 * Create varying node for vertex-fragment communication
 * @param node - Node to pass from vertex to fragment
 * @param name - Optional varying name
 * @returns Varying node
 */
declare function varying(node: Node, name?: string): VaryingNode;

Vector and Scalar Types

Type-safe vector and scalar operations with automatic type inference and conversion.

/**
 * Create float/scalar node
 * @param value - Numeric value or node
 * @returns Float node
 */
declare function float(value: NodeRepresentation): FloatNode;

/**
 * Create integer node
 * @param value - Integer value or node
 * @returns Integer node  
 */
declare function int(value: NodeRepresentation): IntNode;

/**
 * Create boolean node
 * @param value - Boolean value or node
 * @returns Boolean node
 */
declare function bool(value: NodeRepresentation): BoolNode;

/**
 * Create 2D vector node
 * @param x - X component (number/node) or Vector2
 * @param y - Y component (number/node, optional if x is Vector2)
 * @returns Vec2 node
 */
declare function vec2(x?: NodeRepresentation, y?: NodeRepresentation): Vec2Node;

/**
 * Create 3D vector node  
 * @param x - X component (number/node) or Vector3
 * @param y - Y component (number/node, optional if x is Vector3)
 * @param z - Z component (number/node, optional if x is Vector3)
 * @returns Vec3 node
 */
declare function vec3(x?: NodeRepresentation, y?: NodeRepresentation, z?: NodeRepresentation): Vec3Node;

/**
 * Create 4D vector node
 * @param x - X component (number/node) or Vector4
 * @param y - Y component (number/node, optional if x is Vector4)
 * @param z - Z component (number/node, optional if x is Vector4)
 * @param w - W component (number/node, optional if x is Vector4)
 * @returns Vec4 node
 */
declare function vec4(
  x?: NodeRepresentation, 
  y?: NodeRepresentation, 
  z?: NodeRepresentation, 
  w?: NodeRepresentation
): Vec4Node;

/**
 * Create color node
 * @param color - Color value (Color, hex number, or RGB components)
 * @param g - Green component (if color is red component)
 * @param b - Blue component (if color is red component)
 * @returns Color node
 */
declare function color(color: NodeRepresentation, g?: NodeRepresentation, b?: NodeRepresentation): ColorNode;

/**
 * Create matrix nodes
 */
declare function mat3(...values: NodeRepresentation[]): Mat3Node;
declare function mat4(...values: NodeRepresentation[]): Mat4Node;

Usage Example:

import { vec3, color, float, uniform } from 'three/tsl';

// Create vector nodes
const position = vec3(0, 1, 0);
const direction = vec3(1, 0, 0);
const scale = float(2.0);

// Create uniform inputs
const time = uniform(0);
const baseColor = uniform(color(0xff0000));
const intensity = uniform(1.0);

// Combine nodes with operations
const animatedPosition = position.add(direction.mul(time));
const scaledColor = baseColor.mul(intensity);

Mathematical Operations

Comprehensive mathematical functions and operators for shader computations.

/**
 * Arithmetic operations
 */
declare function add(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function sub(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function mul(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function div(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function mod(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function pow(a: NodeRepresentation, b: NodeRepresentation): Node;

/**
 * Trigonometric functions
 */
declare function sin(node: NodeRepresentation): Node;
declare function cos(node: NodeRepresentation): Node;
declare function tan(node: NodeRepresentation): Node;
declare function asin(node: NodeRepresentation): Node;
declare function acos(node: NodeRepresentation): Node;
declare function atan(node: NodeRepresentation): Node;
declare function atan2(y: NodeRepresentation, x: NodeRepresentation): Node;

/**
 * Exponential and logarithmic functions
 */
declare function exp(node: NodeRepresentation): Node;
declare function exp2(node: NodeRepresentation): Node;
declare function log(node: NodeRepresentation): Node;
declare function log2(node: NodeRepresentation): Node;
declare function sqrt(node: NodeRepresentation): Node;
declare function inversesqrt(node: NodeRepresentation): Node;

/**
 * Common mathematical functions
 */
declare function abs(node: NodeRepresentation): Node;
declare function sign(node: NodeRepresentation): Node;
declare function floor(node: NodeRepresentation): Node;
declare function ceil(node: NodeRepresentation): Node;
declare function fract(node: NodeRepresentation): Node;
declare function min(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function max(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function clamp(value: NodeRepresentation, min: NodeRepresentation, max: NodeRepresentation): Node;
declare function mix(a: NodeRepresentation, b: NodeRepresentation, t: NodeRepresentation): Node;
declare function step(edge: NodeRepresentation, value: NodeRepresentation): Node;
declare function smoothstep(edge0: NodeRepresentation, edge1: NodeRepresentation, value: NodeRepresentation): Node;

/**
 * Vector operations
 */
declare function length(node: NodeRepresentation): Node;
declare function distance(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function dot(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function cross(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function normalize(node: NodeRepresentation): Node;
declare function reflect(incident: NodeRepresentation, normal: NodeRepresentation): Node;
declare function refract(incident: NodeRepresentation, normal: NodeRepresentation, eta: NodeRepresentation): Node;

/**
 * Matrix operations
 */
declare function matrixMultiply(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function transpose(matrix: NodeRepresentation): Node;
declare function determinant(matrix: NodeRepresentation): Node;
declare function inverse(matrix: NodeRepresentation): Node;

Usage Example:

import { vec3, float, sin, cos, normalize, dot, mix, smoothstep, time } from 'three/tsl';

// Create animated wave effect
const position = attribute('position');
const waveFreq = float(2.0);
const waveAmp = float(0.5);

const wave = sin(position.y.mul(waveFreq).add(time)).mul(waveAmp);
const animatedPosition = position.add(vec3(wave, 0, 0));

// Create lighting calculation
const normal = attribute('normal');
const lightDir = normalize(vec3(1, 1, 1));
const lightIntensity = max(dot(normal, lightDir), 0);

// Create color mixing
const baseColor = color(0x3366ff);
const highlightColor = color(0xffffff);
const finalColor = mix(baseColor, highlightColor, lightIntensity);

Texture Operations

Comprehensive texture sampling and manipulation functions for material creation.

/**
 * Create texture sampling node
 * @param texture - Texture uniform or object
 * @param uv - UV coordinates (vec2 node)
 * @param bias - Mipmap bias (optional)
 * @returns Texture sample node
 */
declare function texture(texture: NodeRepresentation, uv?: NodeRepresentation, bias?: NodeRepresentation): TextureNode;

/**
 * Create cube texture sampling node
 * @param texture - Cube texture uniform
 * @param direction - Sample direction (vec3 node)
 * @param bias - Mipmap bias (optional)
 * @returns Cube texture sample node
 */
declare function cubeTexture(texture: NodeRepresentation, direction: NodeRepresentation, bias?: NodeRepresentation): CubeTextureNode;

/**
 * Texture derivative functions
 */
declare function textureGrad(
  texture: NodeRepresentation, 
  uv: NodeRepresentation, 
  dPdx: NodeRepresentation, 
  dPdy: NodeRepresentation
): Node;

declare function textureLod(texture: NodeRepresentation, uv: NodeRepresentation, lod: NodeRepresentation): Node;

/**
 * Derivative functions for texture sampling
 */
declare function dFdx(node: NodeRepresentation): Node;
declare function dFdy(node: NodeRepresentation): Node;
declare function fwidth(node: NodeRepresentation): Node;

/**
 * Texture information functions
 */
declare function textureSize(texture: NodeRepresentation, lod?: NodeRepresentation): Node;
declare function textureQueryLod(texture: NodeRepresentation, uv: NodeRepresentation): Node;

Usage Example:

import { texture, vec2, mul, add, sin, cos, time } from 'three/tsl';

// Basic texture sampling
const diffuseMap = uniform(myTexture);
const uv = attribute('uv');
const diffuseColor = texture(diffuseMap, uv);

// Animated texture coordinates
const scrollSpeed = float(0.1);
const animatedUV = uv.add(vec2(time.mul(scrollSpeed), 0));
const scrollingTexture = texture(diffuseMap, animatedUV);

// Distorted texture sampling
const distortion = sin(uv.y.mul(10).add(time)).mul(0.02);
const distortedUV = uv.add(vec2(distortion, 0));
const distortedTexture = texture(diffuseMap, distortedUV);

// Multi-texture blending
const normalMap = uniform(myNormalTexture);
const roughnessMap = uniform(myRoughnessTexture);

const albedo = texture(diffuseMap, uv);
const normal = texture(normalMap, uv);
const roughness = texture(roughnessMap, uv).r; // Red channel only

Control Flow and Logic

Conditional operations and control flow constructs for complex shader logic.

/**
 * Conditional node for branching logic
 * @param condition - Boolean condition node
 * @param ifTrue - Node to use when condition is true
 * @param ifFalse - Node to use when condition is false
 * @returns Conditional result node
 */
declare function cond(condition: NodeRepresentation, ifTrue: NodeRepresentation, ifFalse: NodeRepresentation): Node;

/**
 * Logical operations
 */
declare function and(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function or(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function not(node: NodeRepresentation): Node;
declare function xor(a: NodeRepresentation, b: NodeRepresentation): Node;

/**
 * Comparison operations
 */
declare function equal(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function notEqual(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function lessThan(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function lessThanEqual(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function greaterThan(a: NodeRepresentation, b: NodeRepresentation): Node;
declare function greaterThanEqual(a: NodeRepresentation, b: NodeRepresentation): Node;

/**
 * Select operation (GPU-friendly conditional)
 * @param condition - Boolean condition
 * @param a - Value when condition is true
 * @param b - Value when condition is false
 * @returns Selected value
 */
declare function select(condition: NodeRepresentation, a: NodeRepresentation, b: NodeRepresentation): Node;

Usage Example:

import { cond, greaterThan, lessThan, mix, float, color } from 'three/tsl';

// Conditional color based on height
const position = attribute('position');
const heightThreshold = float(2.0);
const lowColor = color(0x00ff00);    // Green
const highColor = color(0xff0000);   // Red

const finalColor = cond(
  greaterThan(position.y, heightThreshold),
  highColor,
  lowColor
);

// Multi-level conditional
const midThreshold = float(1.0);
const midColor = color(0xffff00);    // Yellow

const triColor = cond(
  greaterThan(position.y, heightThreshold),
  highColor,
  cond(
    greaterThan(position.y, midThreshold),
    midColor,
    lowColor
  )
);

Built-in Variables and Constants

Access to standard shader variables and mathematical constants.

/**
 * Vertex shader built-ins
 */
declare const positionLocal: AttributeNode;      // Local position
declare const positionWorld: Node;              // World position  
declare const positionView: Node;               // View space position
declare const positionClip: Node;               // Clip space position
declare const normalLocal: AttributeNode;       // Local normal
declare const normalWorld: Node;                // World normal
declare const normalView: Node;                 // View space normal
declare const uv: AttributeNode;                // UV coordinates
declare const color: AttributeNode;             // Vertex colors

/**
 * Fragment shader built-ins
 */
declare const fragCoord: Node;                  // Fragment coordinates
declare const frontFacing: Node;               // Whether fragment is front-facing
declare const pointCoord: Node;                // Point sprite coordinates

/**
 * Camera and view uniforms
 */
declare const cameraPosition: UniformNode;      // World camera position
declare const cameraViewMatrix: UniformNode;    // View matrix
declare const cameraProjectionMatrix: UniformNode; // Projection matrix
declare const cameraNear: UniformNode;          // Near clipping plane
declare const cameraFar: UniformNode;           // Far clipping plane

/**
 * Object transform uniforms
 */
declare const modelMatrix: UniformNode;         // Model matrix
declare const modelViewMatrix: UniformNode;     // Model-view matrix
declare const normalMatrix: UniformNode;        // Normal transformation matrix

/**
 * Time and animation
 */
declare const time: UniformNode;                // Global time in seconds
declare const deltaTime: UniformNode;           // Frame delta time

/**
 * Mathematical constants
 */
declare const PI: FloatNode;                    // π (3.14159...)
declare const PI2: FloatNode;                   // 2π
declare const PI_HALF: FloatNode;               // π/2
declare const RECIPROCAL_PI: FloatNode;         // 1/π
declare const RECIPROCAL_PI2: FloatNode;        // 1/(2π)
declare const EPSILON: FloatNode;               // Small epsilon value
declare const E: FloatNode;                     // Euler's number (2.718...)

Custom Node Creation

System for creating reusable custom node functions and effects.

/**
 * Create custom function node
 * @param inputs - Input parameter definitions
 * @param returns - Return type  
 * @param body - Function body as TSL nodes
 * @returns Custom function node
 */
declare function tslFn(inputs: { [key: string]: string }, returns: string, body: (inputs: any) => Node): TslFunction;

/**
 * Create inline WGSL/GLSL code node
 * @param code - Raw shader code string
 * @param inputs - Input nodes array
 * @returns Code node
 */
declare function wgsl(code: string, ...inputs: Node[]): CodeNode;
declare function glsl(code: string, ...inputs: Node[]): CodeNode;

/**
 * Custom node class for complex operations
 */
abstract class TempNode extends Node {
  /**
   * Generate code for this custom node
   * @param builder - Node builder context
   * @param output - Output variable name
   * @returns Generated shader code
   */
  abstract generate(builder: NodeBuilder, output?: string): string;
}

Usage Example:

import { tslFn, vec3, float, sin, cos, mul, add } from 'three/tsl';

// Create custom wave function
const wave = tslFn({
  position: 'vec3',
  time: 'float', 
  frequency: 'float',
  amplitude: 'float'
}, 'vec3', ({ position, time, frequency, amplitude }) => {
  const wave = sin(position.y.mul(frequency).add(time)).mul(amplitude);
  return position.add(vec3(wave, 0, 0));
});

// Use custom function
const animatedPosition = wave({
  position: attribute('position'),
  time: time,
  frequency: float(2.0),
  amplitude: float(0.5)
});

// Create custom material effect
const customEffect = tslFn({
  uv: 'vec2',
  time: 'float'
}, 'vec3', ({ uv, time }) => {
  const r = sin(uv.x.mul(10).add(time)).mul(0.5).add(0.5);
  const g = cos(uv.y.mul(10).add(time)).mul(0.5).add(0.5);
  const b = sin(uv.x.add(uv.y).mul(5).add(time)).mul(0.5).add(0.5);
  return vec3(r, g, b);
});

Material Integration

Integration with Three.js material system for creating custom shaders with TSL.

/**
 * Create node material using TSL nodes
 */
class NodeMaterial extends ShaderMaterial {
  /**
   * Create node-based material
   * @param parameters - Material parameters with TSL nodes
   */
  constructor(parameters?: NodeMaterialParameters);
  
  /** Whether this is a node material */
  isNodeMaterial: true;
  
  /** Vertex position output node */
  positionNode: Node | null;
  
  /** Fragment color output node */
  colorNode: Node | null;
  
  /** Normal output node */
  normalNode: Node | null;
  
  /** Opacity output node */
  opacityNode: Node | null;
  
  /** Emissive color node */
  emissiveNode: Node | null;
  
  /** Metalness node */
  metalnessNode: Node | null;
  
  /** Roughness node */
  roughnessNode: Node | null;
  
  /** Custom vertex shader nodes */
  vertexNode: Node | null;
  
  /** Custom fragment shader nodes */
  fragmentNode: Node | null;
}

interface NodeMaterialParameters extends MaterialParameters {
  colorNode?: Node;
  opacityNode?: Node;
  normalNode?: Node;
  emissiveNode?: Node;
  metalnessNode?: Node;
  roughnessNode?: Node;
  positionNode?: Node;
  vertexNode?: Node;
  fragmentNode?: Node;
}

Types

// TSL type system
type NodeRepresentation = Node | number | boolean | string | Vector2 | Vector3 | Vector4 | Color | Matrix3 | Matrix4;

// Node builder context
interface NodeBuilder {
  material: Material;
  renderer: Renderer;
  object: Object3D;
  camera: Camera;
  scene: Scene;
  
  getUniformFromNode(node: Node): string;
  getVaryingFromNode(node: Node): string;
  getAttributeFromNode(node: Node): string;
  getCode(): string;
  addFlowCode(code: string): void;
}

// Node frame context  
interface NodeFrame {
  time: number;
  deltaTime: number;
  frameId: number;
  renderId: number;
  
  updateBeforeRender(renderer: Renderer, scene: Scene, camera: Camera, geometry: BufferGeometry, material: Material, object: Object3D): void;
}

// Core node types
interface FloatNode extends Node { type: 'float'; }
interface IntNode extends Node { type: 'int'; }
interface BoolNode extends Node { type: 'bool'; }
interface Vec2Node extends Node { type: 'vec2'; }
interface Vec3Node extends Node { type: 'vec3'; }
interface Vec4Node extends Node { type: 'vec4'; }
interface ColorNode extends Node { type: 'vec3'; }
interface Mat3Node extends Node { type: 'mat3'; }
interface Mat4Node extends Node { type: 'mat4'; }
interface TextureNode extends Node { type: 'vec4'; }
interface UniformNode extends Node { }
interface AttributeNode extends Node { }
interface VaryingNode extends Node { }
interface CodeNode extends Node { }

Usage Examples

Complete Custom Material with TSL:

import * as THREE from 'three';
import { 
  NodeMaterial,
  vec3, vec4, float, color,
  texture, mix, sin, cos, normalize, dot,
  time, uv, normalWorld, cameraPosition,
  uniform, mul, add, pow, clamp
} from 'three/tsl';

// Create custom animated material
class AnimatedCrystalMaterial extends NodeMaterial {
  constructor() {
    super();
    
    // Material properties
    this.baseColor = uniform(color(0x3366ff));
    this.emissionColor = uniform(color(0x66ccff));
    this.roughness = uniform(0.1);
    this.metalness = uniform(0.9);
    
    // Animation parameters
    this.animSpeed = uniform(1.0);
    this.waveFreq = uniform(2.0);
    this.waveAmp = uniform(0.1);
    
    this.setupNodes();
  }
  
  setupNodes() {
    // Animated vertex displacement
    const position = positionLocal;
    const displacement = sin(position.y.mul(this.waveFreq).add(time.mul(this.animSpeed)))
      .mul(this.waveAmp);
    
    this.positionNode = position.add(normalLocal.mul(displacement));
    
    // Animated colors based on viewing angle
    const viewDirection = normalize(cameraPosition.sub(positionWorld));
    const fresnel = dot(normalWorld, viewDirection);
    const fresnelPow = pow(clamp(fresnel, 0, 1), 2);
    
    // Animated emission
    const timeOscillation = sin(time.mul(2)).mul(0.3).add(0.7);
    const animatedEmission = this.emissionColor.mul(timeOscillation).mul(fresnelPow);
    
    // Final material properties
    this.colorNode = this.baseColor;
    this.emissiveNode = animatedEmission;
    this.roughnessNode = this.roughness;
    this.metalnessNode = this.metalness;
    
    // Custom fragment effects
    const sparkle = sin(uv.x.mul(50).add(time)).mul(sin(uv.y.mul(50).add(time)));
    const sparkleIntensity = clamp(sparkle.mul(10), 0, 1);
    
    this.colorNode = mix(
      this.baseColor,
      color(1, 1, 1),
      sparkleIntensity.mul(0.3)
    );
  }
  
  // Update animation parameters
  updateAnimation(deltaTime) {
    // Animation updates can be done here
    // Properties are automatically updated via uniforms
  }
}

// Usage in scene
const geometry = new THREE.IcosahedronGeometry(1, 2);
const material = new AnimatedCrystalMaterial();
const crystal = new THREE.Mesh(geometry, material);

scene.add(crystal);

// Animation loop
const clock = new THREE.Clock();
function animate() {
  const deltaTime = clock.getDelta();
  material.updateAnimation(deltaTime);
  
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

Install with Tessl CLI

npx tessl i tessl/npm-three

docs

animation.md

cameras.md

geometries.md

index.md

lights.md

loaders.md

materials.md

math.md

renderers.md

scene-management.md

tsl.md

webgpu.md

tile.json