You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Three.js+React-Three-Fiber中向着色器传递浮点数组uniform?

问题解决方法

一、传递大长度数组到着色器

你之前把uDistance定义成vec3是核心错误——vec3仅能存储3个值,完全无法容纳1000元素的数组。正确做法是直接在GLSL中定义浮点数组:

1. 修改片段着色器

// 直接定义长度为1000的浮点数组
uniform float uDistance[1000];

varying float vDistance;

void main() {
  // 直接通过下标访问数组元素,注意下标范围是0-999
  float x = uDistance[52];
  vec3 color = vec3(0.5, 0.5, x);
  gl_FragColor = vec4(color, 1.0);
}

2. JS端uniform代码调整(补全依赖)

你的JS代码逻辑没问题,但要补全useMemo的依赖,确保数组更新时uniform能同步:

const uniforms = useMemo(() => ({
  uTime: { value: 0.0 },
  uRadius: { value: radius },
  uDistance: { value: normalDistances } // normalDistances需是长度1000的数组
}), [radius, normalDistances]) // 必须添加数组和半径作为依赖

二、动态传递数组长度(用#define)

如果不想硬编码数组长度1000,可以通过JS向着色器传递宏定义:

1. 着色器中使用宏占位

// 声明宏,具体值由JS传递
#define DISTANCE_COUNT 1000
uniform float uDistance[DISTANCE_COUNT];

varying float vDistance;

void main() {
  float x = uDistance[52];
  vec3 color = vec3(0.5, 0.5, x);
  gl_FragColor = vec4(color, 1.0);
}

2. React-Three-Fiber中传递define

在创建着色器材质时,通过defines字段传递宏值:

import { shaderMaterial } from '@react-three/drei'

const CustomMaterial = shaderMaterial(
  {
    uTime: 0.0,
    uRadius: radius,
    uDistance: normalDistances
  },
  // 你的顶点着色器代码(此处省略)
  `...`,
  // 你的片段着色器代码(此处省略)
  `...`,
  // 传递宏定义,动态获取数组长度
  { defines: { DISTANCE_COUNT: normalDistances.length } }
)

如果使用useShaderMaterial,同样可以在配置参数中添加defines字段。

关键注意事项

  • JS端数组长度必须和着色器中定义的数组长度完全一致,否则会出现访问越界或数据截断问题。
  • 务必补全useMemo的依赖数组,避免数组更新后uniform未同步的bug。

内容的提问来源于stack exchange,提问作者ewakwwg12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:11:02