Skip to content

Getting Started

Video Lecture

Section Video Links
Getting Started Getting Started Getting Started 

 (Pay Per View)

You can use PayPal to purchase a one time viewing of this video for $1.49 USD.

Pay Per View Terms

  • One viewing session of this video will cost the equivalent of $1.49 USD in your currency.
  • After successful purchase, the video will automatically start playing.
  • You can pause, replay and go fullscreen as many times as needed in one single session for up to an hour.
  • Do not refresh the browser since it will invalidate the session.
  • If you want longer-term access to all videos, consider purchasing full access through Udemy or YouTube Memberships instead.
  • This Pay Per View option does not permit downloading this video for later viewing or sharing.
  • All videos are Copyright © 2019-2025 Sean Bradley, all rights reserved.

What is TSL

  • TSL (Three.js Shading Language) is a high-level shader abstraction in Three.js.

  • It helps write shaders in a structured, readable way instead of writing raw GLSL or WGSL.

  • We write it directly in our JavaScript / TypeScript files.

  • It is best suited for when you want to write customised vertex, fragment and/or compute shaders.

Importing TSL

The TSL interpreter will convert our TSL code automatically into the equivalent WebGL2 or WebGPU shader code depending on the capabilities of our browser at runtime.

The TSL interpreter requires the three.webgpu.js import, rather then the more common three.module.js.

We can import the required Threejs modules into our project by using import maps or a build tool.

Import Maps

In the case of self hosting threejs, and using import maps, your import map could look like this below, provided that the paths to the files were correct from the perspective of your local web server.

 <script type="importmap">
    {
        "imports": {
            "three": "/build/three.webgpu.js",
            "three/webgpu": "/build/three.webgpu.js",
            "three/tsl": "/build/three.tsl.js",
            "three/addons/": "/jsm/"
        }
    }
</script>

Or if you were using a CDN to download the modules from the internet,

 <script type="importmap">
    {
        "imports": {
            "three": "https://cdn.jsdelivr.net/npm/three@<version>/build/three.webgpu.js",
            "three/webgpu": "https://cdn.jsdelivr.net/npm/three@<version>/build/three.webgpu.js",
            "three/tsl": "https://cdn.jsdelivr.net/npm/three@<version>/build/three.tsl.js",
            "three/addons/": "https://cdn.jsdelivr.net/npm/three@<version>/examples/jsm/"
        }
    }
</script>

Note. In the above import map code, you should replace <version> with a Threejs release number such as 0.178.0.

Build Tool

Or, you can use a build tool / bundler such as Vite or Webpack.

You wouldn't need to use import maps in this case, but you should install the Threejs library and optional types.

Your bundler will link up the required modules automatically and perform extra optimizations such as tree shaking any unused code.

npm install three

# optional but recommended. See note below.
npm install @types/three@0.176.0

Note

Type declarations for TSL from r177 onwards show hundreds of problems in TSL code despite the code still working when transpiled. I suspect it has something to do with a regression introduced in r177 that was fixed in r178 but not yet reflected in the @three/types. To hide the hundreds of warnings and errors that appear from r177 types onwards, then either place a // @ts-nocheck at the top of the *.ts file or a // @ts-ignore before each problematic line in the code.

Script Import Statements

And then in your code you would use imports the same, whether or not you were using a bundler or import maps.

For example,

import * as THREE from 'three/webgpu'
import { positionLocal, Fn, time, vec3 } from 'three/tsl'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'

Set Up Our Development Environment

All the working examples on this website will demonstrate TSL using JavaScript with import maps.

You will be able to view the source using the <> button in the view window of any working example.

However, while we learn, we will use a locally installed copy of Threejs and a build tool.

I have a boilerplate already setup that we can use.

The boilerplate is the Threejs Vite and TypeScript boilerplate created from my course https://sbcode.net/threejs/.

Since TSL doesn't yet have any TypeScript declaration information, we can disable type checking at specific parts of the code as necessary.

So, if you don't know TypeScript, or you don't want to use it, it doesn't matter. I won't focus on it much and will show you some work arounds.

But if you do want to use TypeScript, then either way, this course is still useful.

So before you start, you should preferably have these things installed.

Next, find a place on your system where you want to work, and install the boilerplate using these commands.

git clone https://github.com/Sean-Bradley/Three.js-Boilerplate-TS-Vite.git Three-TSL-Course

CD into the Three-TSL-Course folder.

cd Three-TSL-Course

Open VSCode

code .

Open a terminal. CtrlShift'

npm install
npm run dev

Then open a browser at http://localhost:5173/ and you will see a multi coloured wireframe cube.

This is not yet a TSL project, we will update the main.ts code with this start script below. Copy, paste and save it. Then go back into your open browser.

Start Script

./src/main.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import './style.css'
import * as THREE from 'three/webgpu'
import { color } from 'three/tsl'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'

const scene = new THREE.Scene()

const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  10
)
camera.position.z = 1

const renderer = new THREE.WebGPURenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
renderer.setAnimationLoop(animate)

window.addEventListener('resize', function () {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
})

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

const material = new THREE.NodeMaterial()
material.fragmentNode = color('crimson')

const mesh = new THREE.Mesh(new THREE.PlaneGeometry(), material)
scene.add(mesh)

function animate() {
  controls.update()

  renderer.render(scene, camera)
}

Working Example

<>

Threejs Vite and TypeScript boilerplate

https://sbcode.net/threejs/

Git

Node.js

VSCode

Three.js-Shading-Language (Wiki)