Files
2026-03-28 13:57:54 +08:00

8.6 KiB

TSL Node Materials

Available Material Types

Material Description
MeshBasicNodeMaterial Unlit, no lighting calculations
MeshStandardNodeMaterial PBR material with metalness/roughness
MeshPhysicalNodeMaterial Advanced PBR with clearcoat, transmission, etc.
MeshPhongNodeMaterial Classic Phong shading
MeshToonNodeMaterial Cel/toon shading
MeshLambertNodeMaterial Diffuse-only lighting
MeshNormalNodeMaterial Visualize normals
MeshMatcapNodeMaterial Matcap texture shading
PointsNodeMaterial For point clouds
LineBasicNodeMaterial For lines
LineDashedNodeMaterial For dashed lines
SpriteNodeMaterial For sprites/billboards

Creating Node Materials

import * as THREE from 'three/webgpu';

// Standard PBR material
const material = new THREE.MeshStandardNodeMaterial();

// Physical material with advanced features
const physicalMat = new THREE.MeshPhysicalNodeMaterial();

// Unlit material
const basicMat = new THREE.MeshBasicNodeMaterial();

Material Properties

Color and Opacity

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

// Color from texture
material.colorNode = texture(diffuseMap);

// Solid color
material.colorNode = color(0xff0000);

// Computed color
material.colorNode = positionLocal.normalize();

// Opacity (requires material.transparent = true)
material.opacityNode = float(0.8);
material.transparent = true;

// Alpha test threshold
material.alphaTestNode = float(0.5);

PBR Properties (MeshStandardNodeMaterial)

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

// Metalness (0 = dielectric, 1 = metal)
material.metalnessNode = texture(metalMap).r;
material.metalnessNode = float(0.0);

// Roughness (0 = smooth/mirror, 1 = rough)
material.roughnessNode = texture(roughnessMap).r;
material.roughnessNode = float(0.5);

// Emissive (self-illumination)
material.emissiveNode = color(0xff0000).mul(2.0);
material.emissiveNode = texture(emissiveMap);

Normal Mapping

import { texture, normalMap, bumpMap } from 'three/tsl';

// Normal map
material.normalNode = normalMap(texture(normalMapTexture));

// Normal map with strength
material.normalNode = normalMap(texture(normalMapTexture), float(0.5));

// Bump map (height to normal)
material.normalNode = bumpMap(texture(heightMap), 0.05);

Physical Properties (MeshPhysicalNodeMaterial)

const material = new THREE.MeshPhysicalNodeMaterial();

// Clearcoat (car paint effect)
material.clearcoatNode = float(1.0);
material.clearcoatRoughnessNode = float(0.1);
material.clearcoatNormalNode = normalMap(texture(clearcoatNormalMap));

// Transmission (glass/translucency)
material.transmissionNode = float(0.9);
material.thicknessNode = float(0.5);
material.attenuationDistanceNode = float(1.0);
material.attenuationColorNode = color(0xffffff);

// Iridescence (soap bubble effect)
material.iridescenceNode = float(1.0);
material.iridescenceIORNode = float(1.3);
material.iridescenceThicknessNode = float(400);

// Sheen (fabric effect)
material.sheenNode = float(1.0);
material.sheenRoughnessNode = float(0.5);
material.sheenColorNode = color(0xffffff);

// Anisotropy (brushed metal)
material.anisotropyNode = float(1.0);
material.anisotropyRotationNode = float(0);

// Specular
material.specularIntensityNode = float(1.0);
material.specularColorNode = color(0xffffff);

// Index of Refraction
material.iorNode = float(1.5);

// Dispersion (rainbow effect in glass)
material.dispersionNode = float(0.0);

Environment and Lighting

import { cubeTexture, envMap } from 'three/tsl';

// Environment map reflection
material.envMapNode = cubeTexture(envCubeMap);

// Custom lights
material.lightsNode = lights();

Vertex Manipulation

Position Displacement

import { positionLocal, normalLocal, texture } from 'three/tsl';

// Displace vertices along normals
const displacement = texture(heightMap).r.mul(0.1);
material.positionNode = positionLocal.add(normalLocal.mul(displacement));

// Wave displacement
const wave = positionLocal.x.add(time).sin().mul(0.1);
material.positionNode = positionLocal.add(vec3(0, wave, 0));

Custom Vertex Shader

// Complete vertex position override
material.vertexNode = customVertexPosition;

Fragment Override

// Complete fragment output override
material.fragmentNode = vec4(finalColor, 1.0);

// Output node (respects lighting)
material.outputNode = outputStruct;

Geometry Attributes

Position Nodes

import {
  positionGeometry,  // Original mesh position
  positionLocal,     // Position in model space
  positionWorld,     // Position in world space
  positionView       // Position in camera space
} from 'three/tsl';

Normal Nodes

import {
  normalGeometry,    // Original mesh normal
  normalLocal,       // Normal in model space
  normalWorld,       // Normal in world space (use for lighting)
  normalView         // Normal in camera space
} from 'three/tsl';

Tangent/Bitangent

import {
  tangentLocal, tangentWorld, tangentView,
  bitangentLocal, bitangentWorld, bitangentView
} from 'three/tsl';

UV Coordinates

import { uv } from 'three/tsl';

uv()    // Primary UV set (UV0)
uv(1)   // Secondary UV set (UV1)
uv(2)   // Tertiary UV set (UV2)

Other Attributes

import { vertexColor, instanceIndex, vertexIndex } from 'three/tsl';

vertexColor()    // Vertex colors (if present)
instanceIndex    // Index for instanced meshes
vertexIndex      // Current vertex index

Camera Nodes

import {
  cameraPosition,         // Camera world position
  cameraNear,             // Near plane distance
  cameraFar,              // Far plane distance
  cameraViewMatrix,       // View matrix
  cameraProjectionMatrix, // Projection matrix
  cameraWorldMatrix       // Camera world matrix
} from 'three/tsl';

Screen Space Nodes

import {
  screenUV,         // Screen UV (0-1)
  screenCoordinate, // Pixel coordinates
  screenSize,       // Screen dimensions
  viewportUV,       // Viewport UV
  viewport,         // Viewport dimensions
  depth             // Fragment depth
} from 'three/tsl';

Examples

Animated Color Material

import * as THREE from 'three/webgpu';
import { color, time, oscSine, mix } from 'three/tsl';

const material = new THREE.MeshStandardNodeMaterial();

const colorA = color(0xff0000);
const colorB = color(0x0000ff);
const t = oscSine(time.mul(0.5));

material.colorNode = mix(colorA, colorB, t);
material.roughnessNode = float(0.5);
material.metalnessNode = float(0.0);

Triplanar Mapping Material

import * as THREE from 'three/webgpu';
import { texture, triplanarTexture, float } from 'three/tsl';

const material = new THREE.MeshStandardNodeMaterial();

// Apply texture from all three axes
material.colorNode = triplanarTexture(
  texture(diffuseMap),
  null,           // Y-axis texture (optional)
  null,           // Z-axis texture (optional)
  float(0.1)      // Blend sharpness
);

Glass Material

import * as THREE from 'three/webgpu';
import { float, color } from 'three/tsl';

const material = new THREE.MeshPhysicalNodeMaterial();

material.colorNode = color(0xffffff);
material.transmissionNode = float(0.95);
material.roughnessNode = float(0.0);
material.metalnessNode = float(0.0);
material.iorNode = float(1.5);
material.thicknessNode = float(0.5);

Fresnel Rim Material

import * as THREE from 'three/webgpu';
import {
  color, float, normalWorld, positionWorld,
  cameraPosition, Fn
} from 'three/tsl';

const fresnel = Fn(() => {
  const viewDir = cameraPosition.sub(positionWorld).normalize();
  const nDotV = normalWorld.dot(viewDir).saturate();
  return float(1.0).sub(nDotV).pow(3.0);
});

const material = new THREE.MeshStandardNodeMaterial();
material.colorNode = color(0x222222);
material.emissiveNode = color(0x00ffff).mul(fresnel());

Dissolve Effect Material

import * as THREE from 'three/webgpu';
import {
  color, float, hash, positionLocal, uniform,
  If, Discard, smoothstep
} from 'three/tsl';

const threshold = uniform(0.5);

const material = new THREE.MeshStandardNodeMaterial();

const noise = hash(positionLocal.mul(50));

// Discard fragments below threshold
If(noise.lessThan(threshold), () => {
  Discard();
});

// Edge glow
const edge = smoothstep(threshold, threshold.add(0.1), noise);
material.colorNode = color(0x333333);
material.emissiveNode = color(0xff5500).mul(float(1.0).sub(edge));