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

