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로 설정하면 다음처럼 면으로 구성된 매시라는 점과 항상 카메라를 향하도록(빌보드) 설정되어 있다느 것을 알 수 있습니다.