three.js에서 두께를 갖는 라인

OpenGL이나 이를 기반으로 하는 WebGL에서 3D 그래픽에서 두께를 갖는 라인을 표현하기 위해서는 원하는 만큼의 두께를 표현하기 위한 볼륨을 갖는 매시를 구성해야 합니다. 3D 그래픽에서는 기본적으로 라인을 오직 1 픽셀만큼의 두께로 표현할 수 있다는 제약이 있기 때문입니다. 사실 이런 제약은 OpenGL의 제약은 아니고 이를 구현하는 쪽에서의 표준을 충족하지 못했다고 보는게 맞습니다. 원래 OpenGL은 라인에 대해서도 두께를 지정할 수 있고 이에 맞게 라인을 표현해야한다라는 표준을 정했지만 이 표준을 구현하는 쪽에서 이를 구현하지 않았기 때문입니다.

three.js에서도 라인을 표현할때 아무리 두께에 대한 값을 설정해줘도 항상 1 pixel로 표현됩니다. 다행히도 three.js는 두께를 갖는 라인을 표현하기 위해 충분히 검증된 기능을 Line2라는 확장 Addon을 제공합니다. 이 Line2를 사용하면 원하는 두께를 갖는 라인을 표현할 수 있습니다.

이 Line2를 이용하기 위해 다음과 같은 import문이 필요합니다.

import { ..., Line2, LineMaterial, LineGeometry, GeometryUtils } from "three/addons/Addons.js"

그리고 원하는 형태의 라인의 좌표와 색상을 통해 라인을 생성합니다.

_setupModel() {
  const positions = [];
  const colors = [];
  const points = GeometryUtils.hilbert3D(
    new THREE.Vector3(0, 0, 0), 20.0, 1, 0, 1, 2, 3, 4, 5, 6, 7);
  const spline = new THREE.CatmullRomCurve3(points);
  const divisions = Math.round(3 * points.length);
  const point = new THREE.Vector3();
  const color = new THREE.Color();

  for (let i = 0, l = divisions; i < l; i++) {
    const t = i / l;
    spline.getPoint(t, point);
    positions.push(point.x, point.y, point.z);
    color.setHSL(t, 1, 0.5, THREE.SRGBColorSpace);
    colors.push(color.r, color.g, color.b);
  }

  const geometry = new LineGeometry();
  geometry.setPositions(positions);
  geometry.setColors(colors);

  const matLine = new LineMaterial({
    // wireframe: true,
    // color: 0xffffff,
    vertexColors: true,

    // worldUnits: false,
    linewidth: 10, // worldUnits이 false일 경우 pixel 단위

    // alphaToCoverage: true,

    // dashed: true,
    // dashSize: 3,
    // gapSize: 1,
    // dashScale: 1,
  });

  const line = new Line2(geometry, matLine);
  line.computeLineDistances();
  line.scale.set(1, 1, 1);
  this._scene.add(line);
}

결과는 다음과 같습니다.

위의 결과는 단순히 선으로 보이지만 사실 매시입니다. 코드 중 LineMaterial에 wireframe을 true로 설정하면 다음처럼 면으로 구성된 매시라는 점과 항상 카메라를 향하도록(빌보드) 설정되어 있다느 것을 알 수 있습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다