@basementstudio/shader-lab

中文文档
3.1.0发布于 2026/10/14TypeScriptES Module构建来源已验证近 30 天下载 2828

用于Shader Lab出口的可移植回放运行时间.

中文使用文档
文档目录31 节
  1. 安装
  2. 同伴依赖关系
  3. 所需资源
  4. 隔离群体
  5. 字体
  6. API 概览
  7. 高级API
  8. 高级 API
  9. 1. 组成
  10. 2. 使用构成作为纹理
  11. 纹理说明
  12. 3. 使用Shader Lab作为后处理
  13. 后处理说明
  14. useShaderLab
  15. 选项
  16. 返回值
  17. postprocessing
  18. 高级 API
  19. 钩子
  20. 类
  21. 自定义阴影层
  22. 如何运作
  23. 源模式 vs 效果模式
  24. 注射范围
  25. TSL 全球
  26. 沙德实验室设施
  27. 实例
  28. 包含运行时间支持
  29. 工具出口
  30. 页:1
  31. 链接

@basementstudio/shader-lab (英语)

basement.studio logo NPM version Website

@basementstudio/shader-lab 是一个从编辑器导出 Shader Lab 组件的可移植反应运行时间.

它支持三个主要使用案例:

  • 在 React 中直接渲染成份
  • 在您自己的场景中使用配体作为纹理
  • 使用 Shader 实验室效果层作为您自己的场景的后处理

安装

npm install @basementstudio/shader-lab three
bun add @basementstudio/shader-lab three

同伴依赖关系

  • react
  • react-dom
  • three

所需资源

  • 运行时间需要浏览器中的 WebGPU 支持
  • ShaderLabComposition 此套件中的钩子是客户端 API
  • 媒体层期望在 layer.asset.src
  • 组成纹理输出为画布后置,可以被 WebGL 或 WebGPU 主机场景所消耗
  • 后处理必须运行在同一程序上 WebGPURenderer 当你经过的场景纹理

所支持的效果层包括ASCII,blob跟踪,CRT,方向模糊,分色,半通,墨子,粒子网格,图案,像素排序,后缀,切片,边缘检测,移位图,和色调偏差.

Blob跟踪层检测出下方内容的移动(或亮度)区域,并用闭路电视风格的形状,标签,连接线条和出轨来设定. 一种内在效应可以在检测到的形状内通过 params.innerEffectType (任何过后效应类型)和 params.innerEffectParams (该效应参数的JSON字符串覆盖;参见 ShaderLabBlobInnerEffect 类型)。 设定 params.outputMode 改为 "mask" 以释放白黑相接的填充器使用 compositeMode: "mask"。 。 。 .

隔离群体

导出配置可以包含层 kind: "group", (中文(简体) ), type: "group",以及 params: {}儿童通过 parentId. 平面阵列使用最先,最后深度顺序:先是组,再是其所有后人,再是下个兄弟姐妹. 失踪或无效 parentId 在场景根上放置一层. ID必须是独一无二的,巢穴仅限于8个组.

例如,顺序 [title, portraitGroup, halftone, photo, background] 与 halftone.parentId 财务报告和审定财务报表 photo.parentId 设置为 portraitGroup.id 将半音限制在相片上。 每个组开始透明,处理内容,然后对结果应用自己的不透明与混合模式. 隐藏一个团体隐藏整个子树而不改变孩子的能见度. 组不透明/可视性可以使用普通的地层时间轨.

组使用 compositeMode: "filter", (中文(简体) ), hue: 0,以及 saturation: 1; 覆盖口罩和组色调整在此迭代中没有被曝光. 团体目标目前每组花费约32米B,为1080p. 现有的平面配置继续工作,没有任何新领域.

字体

ASCII 和文本层在运行时通过读取 CSS 解析字体家族 自定义属性( e)--geist-mono, (中文(简体) ), --bsmnt-grotesque, (中文(简体) ), --adhesion从 文档根。 每个变量的值用作 CSS font-family glyph 光栅化; 当变量未被设定时, 层 返回到系统字体.

包船 三个公开许可的家庭 - Geist Sans, Geist Mono,和BSMNT Grotesque——带有一个样式表,宣布 @font-face 规则和设置变量:

import "@basementstudio/shader-lab/fonts.css"

在Shader Lab编辑室(Adhesion, Blob, 包克克克克克尼切克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克 有商业执照。 它们在主机Shader Lab应用程序中使用,但 故意不与这个包一起分发。 使用它们(或 在主机应用程序中装入字体并设置匹配的 CSS 变量 其姓氏,例如:. :root { --adhesion: "Adhesion" }。 。 。 .

API 概览

高级API

  • ShaderLabComposition
  • useShaderLab

高级 API

  • useShaderLabCanvasSource
  • useShaderLabPostProcessingSource
  • useShaderLabTextureSource
  • ShaderLabCanvasSource
  • ShaderLabPostProcessingSource
  • ShaderLabTextureSource

使用 useShaderLab 除非您特别需要手动计时或生命周期控制.

1. 组成

"use client"

import {
  ShaderLabComposition,
  type ShaderLabConfig,
} from "@basementstudio/shader-lab"

const config: ShaderLabConfig = {
  layers: [],
  timeline: {
    duration: 6,
    loop: true,
    tracks: [],
  },
}

export default function Example() {
  return (
    <div style={{ width: "100%", maxWidth: 1200 }}>
      <ShaderLabComposition config={config} />
    </div>
  )
}

处理运行时间错误 :

<ShaderLabComposition
  config={config}
  onRuntimeError={(message) => {
    if (message) {
      console.error(message)
    } else {
      console.info("Shader Lab runtime error resolved.")
    }
  }}
/>

onRuntimeError 当运行时间出错时使用字符串消息调用 (启动失败, 阴影编译错误, 缺失 WebGPU) 支持)。 报告出错后,称为一次 null 何时 错误被解决后, UIs 可以恢复错误 。 它从来没有叫 null 在报告出错之前.

2. 使用构成作为纹理

useShaderLab 能够管理运行时间并返回即时使用 THREE.CanvasTexture。 。 。 .

"use client"

import {
  useShaderLab,
  type ShaderLabConfig,
} from "@basementstudio/shader-lab"
import { OrbitControls, PerspectiveCamera } from "@react-three/drei"
import { Canvas, useFrame } from "@react-three/fiber"
import { useMemo, useRef } from "react"
import * as THREE from "three"
import { WebGPURenderer } from "three/webgpu"

function Scene({ config }: { config: ShaderLabConfig }) {
  const { texture } = useShaderLab(config, {
    width: 1024,
    height: 1024,
  })

  const material = useMemo(
    () => new THREE.MeshBasicMaterial({ color: 0xffffff }),
    []
  )
  const meshRef = useRef<THREE.Mesh | null>(null)

  useFrame((_, delta) => {
    if (meshRef.current) {
      meshRef.current.rotation.y += delta * 0.3
    }

    if (texture) {
      texture.needsUpdate = true
      material.map = texture
      material.needsUpdate = true
    }
  })

  return (
    <>
      <color attach="background" args={["#0a0a0a"]} />
      <PerspectiveCamera makeDefault fov={50} position={[0, 0, 4]} />
      <mesh ref={meshRef} material={material}>
        <sphereGeometry args={[1, 64, 64]} />
      </mesh>
      <OrbitControls enableDamping />
    </>
  )
}

export function TexturedExample({ config }: { config: ShaderLabConfig }) {
  return (
    <Canvas
      gl={async (props) => {
        const renderer = new WebGPURenderer(
          props as ConstructorParameters<typeof WebGPURenderer>[0]
        )
        await renderer.init()
        return renderer
      }}
    >
      <Scene config={config} />
    </Canvas>
  )
}

纹理说明

  • texture 由软件包的内部输出画布支持
  • canvas 也可从下列网址获得: useShaderLab 如果您想要在原始画布级别整合
  • 运行时间在内部更新您的组成
  • 此纹理路径可移植到WebGL和WebGPU主机场景中, 因为软件包输出有画布支持

3. 使用Shader Lab作为后处理

后处理, useShaderLab 暴露一个 postprocessing 手柄.

你把场景变成纹理 然后把纹理交给沙德实验室.

"use client"

import {
  useShaderLab,
  type ShaderLabConfig,
} from "@basementstudio/shader-lab"
import { Canvas, useFrame, useThree } from "@react-three/fiber"
import { PerspectiveCamera } from "@react-three/drei"
import { createPortal } from "@react-three/fiber"
import { useEffect, useMemo, useRef } from "react"
import * as THREE from "three"
import { float, texture as tslTexture, uv, vec2 } from "three/tsl"
import { MeshBasicNodeMaterial, WebGPURenderer } from "three/webgpu"

function PostProcessedScene({ config }: { config: ShaderLabConfig }) {
  const { gl, scene, size } = useThree()
  const renderer = gl as unknown as WebGPURenderer
  const cameraRef = useRef<THREE.PerspectiveCamera | null>(null)
  const sceneTargetRef = useRef<THREE.WebGLRenderTarget | null>(null)

  const { postprocessing } = useShaderLab(config, {
    renderer,
    width: size.width,
    height: size.height,
  })

  const presentScene = useMemo(() => new THREE.Scene(), [])
  const presentCamera = useMemo(
    () => new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1),
    []
  )
  const presentTextureNode = useMemo(() => {
    const sampleUv = vec2(uv().x, float(1).sub(uv().y))
    return tslTexture(new THREE.Texture(), sampleUv)
  }, [])
  const presentMaterial = useMemo(() => {
    const material = new MeshBasicNodeMaterial()
    material.colorNode = presentTextureNode.rgb
    return material
  }, [presentTextureNode])

  useEffect(() => {
    const target = new THREE.WebGLRenderTarget(size.width, size.height)
    sceneTargetRef.current = target

    return () => {
      sceneTargetRef.current = null
      target.dispose()
    }
  }, [size.height, size.width])

  useEffect(() => {
    sceneTargetRef.current?.setSize(size.width, size.height)
    postprocessing.resize(size.width, size.height)
  }, [postprocessing, size.height, size.width])

  useFrame((state, delta) => {
    const target = sceneTargetRef.current
    const camera = cameraRef.current
    if (!(target && camera && postprocessing.ready)) return

    renderer.setRenderTarget(target)
    renderer.render(scene, camera)

    const output = postprocessing.render(
      target.texture,
      state.clock.elapsedTime,
      delta
    )

    if (output) {
      presentTextureNode.value = output
    }

    renderer.setRenderTarget(null)
    renderer.render(presentScene, presentCamera)
  }, 1)

  return (
    <>
      <PerspectiveCamera ref={cameraRef} makeDefault position={[0, 2, 5]} />

      <mesh position={[-1.2, 0, 0]}>
        <boxGeometry args={[1.4, 1.4, 1.4]} />
        <meshStandardMaterial color="#e74c3c" />
      </mesh>

      <mesh position={[1.2, 0, 0]}>
        <sphereGeometry args={[0.8, 32, 32]} />
        <meshStandardMaterial color="#3498db" />
      </mesh>

      {createPortal(
        <mesh frustumCulled={false}>
          <planeGeometry args={[2, 2]} />
          <primitive attach="material" object={presentMaterial} />
        </mesh>,
        presentScene
      )}
    </>
  )
}

export function PostProcessingExample({
  config,
}: {
  config: ShaderLabConfig
}) {
  return (
    <Canvas
      gl={async (props) => {
        const renderer = new WebGPURenderer(
          props as ConstructorParameters<typeof WebGPURenderer>[0]
        )
        await renderer.init()
        return renderer
      }}
    >
      <PostProcessedScene config={config} />
    </Canvas>
  )
}

后处理说明

  • 后处理仅为同级
  • 从同一处传出你的场景纹理 WebGPURenderer 你给了 useShaderLab
  • WebGL 主机渲染器不支持后处理
  • 只有效果的 沙德 实验室配置 最自然适合这里
  • 保留后处理 width编号 :height 财务报告和审定财务报表 postprocessing.resize(...) 与输入同步渲染目标大小,特别是用于屏幕-空间效果,如去色、像素和ASCII
  • postprocessing.texture 总是指向最近的输出纹理

外部输入纹理和输出纹理使用正( 非多倍化) RGB 还有阿尔法 纹理路径通过效果传递来保持输入覆盖; 效果输出α控制效果强度. 源层使用源层 组成。 在传递前将多倍输入转换为正α. 遗留面具层仍然使用他们现有的 RGB- darken 行为,以及 画布构成背景仍然不透明.

useShaderLab

const { canvas, ready, texture, postprocessing } = useShaderLab(config, options)

选项

选项说明
width内部运行时间输出宽度
height内部运行时间输出高度
pixelRatio可选像素比覆盖
canvas可选的现有画布,使组成
renderer可选共享 WebGPURenderer 用于后处理

返回值

外地说明
canvas内部输出画布
readytrue 当管理过的纹理路径初始化时
texture管理 THREE.CanvasTexture 由运行时显示布支持
postprocessing处理同级接线员后处理

postprocessing

外地说明
readytrue 后处理源初始化时
texture最近处理的产出纹理
resize(width, height, pixelRatio?)调整运行时间目标大小
render(inputTexture, time, delta)向输出纹理中渲染

高级 API

这些API是当您想要更直接地控制时间,调整行为大小,或对象生命周期时提供的.

用于:

  • 您已经拥有了自己的渲染回路, 想要手动驱动更新
  • 您想要原始输出画布而不是管理 CanvasTexture
  • 你想自己拥有完整的后处理管道
  • 您需要使用 React 以外的运行时间( 但仍在浏览器/ 客户端运行时间)

钩子

  • useShaderLabCanvasSource
  • useShaderLabPostProcessingSource
  • useShaderLabTextureSource
  • useShaderLabTexture

useShaderLabCanvasSource

需要原始画布和人工计时时时使用此功能.

const { canvas, ready, resize, update } = useShaderLabCanvasSource(config, {
  width: 1024,
  height: 1024,
})

useFrame((state, delta) => {
  if (!ready) return
  update(state.clock.elapsedTime, delta)
})

这在下列情况下是有用的:

  • 你想创造你自己 THREE.CanvasTexture
  • 你想把帆布喂进别的管道
  • 您想要确切决定何时更新组成

useShaderLabPostProcessingSource

想要控制整个场景到文字到屏幕的流量时使用这个.

const { ready, error, resize, texture, update } =
  useShaderLabPostProcessingSource(effectConfig, {
    renderer,
    width: size.width,
    height: size.height,
  })

useFrame((state, delta) => {
  if (!(ready && sceneTarget)) return

  renderer.setRenderTarget(sceneTarget)
  renderer.render(scene, camera)

  const output = update(
    sceneTarget.texture,
    state.clock.elapsedTime,
    delta
  )

  renderer.setRenderTarget(null)
  // present(output)
})

确保当场景改变目标大小时, Shader Lab 后处理源会调整大小 。 屏幕-空间效应使用这个尺寸来确定它们的采样网格.

这在下列情况下是有用的:

  • 你已经有你自己的目标了
  • 您要决定最终输出是如何呈现的
  • 您需要低于 useShaderLab().postprocessing

useShaderLabTextureSource

这暴露出下层的内部纹理来源.

只有在您特别想要内部纹理路径并理解渲染器的制约时才使用. 在大多数情况下, useShaderLab 或者说 useShaderLabCanvasSource 是更好的选择.

类

  • ShaderLabCanvasSource
  • ShaderLabPostProcessingSource
  • ShaderLabTextureSource

类API是钩子的非反应等同物.

典型流量 :

const source = new ShaderLabCanvasSource(config, {
  width: 1024,
  height: 1024,
})

await source.initialize()
source.update(time, delta)
source.resize(width, height)
source.dispose()

当 :

  • 你在外面反应
  • 你想要全手工控制生命周期
  • 您正在将 Shader Lab 整合到自定义运行时间或框架中

自定义阴影层

自定义阴影层允许您使用 GPU 阴影层写入 Three.js TSL( 三分语言)您的草图完全运行在 GPU 作为节点图 —— 没有 GLSL 或 WGSL 可写入 .

如何运作

您的代码必须导出一个被包裹的函数 Fn() 返回 TSL 节点( vec3 或 vec4) 。 编辑器会编译您的 TypeScript, 条形导入, 并评价结果为带有前置范围的沙盒. 一切从 three/tsl 而Shader Lab 通用图书馆作为全球图书馆可供使用——不需要进口.

export const sketch = Fn(() => {
  const color = vec3(uv().x, uv().y, sin(time).mul(0.5).add(0.5))
  return color
})

点击 应用 (或作再作活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活 导出项名默认为 sketch 但可以在条目导出字段中更改.

源模式 vs 效果模式

自定义阴影层有一个 效果模式 切换 :

  • 源模式 (默认)——地层从头产生像素,像梯度或图像. 您的草图输出每个像素的颜色 。 输出为线性( sRGB → 线性通过) pow(2.2))与堆肥管道相匹配.

  • 效果模式 ——地层发挥后处理作用. 它通过它接收下方所有层的复合结果 inputTexture 并改变它。 由于输入已经处于线性空间,因此没有应用γ转换.

注射范围

这些变量被注入到您的草图中,并作为全局数据提供:

变量类型说明
timefloat以秒计耗时, 不断更新
inputTextureTextureNode下面的复合层(效果模式). 在源模式下, 这是空白的纹理 。 直接用于默认- UV 颜色, 或调用 .sample(customUV) 以自定义坐标重采样

TSL 全球

全部从 three/tsl 已提供。 关键:

函数说明
Fn(() => { ... })定义延后的阴影函数( 需要的包装)
float, (中文(简体) ), vec2, (中文(简体) ), vec3, (中文(简体) ), vec4平面和向量类型的构造器
uv()碎片紫外线坐标 (0-1)
screenSize将传送分辨率视为 vec2
sin, (中文(简体) ), cos, (中文(简体) ), abs, (中文(简体) ), floor, (中文(简体) ), round, (中文(简体) ), pow, (中文(简体) ), mix, (中文(简体) ), clamp, (中文(简体) ), smoothstep, (中文(简体) ), dot, (中文(简体) ), min, (中文(简体) ), max标准数学
texture(tex, uv)给定紫外线上的纹理样本
uniform(value)创建统一节点
select(cond, a, b)初选
If(cond, () => { ... }).Else(...)有条件分支 .toVar() 任务

节点用方法链: a.add(b), (中文(简体) ), a.mul(b), (中文(简体) ), a.sub(b), (中文(简体) ), a.div(b), (中文(简体) ), a.negate(), (中文(简体) ), a.toVar() (使可变), a.assign(b) (将 a 移动到 Var 节点).

沙德实验室设施

这些是与 TSL 一起注入的额外助手 :

噪声

函数签署说明
simplexNoise3d(vec3) → float3D 简单音响
simplexNoise4d(vec4) → float4D 简单音响( 使用) .w (时间)
perlinNoise3d(vec3) → float3D 佩林噪声
valueNoise3d(vec3) → float三维值噪声
voronoiNoise3d(vec3) → vec23D 沃罗诺伊.x =细胞分解, .y =边角)
fbm(vec3) → float分形布朗运动(2-octave simplex)
curlNoise3d(vec3) → vec33D 卷曲噪声
curlNoise4d(vec4) → vec34D 卷曲噪声
ridgeNoise(vec3) → float山脊噪声
turbulence(vec3) → float骚动的噪音

记事

函数签署说明
reinhardTonemap(vec3) → vec3莱因哈德语调图
acesTonemap(vec3) → vec3ACES 电影音调图
technicolorTonemap(vec3) → vec3温暖的科技色彩外观
cinematicTonemap(vec3) → vec3有线的电影S曲线
bleachBypassTonemap(vec3) → vec3脱饱和高孔
crossProcessTonemap(vec3) → vec3跨进程颜色变化
totosTonemap(vec3) → vec3Basement 的自定义胶片色调图

SDF 原始人

函数签署说明
sdBox2d(vec2, float) → float2D 框签名距离
sdSphere(vec3, float) → float3D 球体签名距离
sdDiamond(vec2, float) → float2D 钻石签名距离
sdRhombus(vec2, vec2) → float2D Rhombus 签名距离

数学空间( S)

函数签署说明
screenAspectUV(screenSize, range?) → vec2以原产地为中心、被视线校正的紫外线
rotate(vec2, float) → vec22D 按角度旋转(弧度)
smin(float, float, float) → float最小平滑
smax(float, float, float) → float最大滑动度
atan2(float, float) → float两相弧度
tanh(float) → float双曲正切
sinh(float) → float双曲正弦
cosh(float) → float双曲余弦
cosinePalette(t, a, b, c, d, e?) → vec3基于余弦的调色板生成器

复杂的数学

所有复杂业务的使用 vec2 地点 .x 真实的, .y = 虚构:

complexMul, (中文(简体) ), complexDiv, (中文(简体) ), complexPow, (中文(简体) ), complexSqrt, (中文(简体) ), complexSin, (中文(简体) ), complexCos, (中文(简体) ), complexTan, (中文(简体) ), complexLog, (中文(简体) ), complexConj, (中文(简体) ), complexToPolar, (中文(简体) ), complexMobius

模式

函数签署说明
bloom(float) → float软发光曲线
bloomEdgePattern(float, float, float) → float边缘意识开花
canvasWeavePattern(vec2, float) → float织布纹理
grainTexturePattern(vec2) → float胶片粒纹理
repeatingPattern(vec2, float) → vec2倾斜紫外线帮助器

实例

出处模式 — 有色调的动画梯度 :

export const sketch = Fn(() => {
  const uv0 = screenAspectUV(screenSize)
  const color = vec3(
    uv0.x.add(0.5),
    uv0.y.add(0.5),
    sin(time).mul(0.5).add(0.5)
  ).toVar()
  color.assign(technicolorTonemap(color))
  return color
})

效果模式——自定义紫外线的样本输入有扭曲:

export const sketch = Fn(() => {
  const warp = sin(uv().y.mul(20).add(time.mul(2))).mul(0.02)
  const warped = vec2(uv().x.add(warp), uv().y)
  return inputTexture.sample(warped)
})

效果模式——简单的色彩操作 :

export const sketch = Fn(() => {
  const color = inputTexture.toVar()
  const luma = dot(color.rgb, vec3(0.299, 0.587, 0.114))
  return vec4(vec3(luma), color.a)
})

包含运行时间支持

包含模式支持中的图像和视频层 params.transparentBounds: true 以揭示其空地边界下的内容。 关闭设置或使用 false 以保留黑色边界。 此选项不影响封面模式或制作 组成背景透明.

  • 渐变
  • 文本
  • 自定义阴影( 来源和效果模式)
  • 图像和视频来源
  • 实时相机输入
  • ASC 二届理事会
  • 图案
  • 墨迹
  • 半圆
  • 抖动
  • CRT 网络
  • 粒子网格
  • 像素排序

工具出口

  • createRuntimeClock
  • advanceRuntimeClock
  • buildRuntimeFrame
  • evaluateTimelineForLayers
  • resolveEvaluatedLayers
  • 运行时间配置和时间轴类型

页:1

  • ShaderLabComposition 仅在 config.composition ,否则将填充由您布局定义的大小
  • useShaderLab 是大多数应用程序集成推荐的切入点
  • 如果您只需要在 DOM 中直接渲染成分, 请使用 ShaderLabComposition
  • 如果需要全手工控制,请使用下级源 API
  • 纹理输出是可移植的,因为它由管理的画布支撑
  • 后处理目前需要共享 THREE.WebGPURenderer
  • 如果您使用三发式反射 [email protected]你可能会看到 THREE.Clock 从 @react-three/fiber; 警告是上游的, 不是由此套件发出的

版本与发布记录

@basementstudio/shader-lab 共发布 30 个版本,首次发布于 2026/03/28;过去 12 个月发布了 30 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
3.1.0latest2026/10/1424 天前
3.0.22026/09/012 个月前
3.0.12026/08/242 个月前
3.0.02026/08/202 个月前
2.1.02026/08/192 个月前
2.0.02026/08/122 个月前

关于 @basementstudio/shader-lab 的常见问题

@basementstudio/shader-lab 是什么?

用于Shader Lab出口的可移植回放运行时间.

如何安装 @basementstudio/shader-lab?

在项目目录运行 npm install @basementstudio/shader-lab,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^19.0.0)、three(^0.185.0)、react-dom(^19.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@basementstudio/shader-lab 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@basementstudio/shader-lab 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@basementstudio/shader-lab 可以商用吗?

@basementstudio/shader-lab 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@basementstudio/shader-lab 的下载量有多少?

根据 npm 官方下载统计,@basementstudio/shader-lab 在 2026/10/08 – 2026/11/06 这 30 天内被下载 2,828 次,日均约 94 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@basementstudio/shader-lab 还在维护吗?

最新版本 3.1.0 发布于 2026/10/14(24 天前);至今共发布 30 个版本,其中过去 12 个月发布了 30 个;首次发布于 2026/03/28。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。