首页 > 解决方案 > 在 React-Three-Fiber 中渲染索引缓冲区几何图形

问题描述

我目前正在尝试从https://threejs.org/examples/?q=buffer#webgl_buffergeometry_indexed在 React-Three-Fiber 环境中获取示例。

我目前在我的代码中看到了几个问题。

首先,特别是在 Chrome 中,我反复收到以下警告:

[.WebGL-0x26d30384f700] GL_INVALID_ENUM: Enum is not currently supported.

此外,我目前看不到任何颜色应用于网格。

这是我到目前为止工作的代码:

import React, { useMemo } from "react";
import { Canvas } from "@react-three/fiber";
import { DoubleSide } from "three";

const App = () => {
  const size = 20;
  const segments = 10;

  const [colors, normals, positions] = useMemo(() => {
    const colorsArr = [];
    const normalsArr = [];
    const positionsArr = [];

    const halfSize = size / 2;
    const segmentSize = size / segments;

    // generate vertices, normals and color data for a simple grid geometry

    for (let i = 0; i <= segments; i++) {
      const y = i * segmentSize - halfSize;

      for (let j = 0; j <= segments; j++) {
        const x = j * segmentSize - halfSize;

        positionsArr.push(x, -y, 0);
        normalsArr.push(0, 0, 1);

        const r = x / size + 0.5;
        const g = y / size + 0.5;

        colorsArr.push(r, g, 1);
      }
    }

    return [colorsArr, normalsArr, positionsArr];
  }, []);

  const indices = useMemo(() => {
    const indicesArr = [];

    // generate indices (data for element array buffer)

    for (let i = 0; i < segments; i++) {
      for (let j = 0; j < segments; j++) {
        const a = i * (segments + 1) + (j + 1);
        const b = i * (segments + 1) + j;
        const c = (i + 1) * (segments + 1) + j;
        const d = (i + 1) * (segments + 1) + (j + 1);

        // generate two faces (triangles) per iteration

        indicesArr.push(a, b, d); // face one
        indicesArr.push(b, c, d); // face two
      }
    }

    return indicesArr;
  }, []);

  return (
    <Canvas
      camera={{
        fov: 27,
        near: 1,
        far: 3500
      }}
      position-z={64}
    >
      <color attach="background" args={["#050505"]} />
      <mesh>
        <bufferGeometry attach="geometry">
          <bufferAttribute
            array={indices}
            attach="index"
            count={indices.length}
            itemSize={1}
          />
          <bufferAttribute
            attachObject={["attributes", "position"]}
            count={positions.length / 3}
            array={positions}
            itemSize={3}
          />
          <bufferAttribute
            attachObject={["attributes", "color"]}
            count={colors.length / 3}
            array={colors}
            itemSize={3}
          />
          <bufferAttribute
            attachObject={["attributes", "normal"]}
            count={normals.length / 3}
            array={normals}
            itemSize={3}
          />
        </bufferGeometry>
        <meshPhongMaterial attach="material" side={DoubleSide} vertexColors />
      </mesh>
      <hemisphereLight />
    </Canvas>
  );
};

export default App;

Three.js 的示例代码:https ://github.com/mrdoob/three.js/blob/master/examples/webgl_buffergeometry_indexed.html

标签: javascriptreactjsthree.jsreact-three-fiber

解决方案


终于解决了这个问题。主要问题是我需要将位置、颜色和法线数组转换为 Float32Array() 并将索引转换为 Uint32Array()。

因此,例如,在索引数组的情况下,以下内容对我有用:

const indices = useMemo(() => {
    const indicesArr = [];

    // generate indices (data for element array buffer)

    for (let i = 0; i < segments; i++) {
      for (let j = 0; j < segments; j++) {
        const a = i * (segments + 1) + (j + 1);
        const b = i * (segments + 1) + j;
        const c = (i + 1) * (segments + 1) + j;
        const d = (i + 1) * (segments + 1) + (j + 1);

        // generate two faces (triangles) per iteration

        indicesArr.push(a, b, d); // face one
        indicesArr.push(b, c, d); // face two
      }
    }

    return new Uint32Array(indicesArr);
  }, []);

推荐阅读