Three.js实例化技术:高效渲染数千3D对象

Three.js实例化技术:同时渲染多个3D对象

学习如何使用React Three Fiber中的实例化技术高效渲染数千个3D对象,正如性能优化的basement.studio网站所展示的那样。

引言

实例化是一种性能优化技术,允许你同时渲染共享相同几何体和材质的多个对象。如果需要渲染森林场景,你会需要大量的树木、岩石和草地。如果它们共享相同的基础网格和材质,你就可以通过单次绘制调用渲染所有对象。

绘制调用是CPU向GPU发出的绘制指令,比如绘制一个网格。每个独特的几何体或材质通常需要自己的调用。过多的绘制调用会损害性能。实例化通过将多个副本批量处理为一个来减少这种情况。

基础实例化

让我们从一个传统方式渲染一千个方块的例子开始:

javascript 复制代码
const boxCount = 1000

function Scene() {
  return (
    <>
      {Array.from({ length: boxCount }).map((_, index) => (
        <mesh
          key={index}
          position={getRandomPosition()}
          scale={getRandomScale()}
        >
          <boxGeometry />
          <meshBasicMaterial color={getRandomColor()} />
        </mesh>
      ))}
    </>
  )
}

查看示例 | 源代码

如果添加性能监视器,会发现"calls"数量与boxCount匹配。

使用drei/instances可以快速实现实例化:

javascript 复制代码
import { Instance, Instances } from "@react-three/drei"

const boxCount = 1000

function Scene() {
  return (
    <Instances limit={boxCount}>
      <boxGeometry />
      <meshBasicMaterial />
      {Array.from({ length: boxCount }).map((_, index) => (
        <Instance
          key={index}
          position={getRandomPosition()}
          scale={getRandomScale()}
          color={getRandomColor()}
        />
      ))}
    </Instances>
  )
}

现在"calls"减少到1,即使我们显示了一千个方块。

多组实例

要渲染森林场景,可能需要不同的实例组:

javascript 复制代码
import { createInstances } from "@react-three/drei"

const boxCount = 1000
const sphereCount = 1000

const [CubeInstances, Cube] = createInstances()
const [SphereInstances, Sphere] = createInstances()

function InstancesProvider({ children }: { children: React.ReactNode }) {
  return (
    <CubeInstances limit={boxCount}>
      <boxGeometry />
      <meshBasicMaterial />
      <SphereInstances limit={sphereCount}>
        <sphereGeometry />
        <meshBasicMaterial />
        {children}
      </SphereInstances>
    </CubeInstances>
  )
}

自定义着色器实例

要为自定义着色器添加实例支持:

javascript 复制代码
const baseMaterial = new THREE.RawShaderMaterial({
  vertexShader: /*glsl*/ `
    attribute vec3 position;
    attribute vec3 instanceColor;
    attribute vec3 normal;
    attribute vec2 uv;
    uniform mat4 modelMatrix;
    uniform mat4 viewMatrix;
    uniform mat4 projectionMatrix;
    attribute mat4 instanceMatrix;

    uniform float uTime;
    uniform float uAmplitude;

    vec3 movement(vec3 position) {
      vec3 pos = position;
      pos.x += sin(position.y + uTime) * uAmplitude;
      return pos;
    }

    void main() {
      vec3 blobShift = movement(position);
      vec4 modelPosition = modelMatrix * instanceMatrix * vec4(blobShift, 1.0);
      vec4 viewPosition = viewMatrix * modelPosition;
      vec4 projectionPosition = projectionMatrix * viewPosition;
      gl_Position = projectionPosition;
    }
  `,
  fragmentShader: /*glsl*/ `
    void main() {
      gl_FragColor = vec4(1, 0, 0, 1);
    }
  `
})

创建森林场景

使用实例化网格创建森林场景:

javascript 复制代码
const [TreeInstances, Tree] = createInstances()
const treeCount = 1000

function Scene() {
  const { scene, nodes } = useGLTF(
    "/stylized_pine_tree_tree.glb"
  ) as unknown as TreeGltf

  return (
    <group>
      <TreeInstances
        limit={treeCount}
        scale={0.02}
        geometry={nodes.tree_low001_StylizedTree_0.geometry}
        material={nodes.tree_low001_StylizedTree_0.material}
      >
        {Array.from({ length: treeCount }).map((_, index) => (
          <Tree key={index} position={getRandomPosition()} />
        ))}
      </TreeInstances>
    </group>
  )
}

整个森林仅用三次绘制调用渲染:天空盒一次,地面平面一次,所有树木一次。

延伸阅读

  • 批处理网格:允许同时渲染不同几何体
  • 骨骼动画:当前不支持实例化
  • 变形动画:实例支持但批处理网格不支持
相关推荐
陈天伟教授几秒前
人工智能应用- 语言处理:03.机器翻译:规则方法
人工智能·自然语言处理·机器翻译
Σίσυφος190010 分钟前
PCL 姿态估计 RANSAC + SVD(基于特征匹配)
人工智能·机器学习
Warren2Lynch11 分钟前
C4 vs UML:从入门到结合使用的完整指南(含 Visual Paradigm AI 实操)
人工智能·机器学习·uml
Ryan老房16 分钟前
智能家居AI-家庭场景物体识别标注实战
人工智能·yolo·目标检测·计算机视觉·ai·智能家居
2401_8362358616 分钟前
财务报表识别产品:从“数据搬运”到“智能决策”的技术革命
人工智能·科技·深度学习·ocr·生活
明明如月学长35 分钟前
全网最火的 Agent Skills 都在这了!这 7 个宝藏市场建议收藏
人工智能
猫头虎36 分钟前
如何使用Docker部署OpenClaw汉化中文版?
运维·人工智能·docker·容器·langchain·开源·aigc
njsgcs38 分钟前
输入图片,点击按钮,返回下一个state的图片,llm给标签,循环,能训练出按钮对应的标签吗
人工智能
Aric_Jones42 分钟前
如何在网站中接入 AI 智能助手
人工智能