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

@react-three/fiber中如何给Sphere的MeshBasicMaterial设置渐变色

Sphere 球体 MeshBasicMaterial 渐变实现方案

MeshBasicMaterial 本身不支持直接配置渐变属性,你可以通过以下两种常用方案实现需求,均适配你当前使用的 React Three Fiber 写法:


方案1:顶点颜色实现(无需写着色器)

通过给球体几何体的每个顶点设置插值后的颜色,开启材质的顶点颜色属性即可实现渐变,实现逻辑简单,性能优异:

import { useMemo } from 'react'
import * as THREE from 'three'

const GradientSphere = () => {
  // 预处理几何体,添加顶点颜色属性
  const sphereGeometry = useMemo(() => {
    const geo = new THREE.SphereBufferGeometry(0.8, 30, 30)
    const positionAttr = geo.getAttribute('position')
    const colors = []
    const topColor = new THREE.Color(0xffff00) // 渐变起始色:黄色
    const bottomColor = new THREE.Color(0xff0000) // 渐变结束色:红色
    
    // 计算球体y轴范围做值归一化
    geo.computeBoundingBox()
    const minY = geo.boundingBox.min.y
    const yRange = geo.boundingBox.max.y - minY

    for (let i = 0; i < positionAttr.count; i++) {
      const y = positionAttr.getY(i)
      // 归一化y值映射颜色插值比例
      const mixRatio = (y - minY) / yRange
      const currentColor = topColor.clone().lerp(bottomColor, 1 - mixRatio)
      colors.push(currentColor.r, currentColor.g, currentColor.b)
    }
    geo.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3))
    return geo
  }, [])

  return (
    <mesh geometry={sphereGeometry}>
      <meshBasicMaterial vertexColors attach="material" />
    </mesh>
  )
}
  • 优缺点:实现成本低,你当前设置的30段几何体细分足够支撑平滑的渐变效果,缺点是渐变精度和几何体顶点密度正相关,细分度太低会出现渐变断层。

方案2:自定义着色器实现(渐变完全平滑)

基于自定义着色器材质实现,渐变效果不受几何体细分度影响,自定义灵活度更高:

import * as THREE from 'three'
import { shaderMaterial } from '@react-three/drei'
import { extend } from '@react-three/fiber'

// 注册自定义渐变材质
const GradientBasicMaterial = shaderMaterial(
  {
    colorTop: new THREE.Color(0xffff00),
    colorBottom: new THREE.Color(0xff0000)
  },
  // 顶点着色器
  `
  varying float vY;
  void main() {
    vY = position.y;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  }
  `,
  // 片元着色器
  `
  uniform vec3 colorTop;
  uniform vec3 colorBottom;
  varying float vY;
  void main() {
    // 球体半径为0.8,y值范围是-0.8~0.8,归一化到0~1区间做颜色插值
    float mixRatio = (vY + 0.8) / 1.6;
    gl_FragColor = vec4(mix(colorBottom, colorTop, mixRatio), 1.0);
  }
  `
)
extend({ GradientBasicMaterial })

// 组件内直接使用
const GradientSphere = () => {
  return (
    <mesh>
      <sphereBufferGeometry args={[0.8, 30, 30]} attach="geometry" />
      <gradientBasicMaterial attach="material" />
    </mesh>
  )
}
  • 优缺点:渐变完全平滑无断层,后续可灵活调整渐变方向、新增多色渐变节点、修改过渡曲线,缺点是需要少量GLSL着色器基础,上述代码可直接复用。

如果需要其他方向的渐变,只需将上述代码中用于插值的y轴坐标替换为x轴/z轴/距离球心的距离即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:30:05