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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 10:36:01