在Three.js中把一张图片变成点云的方法

问题描述 投票:0回答:1

我想把一张图片变成点云,并根据颜色值偏移Z的位置。到目前为止,我已经

  1. 加载了一张图片,加载后
  2. 建立一个几何体,并将图像颜色存储在几何体中。
  3. 创建一个PointsMaterial,并建立一个THREE.Points。
  4. 添加到场景

但是,结果看起来和输入的图像完全不一样。我缺少了一些东西,但不确定是什么。

在显示图像的点云版本方面,我缺少了什么?

举个例子。https:/img2pointcloud.glitch.me。

<html>
  <head>
    <script src="https://threejs.org/build/three.js"></script>
  </head>
  <body style="margin:0">
    <script>
      var container, renderer, points;

      var scene = new THREE.Scene();

      var camera = new THREE.PerspectiveCamera(
        45,
        window.innerWidth / window.innerHeight,
        1,
        10000
      );
      camera.position.set(0, 0, 1000);

      var renderer = new THREE.WebGLRenderer();
      renderer.setPixelRatio(window.devicePixelRatio);
      renderer.setSize(window.innerWidth, window.innerHeight);

      document.body.appendChild(renderer.domElement);

      var imgSrc =
        "https://cdn.glitch.com/c3afecd9-365c-424f-a08e-90fce02a151a%2Fimg.jpeg?v=1588102020636";
      var img = new Image();
      var width = 1920 / 4;
      var height = 1080 / 4;
      img.crossOrigin = "anonymous";
      img.src = imgSrc;

      img.onload = function() {
        var canvas = document.createElement("canvas");
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0);
        var imageData = ctx.getImageData(0, 0, width, height);
        var data = imageData.data;
        document.body.appendChild(canvas);
        createPointCloud(imageData);
      };

      function createPointCloud(imageData) {

        var geometry = new THREE.BufferGeometry();
        var positions = [];

        for (var x = 0; x < height; x++) {
          for (var z = 0; z < width; z++) {
            positions.push(x, z, x);
          }
        }

        var color = new THREE.Color();
        var colors = [];

        for (let i = 0; i < imageData.data.length; i += 4) {
          const r = imageData.data[i + 0];
          const g = imageData.data[i + 1];
          const b = imageData.data[i + 2];
          const a = imageData.data[i + 3];
          color.setRGB(r, g, b);
          colors.push(color.r, color.b, color.c);
        }

        geometry.setAttribute(
          "position",
          new THREE.Float32BufferAttribute(positions, 3)
        );
        geometry.setAttribute(
          "color",
          new THREE.Float32BufferAttribute(colors, 3)
        );

        geometry.computeBoundingSphere();

        var material = new THREE.PointsMaterial({
          size: 0.1,
          vertexColors: true
        });

        points = new THREE.Points(geometry, material);
        scene.add(points);

        animate();
      }

      function animate() {
        requestAnimationFrame(animate);
        render();
      }

      function render() {
        renderer.render(scene, camera);
      }
    </script>
  </body>
</html>


  [1]: https://i.stack.imgur.com/9etFB.png
  [2]: https://i.stack.imgur.com/HKM7m.png
three.js point-clouds
1个回答
2
投票

另一种方法是修改着色器的 THREE.PointsMaterial():

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(-75, 0, 1);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

new THREE.TextureLoader().load("https://cdn.glitch.com/c3afecd9-365c-424f-a08e-90fce02a151a%2Fimg.jpeg?v=1588102020636", tex => {

    let img = tex.image;
    console.log(img.width, img.height);

    let g = new THREE.PlaneBufferGeometry(Math.floor(img.width / 4), Math.floor(img.height / 4), img.width, img.height);
    let m = new THREE.PointsMaterial({
      map: tex,
      size: 0.1
    });
    m.onBeforeCompile = shader => {
      shader.vertexShader = `
        varying vec2 vUv;
        ${shader.vertexShader}
      `;
      shader.vertexShader = shader.vertexShader.replace(
        `#include <color_vertex>`,
        `
        vUv = uv;
        #include <color_vertex>`
      );
      shader.fragmentShader = `
        varying vec2 vUv;
        ${shader.fragmentShader}
      `;
      shader.fragmentShader = shader.fragmentShader.replace(
        `#include <map_particle_fragment>`,
        `vec4 mapTexel = texture2D( map, vUv );
	        diffuseColor = mapTexel;
          `
      );
      console.log(shader.vertexShader);

    };
    let p = new THREE.Points(g, m);
    scene.add(p);

});

renderer.setAnimationLoop(() => {
  renderer.render(scene, camera)
});
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

0
投票

我的代码里有一个很大的错别字,不知为什么,它说 colors.push(color.r, color.b, color.c); 而不是 colors.push(color.r, color.g, color.b); 注意rbc与rgb)。

现在整理好了,谢谢你的评论,让我看到了。

© www.soinside.com 2019 - 2024. All rights reserved.