react-three-fiber自定义BufferGeometry生成normals实现阴影的方法
解决方案
自定义BufferGeometry默认不会自动生成顶点法线,你可以通过useLayoutEffect在几何实例挂载完成后,调用Three.js内置的computeVertexNormals()方法自动生成适配的法线,即可正常支持光照、阴影和材质反射效果。useLayoutEffect会在浏览器绘制内容前同步执行,能避免法线加载滞后导致的材质闪烁问题。
修改后的完整代码如下:
import { useRef, useLayoutEffect } from 'react' import * as THREE from 'three' const CustomTriangle = ({ point1, point2, point3, position, color }) => { const mesh = useRef<THREE.Mesh>(null!); const vertices = new Float32Array( [ point1.x, point1.y, point1.z, point2.x, point2.y, point2.z, point3.x, point3.y, point3.z, ] ); // 新增法线计算逻辑 useLayoutEffect(() => { if (!mesh.current) return const geometry = mesh.current.geometry as THREE.BufferGeometry // 自动计算顶点法线 geometry.computeVertexNormals() // 标记法线属性需要更新到GPU,否则计算结果不会生效 geometry.attributes.normal.needsUpdate = true }, [vertices]) // 顶点变更时自动重新计算法线,如果顶点是静态的可以改为空数组 return ( <mesh ref={mesh} position={[position.x, position.y, position.z]} castShadow // 可选:需要投射阴影可添加 receiveShadow // 可选:需要接收阴影可添加 > <bufferGeometry attach="geometry"> <bufferAttribute attachObject={["attributes", "position"]} array={vertices} count={vertices.length / 3} itemSize={3} /> </bufferGeometry> <meshPhongMaterial color={color} side={THREE.DoubleSide} /> </mesh> ); }
如果有特殊的法线自定义需求,也可以手动构造normal对应的BufferAttribute传入几何属性,不需要调用自动计算方法。
内容的提问来源于stack exchange,提问作者Timmotoo
相关产品推荐
相关产品推荐

