Vanilla的三个JS与三纤维代码之间的差异,无法弄清楚什么是不同的

发布于 2025-01-20 02:39:44 字数 4168 浏览 1 评论 0原文

以下代码工作得很好,并使用设置的所有属性(即颜色、uvs、法线和顶点)渲染几何图形。

import * as THREE from "three";
const { useEffect } = require("react");

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});

  const fov = 150;
  const aspect = 2;
  const near = 0.1;
  const far = 100;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.z = 5;

  const scene = new THREE.Scene();

  const color = 0xFFFFFF;
  const intensity = 1;
  const light = new THREE.DirectionalLight(color, intensity);
  light.position.set(-1, 2, 4);
  scene.add(light);

  const positions = [...somepoints];
  const normals = [...somepoints];
  const uvs = [...somepoints];
  const colours = [...somepoints];

  const geometry = new THREE.BufferGeometry();
  const positionNumComponents = 3;
  const normalNumComponents = 3;
  const uvNumComponents = 2;
  const colorComp = 4;
  geometry.setAttribute(
      'position',
      new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
  geometry.setAttribute(
      'normal',
      new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
  geometry.setAttribute(
      'uv',
      new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
        geometry.setAttribute(
      'color',
      new THREE.BufferAttribute(new Float32Array(colours), colorComp));


  const material = new THREE.MeshPhongMaterial({color: 0x88FF88});

  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  function render(time) {
    renderer.render(scene, camera);
  }

  requestAnimationFrame(render);
}

const App = () => {

  useEffect(() => {
    main();
  });

  return (
    <canvas id="c"></canvas>
  )
}

export default App;

但是,如果我尝试使用 React 组件运行它,它不会显示任何内容,并且出现以下错误 235 [.WebGL-0x38089eaa00] GL_INVALID_OPERATION: Vertex buffer is not big enough for the draw call:

I认为问题可能出在 requestAnimationFrame 上,但在上面的代码中它甚至没有对场景的对象执行任何计算。它只是调用 renderer.render 来反应三纤维,对吧?

import { Canvas } from '@react-three/fiber'
import * as THREE from "three";

const App = () => {

  const positions = [...somepoints];
  const normals = [...somepoints];
  const uvs = [...somepoints];
  const colours = [...somepoints];

    return (
        <Canvas>
          <perspectiveCamera
            fov={150}
            aspect={2}
            position={[0,0,5]}
            near={0.1}
            far={100}
            />
            <directionalLight
              color={0xFFFFFF}
              intensity={1.5}
              position={[-1, 2, 4]}
            />
            <mesh>
              <bufferGeometry attach="geometry">
                <bufferAttribute
                  attachObject={["attributes", "position"]}
                  count={positions.length / 3}
                  itemSize={3}
                  array={positions}
                  normalized={true}
                />
                <bufferAttribute
                  attachObject={["attributes", "normal"]}
                  count={normals.length / 3}
                  itemSize={3}
                  array={normals}
                  normalized={true}
                />
                <bufferAttribute
                  attachObject={["attributes", "color"]}
                  count={colours.length / 4}
                  itemSize={4}
                  array={colours}
                  normalized={true}
                />
                <bufferAttribute
                  attachObject={["attributes", "uv"]}
                  count={uvs.length / 2}
                  itemSize={2}
                  array={uvs}
                  normalized={true}
                />
              </bufferGeometry>
              <meshPhongMaterial attach="material" color={0x88FF88} />
            </mesh>
        </Canvas>
      )
  };

  export default App;

任何帮助将不胜感激!谢谢你!

编辑: 这里的问题在于反应代码。由于缓冲区属性要求所有数组均为 new Float32Array([...somepoints])。将位置、uv、法线和颜色更改为 float32 数组类型后,一切正常。

Following code works just fine and renders the geometry with all the attributes set i.e. color, uvs, normal and vertices.

import * as THREE from "three";
const { useEffect } = require("react");

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({canvas});

  const fov = 150;
  const aspect = 2;
  const near = 0.1;
  const far = 100;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.z = 5;

  const scene = new THREE.Scene();

  const color = 0xFFFFFF;
  const intensity = 1;
  const light = new THREE.DirectionalLight(color, intensity);
  light.position.set(-1, 2, 4);
  scene.add(light);

  const positions = [...somepoints];
  const normals = [...somepoints];
  const uvs = [...somepoints];
  const colours = [...somepoints];

  const geometry = new THREE.BufferGeometry();
  const positionNumComponents = 3;
  const normalNumComponents = 3;
  const uvNumComponents = 2;
  const colorComp = 4;
  geometry.setAttribute(
      'position',
      new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents));
  geometry.setAttribute(
      'normal',
      new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents));
  geometry.setAttribute(
      'uv',
      new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents));
        geometry.setAttribute(
      'color',
      new THREE.BufferAttribute(new Float32Array(colours), colorComp));


  const material = new THREE.MeshPhongMaterial({color: 0x88FF88});

  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  function render(time) {
    renderer.render(scene, camera);
  }

  requestAnimationFrame(render);
}

const App = () => {

  useEffect(() => {
    main();
  });

  return (
    <canvas id="c"></canvas>
  )
}

export default App;

However if I try to run it using react components it doesn't show anything and I get the following error 235 [.WebGL-0x38089eaa00] GL_INVALID_OPERATION: Vertex buffer is not big enough for the draw call:

I think that the problem might be with requestAnimationFrame but in above code it doesn't even perform any computation on the scene's object. It just calls renderer.render which react three fiber takes care off, right?

import { Canvas } from '@react-three/fiber'
import * as THREE from "three";

const App = () => {

  const positions = [...somepoints];
  const normals = [...somepoints];
  const uvs = [...somepoints];
  const colours = [...somepoints];

    return (
        <Canvas>
          <perspectiveCamera
            fov={150}
            aspect={2}
            position={[0,0,5]}
            near={0.1}
            far={100}
            />
            <directionalLight
              color={0xFFFFFF}
              intensity={1.5}
              position={[-1, 2, 4]}
            />
            <mesh>
              <bufferGeometry attach="geometry">
                <bufferAttribute
                  attachObject={["attributes", "position"]}
                  count={positions.length / 3}
                  itemSize={3}
                  array={positions}
                  normalized={true}
                />
                <bufferAttribute
                  attachObject={["attributes", "normal"]}
                  count={normals.length / 3}
                  itemSize={3}
                  array={normals}
                  normalized={true}
                />
                <bufferAttribute
                  attachObject={["attributes", "color"]}
                  count={colours.length / 4}
                  itemSize={4}
                  array={colours}
                  normalized={true}
                />
                <bufferAttribute
                  attachObject={["attributes", "uv"]}
                  count={uvs.length / 2}
                  itemSize={2}
                  array={uvs}
                  normalized={true}
                />
              </bufferGeometry>
              <meshPhongMaterial attach="material" color={0x88FF88} />
            </mesh>
        </Canvas>
      )
  };

  export default App;

Any Help will be greatly appreciated! Thank you!

EDIT:
The issue here was with the react code. As buffer attributes requires all the arrays to be new Float32Array([...somepoints]). After changing positions, uvs, normal and colours to float32 array type everything worked fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文