@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
相关产品推荐
相关产品推荐

