TSL + Vue 快速集成指南
面向已有 Vue 3 + Vite 基础的开发者,目标是用最少步骤将 Three.js 的 WebGPU/TSL 跑起来,并得到一个可验证的动态彩色平面。
1. 前提条件
- 浏览器具备 WebGPU 能力(新版 Chrome 等)。无 WebGPU 时 Three.js 可能回退,但 TSL 功能会受限。
- 建议使用 three@latest,从 three/webgpu 与 three/tsl 显式导入。
2. 安装
# 在你的 Vue 项目中安装 three(建议使用最新版本)
npm i three3. 最小可运行示例(拆分展示,保证高亮)
本示例用到 color、 time、 sin、 positionLocal TSL 节点。
新建:src/components/ColorPlaneTSL.vue
template:
<template>
<div ref="el"></div>
</template>script:
// <script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import * as THREE from 'three/webgpu'
import { color, time, sin, positionLocal } from 'three/tsl'
const el = ref(null)
let renderer, scene, camera, mesh
const handleResize = () => {
if (!renderer || !camera) return
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
}
onMounted(async () => {
// 1) 场景 / 相机 / 渲染器
scene = new THREE.Scene()
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.z = 2.5
renderer = new THREE.WebGPURenderer({ antialias: true })
renderer.setSize(window.innerWidth, window.innerHeight)
el.value.appendChild(renderer.domElement)
// 2) 平面网格 + Node 材质(TSL)
const geometry = new THREE.PlaneGeometry(2, 2)
const material = new THREE.MeshBasicNodeMaterial()
// 与 R3F 示例等价的 TSL 颜色节点:随时间变换的 RGB
const R = sin(positionLocal.x.add(time)).add(1).mul(0.5)
const G = sin(positionLocal.y.add(time)).add(1).mul(0.5)
const B = sin(positionLocal.x.add(time)).add(1).mul(0.5)
material.colorNode = color(R, G, B)
mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
// 3) 监听尺寸
window.addEventListener('resize', handleResize)
// 4) 初始化并渲染(不同 three 版本:init 可能是函数或 Promise 属性)
if (typeof renderer.init === 'function') await renderer.init()
else if (renderer.init) await renderer.init
renderer.setAnimationLoop(() => {
renderer.render(scene, camera)
})
})
onBeforeUnmount(() => {
window.removeEventListener('resize', handleResize)
renderer?.setAnimationLoop(null)
mesh?.geometry?.dispose?.()
mesh?.material?.dispose?.()
renderer?.dispose?.()
})
// </script>在 src/App.vue 挂载组件:
<!-- src/App.vue -->
<template>
<ColorPlaneTSL />
</template>
<script setup>
import ColorPlaneTSL from './components/ColorPlaneTSL.vue'
</script>
<style>
html, body, #app { height: 100%; margin: 0; }
</style>(可选)Vite 配置示例
// vite.config.js(可选)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'three/addons': 'three/examples/jsm'
}
}
})4. 运行与验证
- 启动本地服务:npm run dev。
- 看到页面出现一个随时间动态变化的彩色平面,即为成功。

5. 常见问题与排查
- 黑屏或空白: 先确认浏览器支持 WebGPU;其次确保已调用 await renderer.init()(不同 three 版本可能是函数或 Promise 属性,示例已兼容);最后检查是否把 renderer.domElement 正确 append 到容器。
- 找不到 three/tsl 或 WebGPURenderer: 升级到 three@latest,并从 three/webgpu 导入渲染器和 Node 材质,从 three/tsl 导入 color、time、sin、positionLocal 等节点函数。
- Multiple instances of Three.js: 说明导入了多个 three 实例。统一导入路径(都用 three/webgpu),必要时在 Vite 配置里用 resolve.alias 将 'three' 指到同一版本。
- 颜色不随时间变化: 确保使用 MeshBasicNodeMaterial 而不是普通材质;给 material.colorNode 赋值;并使用 renderer.setAnimationLoop 驱动渲染。
- 窗口缩放后比例异常: 在 resize 事件里更新 camera.aspect + camera.updateProjectionMatrix(),并调用 renderer.setSize()。