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

React Three Fiber精灵球制作:实现清晰红白颜色分界

解决React Three Fiber精灵球颜色清晰分界问题

你用GradientTexture会产生平滑过渡的渐变,所以出现模糊。要实现清晰的颜色分界,直接通过着色器判断顶点位置切换颜色是最直接的方案,下面给两种具体实现方式:

方案一:使用自定义着色器材质

直接在片元着色器里基于球体顶点的Y坐标区分颜色,完全没有过渡:

import { Canvas } from '@react-three/fiber'
import * as THREE from 'three'

export default function Pokeball() {
  return (
    <>
      <Canvas style={{ height: '10vh', width: '100%' }}>
        <ambientLight intensity={0.5} />
        <directionalLight position={[0, 10, 0]} intensity={1} castShadow />
        <mesh position={[0, 0, 0]} castShadow receiveShadow>
          <sphereGeometry args={[1, 32, 32]} />
          {/* 自定义着色器材质 */}
          <shaderMaterial
            uniforms={{
              colorRed: { value: new THREE.Color('red') },
              colorWhite: { value: new THREE.Color('white') },
              splitY: { value: 0.0 } // 分界位置,0为球体中心
            }}
            vertexShader={`
              varying vec3 vVertexPosition;
              void main() {
                vVertexPosition = position;
                gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
              }
            `}
            fragmentShader={`
              uniform vec3 colorRed;
              uniform vec3 colorWhite;
              uniform float splitY;
              varying vec3 vVertexPosition;
              
              void main() {
                // 根据顶点Y坐标判断颜色,低于分界点用红色,高于用白色
                gl_FragColor = vec4(vVertexPosition.y < splitY ? colorRed : colorWhite, 1.0);
              }
            `}
          />
        </mesh>
      </Canvas>
    </>
  )
}

方案二:修改现有材质的着色器

如果不想用纯自定义着色器,可以通过onBeforeCompile修改meshBasicMaterial的着色逻辑:

import { Canvas } from '@react-three/fiber'
import * as THREE from 'three'

export default function Pokeball() {
  return (
    <>
      <Canvas style={{ height: '10vh', width: '100%' }}>
        <ambientLight intensity={0.5} />
        <directionalLight position={[0, 10, 0]} intensity={1} castShadow />
        <mesh position={[0, 0, 0]} castShadow receiveShadow>
          <sphereGeometry args={[1, 32, 32]} />
          <meshBasicMaterial
            onBeforeCompile={(shader) => {
              // 添加自定义参数
              shader.uniforms.colorRed = { value: new THREE.Color('red') }
              shader.uniforms.colorWhite = { value: new THREE.Color('white') }
              shader.uniforms.splitY = { value: 0.0 }

              // 顶点着色器传递顶点位置
              shader.vertexShader = `
                varying vec3 vVertexPosition;
                ${shader.vertexShader}
              `.replace(
                '#include <begin_vertex>',
                `#include <begin_vertex>
                vVertexPosition = position;`
              )

              // 片元着色器替换颜色逻辑
              shader.fragmentShader = `
                uniform vec3 colorRed;
                uniform vec3 colorWhite;
                uniform float splitY;
                varying vec3 vVertexPosition;
                ${shader.fragmentShader}
              `.replace(
                'vec4 diffuseColor = vec4( diffuse, opacity );',
                `vec3 finalColor = vVertexPosition.y < splitY ? colorRed : colorWhite;
                vec4 diffuseColor = vec4(finalColor, opacity);`
              )
            }}
          />
        </mesh>
      </Canvas>
    </>
  )
}

补充:添加精灵球中间的黑色环

如果要还原精灵球的完整样式,可以在球体中间加一个圆环:

// 在球体mesh后面添加
<mesh position={[0, 0, 0]}>
  <torusGeometry args={[1, 0.05, 16, 100]} />
  <meshBasicMaterial color="black" />
</mesh>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 18:57:42