You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
337 lines
25 KiB
337 lines
25 KiB
<!DOCTYPE html><html lang="ko"><head>
|
|
<meta charset="utf-8">
|
|
<title>원시 모델(primitives)</title>
|
|
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="twitter:site" content="@threejs">
|
|
<meta name="twitter:title" content="Three.js – 원시 모델(primitives)">
|
|
<meta property="og:image" content="https://threejs.org/files/share.png">
|
|
<link rel="shortcut icon" href="/files/favicon_white.ico" media="(prefers-color-scheme: dark)">
|
|
<link rel="shortcut icon" href="/files/favicon.ico" media="(prefers-color-scheme: light)">
|
|
|
|
<link rel="stylesheet" href="/manual/resources/lesson.css">
|
|
<link rel="stylesheet" href="/manual/resources/lang.css">
|
|
<!-- Import maps polyfill -->
|
|
<!-- Remove this when import maps will be widely supported -->
|
|
<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
|
|
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"three": "../../build/three.module.js"
|
|
}
|
|
}
|
|
</script>
|
|
<link rel="stylesheet" href="/manual/ko/lang.css">
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="lesson-title">
|
|
<h1>원시 모델(primitives)</h1>
|
|
</div>
|
|
<div class="lesson">
|
|
<div class="lesson-main">
|
|
<p>※ 이 글은 Three.js의 튜토리얼 시리즈로서,
|
|
먼저 <a href="fundamentals.html">Three.js의 기본 구조에 관한 글</a>을
|
|
읽고 오길 권장합니다.</p>
|
|
<p>Three.js에는 다양한 원시 모델이 있습니다. 먼저 Three.js의 원시 모델이란,
|
|
주로 런타임에서 다양한 인자들로 정의한 3D 모양을 의미합니다.</p>
|
|
<p>원시 모델은 주로 구체로 공 모양을 만든다거나, 수많은 육면체를 모아
|
|
3D 그래프를 만드는 데 사용합니다. 또한 3D에 입문한다거나, 모의
|
|
프로젝트를 만들 때 사용하기도 하죠. 물론 대부분의 3D 앱은 그래픽
|
|
전문가가 <a href="https://blender.org">블렌더(Blender)</a>, <a href="https://www.autodesk.com/products/maya/">마야(Maya)</a>,
|
|
<a href="https://www.maxon.net/en-us/products/cinema-4d/">시네마 4D(Cinema 4D)</a> 등으로
|
|
만든 그래픽 모델을 사용합니다. Three.js도 이런 외부 모델을 불러올 수
|
|
있지만, 이건 나중에 알아보기로 하고 일단 이 글에서는 사용 가능한 원시
|
|
모델에 무엇이 있는지 살펴보도록 하죠.</p>
|
|
<p>앞으로 소개할 원시 모델들은 대부분 기본값이 있으므로 필요에 따라
|
|
인자를 넣어주면 됩니다.</p>
|
|
<div id="Diagram-BoxGeometry" data-primitive="BoxGeometry">육면체(Box)</div>
|
|
<div id="Diagram-CircleGeometry" data-primitive="CircleGeometry">원(flat circle)</div>
|
|
<div id="Diagram-ConeGeometry" data-primitive="ConeGeometry">원뿔(Cone)</div>
|
|
<div id="Diagram-CylinderGeometry" data-primitive="CylinderGeometry">원통(Cylinder)</div>
|
|
<div id="Diagram-DodecahedronGeometry" data-primitive="DodecahedronGeometry">십이면체(Dodecahedron)</div>
|
|
<div id="Diagram-ExtrudeGeometry" data-primitive="ExtrudeGeometry">사각(bevel)을 주어 깍아낸(extruded) 2D 모양입니다.
|
|
아래에서는 하트 모양으로 깍아냈죠. <code class="notranslate" translate="no">ExtrudedGeometry</code>는 나중에 설명할
|
|
<a href="/docs/#api/ko/geometries/TextGeometry"><code class="notranslate" translate="no">TextGeometry</code></a>과 <a href="/docs/#api/ko/geometries/TextGeometry"><code class="notranslate" translate="no">TextGeometry</code></a>의 기초 모델입니다.</div>
|
|
<div id="Diagram-IcosahedronGeometry" data-primitive="IcosahedronGeometry">이십면체(Icosahedron)</div>
|
|
<div id="Diagram-LatheGeometry" data-primitive="LatheGeometry">선(line)을 회전시켜 만든 모양입니다. 램프, 볼링핀, 초, 초 받침, 와인잔, 유리잔 등이 있죠(물레로 도자기를 만드는 것처럼. 역주). 2D 형태를 점(point, Vector2 클래스를 말함. 역주)을 사용해 지정하고, Three.js에게 축을 따라 세분값(아래 예제의 <code class="notranslate" translate="no">segments</code> 값. 역주)과 회전값(아래 예제의 <code class="notranslate" translate="no">phiLength</code> 값. 역주)을 지정해주면 됩니다.</div>
|
|
<div id="Diagram-OctahedronGeometry" data-primitive="OctahedronGeometry">팔면체(Octahedron)</div>
|
|
<div id="Diagram-ParametricGeometry" data-primitive="ParametricGeometry">2D 격자값(격자 하나의 벡터값)을 받아 3D 값을 반환하는 함수를 인자로 전달하여 면을 만듭니다.</div>
|
|
<div id="Diagram-PlaneGeometry" data-primitive="PlaneGeometry">2D 평면(2D plane)</div>
|
|
<div id="Diagram-PolyhedronGeometry" data-primitive="PolyhedronGeometry">다면체입니다. 주어진 3D 점들(아래 <code class="notranslate" translate="no">verticesOfCube</code>. 역주)을 중심으로 삼각형(아래 <code class="notranslate" translate="no">indicesOfFaces</code>. 역주)을 구 형태로 잇습니다.</div>
|
|
<div id="Diagram-RingGeometry" data-primitive="RingGeometry">중앙이 빈 2D 디스크(disc)입니다.</div>
|
|
<div id="Diagram-ShapeGeometry" data-primitive="ShapeGeometry">삼각형으로 이루어진 2D 윤곽선입니다.</div>
|
|
<div id="Diagram-SphereGeometry" data-primitive="SphereGeometry">구(Sphere)</div>
|
|
<div id="Diagram-TetrahedronGeometry" data-primitive="TetrahedronGeometry">사면체(tetrahedron)</div>
|
|
<div id="Diagram-TextGeometry" data-primitive="TextGeometry">3D 폰트와 문자열로 만든 3D 텍스트입니다.</div>
|
|
<div id="Diagram-TorusGeometry" data-primitive="TorusGeometry">원환체(torus), 도넛(donut)</div>
|
|
<div id="Diagram-TorusKnotGeometry" data-primitive="TorusKnotGeometry">원환체 매듭(torus knot)</div>
|
|
<div id="Diagram-TubeGeometry" data-primitive="TubeGeometry">패스를 따라 이어진 원입니다.</div>
|
|
<div id="Diagram-EdgesGeometry" data-primitive="EdgesGeometry">다른 <code class="notranslate" translate="no">geometry</code>를 받는 헬퍼 객체로, 각 면 사이의 각이 일정 값 이상일 때만 모서리를 표시합니다. 상단의 육면체 예제를 보면 육면체를 만드는 삼각형이 표면에 전부 표시된 것을 확인할 수 있는데, <a href="/docs/#api/ko/geometries/EdgesGeometry"><code class="notranslate" translate="no">EdgesGeometry</code></a>를 사용할 경우 표면에 있던 선들이 전부 사라집니다. 아래 예제의 <code class="notranslate" translate="no">thresholdAngle</code> 값을 조정해 해당 값 이하인 모서리가 전부 사라지는 것을 확인해보세요.</div>
|
|
<div id="Diagram-WireframeGeometry" data-primitive="WireframeGeometry">매개변수로 받은 <code class="notranslate" translate="no">geometry</code>의 모서리 하나당 하나의 선분(2개의 점)을 가진 <code class="notranslate" translate="no">geometry</code>를 생성합니다. WebGl은 보통 선분 하나당 2개의 점을 필요로 합니다. 때문에 이 모델을 사용하지 않는 경우, 모서리가 없어지거나 추가되는 현상이 발생할 수 있습니다. 예를 들어 2D 삼각형을 만드는 경우, 대부분 3개의 점을 이용해 삼각형을 만들려고 할 겁니다. <code class="notranslate" translate="no">wireframe: true</code>라는 옵션이 있기는 하나, 이를 이용해 삼각형을 만들면 (WebGl은 삼각형을 만들 때 6개의 점을 요구하므로. 역주) 출력되는 건 선 하나 뿐일 겁니다. 삼각형 <code class="notranslate" translate="no">geometry</code>를 <a href="/docs/#api/ko/geometries/WireframeGeometry"><code class="notranslate" translate="no">WireframeGeometry</code></a>에 넘겨주면 6개의 점과 3개의 선분을 가진 새 <code class="notranslate" translate="no">geometry</code>를 생성합니다.</div>
|
|
|
|
<p><a href="custom-buffergeometry.html">커스텀 geometry를 만드는 법</a>에 대해서는
|
|
나중에 자세히 다룰 것이므로, 지금은 각 원시 모델로 예제를 만들어 보겠습니다.
|
|
예제 코드는 <a href="responsive.html">지난 글</a>에서 썼던 예제를 쓸 거에요.</p>
|
|
<p>먼저 배경색을 지정합니다.</p>
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
|
|
+scene.background = new THREE.Color(0xAAAAAA);
|
|
</pre>
|
|
<p>이는 옅은 회색으로 배경을 칠하라는 의미이죠.</p>
|
|
<p>모든 물체를 봐야 하므로 카메라도 수정합니다.</p>
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const fov = 75;
|
|
+const fov = 40;
|
|
const aspect = 2; // the canvas default
|
|
const near = 0.1;
|
|
-const far = 5;
|
|
+const far = 1000;
|
|
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
|
|
-camera.position.z = 2;
|
|
+camera.position.z = 120;
|
|
</pre>
|
|
<p>다음으로 x, y 좌표와 <a href="/docs/#api/ko/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a>를 매개변수로 받아 씬에 추가하는 <code class="notranslate" translate="no">addObject</code>
|
|
함수를 만듭니다.</p>
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const objects = [];
|
|
const spread = 15;
|
|
|
|
function addObject(x, y, obj) {
|
|
obj.position.x = x * spread;
|
|
obj.position.y = y * spread;
|
|
|
|
scene.add(obj);
|
|
objects.push(obj);
|
|
}
|
|
</pre>
|
|
<p>물체를 무작위로 채색하는 함수도 하나 만듭니다. hue, 채도, 명도로
|
|
색을 지정하는 <a href="/docs/#api/ko/math/Color"><code class="notranslate" translate="no">Color</code></a>의 기능을 활용할 거에요.</p>
|
|
<p><code class="notranslate" translate="no">hue</code>는 0부터 1까지의 색상값을 고리 모양으로 배치한 것으로,
|
|
12시는 빨강, 4시는 녹색, 8시는 파랑입니다. <code class="notranslate" translate="no">채도(saturation)</code>
|
|
또한 마찬가지로 0부터 1까지이며, 0은 색이 가장 옅은 것, 1은
|
|
색이 가장 진한 것을 의미합니다. <code class="notranslate" translate="no">명도(luminance)</code>에서 0.0은
|
|
검정, 1.0은 하양으로, 0.5가 가장 색이 가장 풍부합니다. 쉽게
|
|
말해 명도가 0.0에서 0.5로 갈수록 검정에서 <code class="notranslate" translate="no">hue</code>에 가까워지고,
|
|
0.5에서 1.0으로 갈수록 <code class="notranslate" translate="no">hue</code>에서 하양에 가까워지는 것이죠.</p>
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function createMaterial() {
|
|
const material = new THREE.MeshPhongMaterial({
|
|
side: THREE.DoubleSide,
|
|
});
|
|
|
|
const hue = Math.random();
|
|
const saturation = 1;
|
|
const luminance = .5;
|
|
material.color.setHSL(hue, saturation, luminance);
|
|
|
|
return material;
|
|
}
|
|
</pre>
|
|
<p>위 예제에서는 <code class="notranslate" translate="no">material</code>에 <code class="notranslate" translate="no">side: THREE.DoubleSide</code> 옵션을
|
|
지정했습니다. 이는 Three.js에게 삼각형의 양면 모두를 렌더링하라고
|
|
알려주는 것이죠. 구나 정육면체 같은 물체는 보이지 않는 안쪽 면을
|
|
굳이 렌더링할 이유가 없지만, 예제의 경우 <a href="/docs/#api/ko/geometries/PlaneGeometry"><code class="notranslate" translate="no">PlaneGeometry</code></a>나
|
|
<a href="/docs/#api/ko/geometries/ShapeGeometry"><code class="notranslate" translate="no">ShapeGeometry</code></a> 등 안쪽 면이 없는 물체를 만들 것이므로
|
|
<code class="notranslate" translate="no">side: THREE.DoubleSide</code> 옵션을 설정하지 않으면 반대편에서 봤을 때
|
|
물체가 사라진 것처럼 보일 겁니다.</p>
|
|
<p>중요한 건 <code class="notranslate" translate="no">side: THREE.DoubleSide</code> 옵션은 <strong>렌더링 속도에 영향을 줍니다</strong>.
|
|
실제로 사용할 때는 필요한 물체에만 지정하는 게 좋겠지만, 지금은
|
|
물체의 수가 많지 않으므로 일단 넘어가겠습니다.</p>
|
|
<p>다음으로 <code class="notranslate" translate="no">addSolidGeometry</code> 함수를 만듭니다. 이 함수는 매개변수로
|
|
받은 <code class="notranslate" translate="no">geometry</code>와 앞서 만든 <code class="notranslate" translate="no">createMaterial</code> 함수를 사용해
|
|
무작위로 색칠한 물체를 만들고, <code class="notranslate" translate="no">addObject</code> 함수로 씬에 추가합니다.</p>
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function addSolidGeometry(x, y, geometry) {
|
|
const mesh = new THREE.Mesh(geometry, createMaterial());
|
|
addObject(x, y, mesh);
|
|
}
|
|
</pre>
|
|
<p>이제 이를 활용해 주요 원시 모델을 생성할 수 있습니다.
|
|
예를 들어 정육면체를 만든다고 해보죠.</p>
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
|
|
const width = 8;
|
|
const height = 8;
|
|
const depth = 8;
|
|
addSolidGeometry(-2, -2, new THREE.BoxGeometry(width, height, depth));
|
|
}
|
|
</pre>
|
|
<p>아래 코드를 보면 각 <code class="notranslate" translate="no">geometry</code>마다 비슷한 단락으로 이루어진 것을 확인할 수 있습니다.</p>
|
|
<p></p><div translate="no" class="threejs_example_container notranslate">
|
|
<div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/primitives.html"></iframe></div>
|
|
<a class="threejs_center" href="/manual/examples/primitives.html" target="_blank">새 탭에서 보기</a>
|
|
</div>
|
|
|
|
<p></p>
|
|
<p>몇몇 예외가 보일 텐데, 가장 크게 두드러진 것은 아마 <a href="/docs/#api/ko/geometries/TextGeometry"><code class="notranslate" translate="no">TextGeometry</code></a>일 겁니다.
|
|
<a href="/docs/#api/ko/geometries/TextGeometry"><code class="notranslate" translate="no">TextGeometry</code></a>는 텍스트의 <code class="notranslate" translate="no">mesh</code>를 생성하기 위해 3D 폰트 데이터를 필요로 합니다.
|
|
이 데이터는 비동기로 로드되므로, 객체를 생성하기 전에 3D 폰트 데이터가 로드되기를 기다려야
|
|
하죠. 폰트 로드 과정을 프로미스화 하면 이 과정를 더 쉽게 만들 수 있습니다. 먼저 <a href="/docs/#api/ko/loaders/FontLoader"><code class="notranslate" translate="no">FontLoader</code></a>를
|
|
생성하고, Promise를 반환하는 <code class="notranslate" translate="no">loadFont</code> 함수를 만들어 요청을 Promise로 감쌉니다.
|
|
그리고 <code class="notranslate" translate="no">doit</code>이라는 비동기 함수를 만들어 <code class="notranslate" translate="no">await</code> 키워드로 폰트를 로드한 후, <code class="notranslate" translate="no">geometry</code>를
|
|
만들고 <code class="notranslate" translate="no">addObject</code> 함수로 씬에 추가하죠.</p>
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">{
|
|
const loader = new FontLoader();
|
|
// promisify font loading
|
|
function loadFont(url) {
|
|
return new Promise((resolve, reject) => {
|
|
loader.load(url, resolve, undefined, reject);
|
|
});
|
|
}
|
|
|
|
async function doit() {
|
|
const font = await loadFont('resources/threejs/fonts/helvetiker_regular.typeface.json'); /* threejs.org: url */
|
|
const geometry = new TextGeometry('three.js', {
|
|
font: font,
|
|
size: 3.0,
|
|
height: .2,
|
|
curveSegments: 12,
|
|
bevelEnabled: true,
|
|
bevelThickness: 0.15,
|
|
bevelSize: .3,
|
|
bevelSegments: 5,
|
|
});
|
|
const mesh = new THREE.Mesh(geometry, createMaterial());
|
|
geometry.computeBoundingBox();
|
|
geometry.boundingBox.getCenter(mesh.position).multiplyScalar(-1);
|
|
|
|
const parent = new THREE.Object3D();
|
|
parent.add(mesh);
|
|
|
|
addObject(-1, -1, parent);
|
|
}
|
|
doit();
|
|
}
|
|
</pre>
|
|
<p>또 다른 차이점은 Three.js의 텍스트는 기본적으로 중앙을 중심으로 돌지
|
|
않는다는 것입니다. 기본 회전축은 왼쪽 모서리로, 중앙을 중심으로 돌게
|
|
하려면 Three.js에게 <code class="notranslate" translate="no">geometry</code>의 bounding box(경계 좌표)를 계산해
|
|
달라고 요청한 뒤, bounding box의 <code class="notranslate" translate="no">getCenter</code> 메서드에 해당 <code class="notranslate" translate="no">mesh</code>의
|
|
위치값 객체를 넘겨주어야 합니다. 이러면 <code class="notranslate" translate="no">getCenter</code> 메서드는 넘겨받은
|
|
위치값의 중앙 좌표값을 자신의 위치값으로 복사합니다. 그리고 변경된 위치값
|
|
객체를 반환하는데, 이 객체의 <code class="notranslate" translate="no">multiplyScalar(-1)</code> 메서드로 전체 텍스트의
|
|
회전 중심이 텍스트의 중앙에 오도록 조정할 수 있습니다.</p>
|
|
<p>만약 이대로 다른 예제처럼 <code class="notranslate" translate="no">addSolidGeometry</code> 함수를 호출한다면 위치값을
|
|
재할당해버릴 겁니다. 그러니 대신 Three.js의 씬 그래프의 기본 요소(node)인
|
|
<a href="/docs/#api/ko/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a>를 하나 만듭니다(<a href="/docs/#api/ko/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a> 또한 <a href="/docs/#api/ko/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a>의 자식 요소임).
|
|
씬 그래프가 어떻게 작동하는가에 대해서는 <a href="scenegraph.html">다른 글</a>에서 자세히 다룰 것이므로,
|
|
당장은 DOM 요소처럼 자식 요소가 부모 요소를 기반으로 생성된다는
|
|
것만 알아둡시다. <a href="/docs/#api/ko/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a>를 생성해 텍스트를 감싸면 텍스트의 회전 중심은
|
|
유지한 채로 위치값을 얼마든지 조정할 수 있습니다.</p>
|
|
<p>만약 <code class="notranslate" translate="no">addSolidGeometry</code>를 그냥 사용한다면 아래 왼쪽의 예제처럼
|
|
회전축이 아예 빗나가겠죠.</p>
|
|
<p></p><div translate="no" class="threejs_example_container notranslate">
|
|
<div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/primitives-text.html"></iframe></div>
|
|
<a class="threejs_center" href="/manual/examples/primitives-text.html" target="_blank">새 탭에서 보기</a>
|
|
</div>
|
|
|
|
<p></p>
|
|
<p>예제의 왼쪽 텍스트는 회전축이 중앙에서 벗어났지만, 오른쪽 텍스트는
|
|
중앙을 중심으로 회전합니다.</p>
|
|
<p>다른 예외는 2개의 선을 기반으로 한 <a href="/docs/#api/ko/geometries/EdgesGeometry"><code class="notranslate" translate="no">EdgesGeometry</code></a>와 <a href="/docs/#api/ko/geometries/WireframeGeometry"><code class="notranslate" translate="no">WireframeGeometry</code></a>입니다.
|
|
<code class="notranslate" translate="no">addSolidGeometry</code> 함수 대신 아래와 같은 <code class="notranslate" translate="no">addLineGeometry</code> 함수를 호출했죠.</p>
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function addLineGeometry(x, y, geometry) {
|
|
const material = new THREE.LineBasicMaterial({color: 0x000000});
|
|
const mesh = new THREE.LineSegments(geometry, material);
|
|
addObject(x, y, mesh);
|
|
}
|
|
</pre>
|
|
<p>이 함수는 검은 <a href="/docs/#api/ko/materials/LineBasicMaterial"><code class="notranslate" translate="no">LineBasicMaterial</code></a>을 만들고 이를 기반으로 <a href="/docs/#api/ko/objects/LineSegments"><code class="notranslate" translate="no">LineSegments</code></a>를
|
|
만듭니다. <a href="/docs/#api/ko/objects/LineSegments"><code class="notranslate" translate="no">LineSegments</code></a>는 <a href="/docs/#api/ko/objects/Mesh"><code class="notranslate" translate="no">Mesh</code></a>의 자식 객체로, Three.js의 선분(line segments, 선분 하나당 점 2개)
|
|
렌더링을 도와주는 객체입니다.</p>
|
|
<p>원시 모델을 생성할 때 인자는 차이가 있으니 <a href="https://threejs.org/docs/">공식 문서</a>를 참고하시거나,
|
|
각 원시 모델 예시 위에 공식 문서 링크가 있으니 해당 링크를 참고하시기 바랍니다.</p>
|
|
<p>소개하지 않은 클래스 중에 위 패턴으로는 사용하기 어려운 클래스가 있습니다.
|
|
<a href="/docs/#api/ko/materials/PointsMaterial"><code class="notranslate" translate="no">PointsMaterial</code></a>과 <a href="/docs/#api/ko/objects/Points"><code class="notranslate" translate="no">Points</code></a> 클래스인데요. <a href="/docs/#api/ko/objects/Points"><code class="notranslate" translate="no">Points</code></a>는 <code class="notranslate" translate="no">Geometry</code>나 <a href="/docs/#api/ko/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>를
|
|
매개변수로 받는다는 점에서 위 예제의 <a href="/docs/#api/ko/objects/LineSegments"><code class="notranslate" translate="no">LineSegments</code></a>와 비슷하나, 선 대신 각 정점에
|
|
점(point)을 그린다는 점이 다릅니다. 또 점의 크기를 지정하는 <a href="/docs/#api/ko/materials/PointsMaterial#size"><code class="notranslate" translate="no">size</code></a>도
|
|
<a href="/docs/#api/ko/materials/PointsMaterial"><code class="notranslate" translate="no">PointsMaterial</code></a>에 함께 넘겨주어야 하죠.</p>
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const radius = 7;
|
|
const widthSegments = 12;
|
|
const heightSegments = 8;
|
|
const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
|
|
const material = new THREE.PointsMaterial({
|
|
color: 'red',
|
|
size: 0.2, // 글로벌 단위
|
|
});
|
|
const points = new THREE.Points(geometry, material);
|
|
scene.add(points);
|
|
</pre>
|
|
<div class="spread">
|
|
<div data-diagram="Points"></div>
|
|
</div>
|
|
|
|
<p><a href="/docs/#api/ko/materials/PointsMaterial#sizeAttenuation"><code class="notranslate" translate="no">sizeAttenuation</code></a>을 <code class="notranslate" translate="no">false</code>로 지정하면
|
|
카메라로부터의 거리에 상관없이 점의 크기가 일정하게 보입니다.</p>
|
|
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const material = new THREE.PointsMaterial({
|
|
color: 'red',
|
|
+ sizeAttenuation: false,
|
|
+ size: 3, // 픽셀
|
|
- size: 0.2, // 글로벌 단위
|
|
});
|
|
...
|
|
</pre>
|
|
<div class="spread">
|
|
<div data-diagram="PointsUniformSize"></div>
|
|
</div>
|
|
|
|
<p>또 하나 집고 넘어가야 하는 것은 Three.js의 물체 대부분이
|
|
세분값에 대한 설정이 다양하다는 겁니다. 좋은 예로 구체가
|
|
있죠. 구체는 얼마나 물체를 세분할지에 대한 값을 매개변수로
|
|
받습니다.</p>
|
|
<div class="spread">
|
|
<div data-diagram="SphereGeometryLow"></div>
|
|
<div data-diagram="SphereGeometryMedium"></div>
|
|
<div data-diagram="SphereGeometryHigh"></div>
|
|
</div>
|
|
|
|
<p>위 그림에서 첫 번째 구체는 둘레로 5개, 높이로 3개의 면으로 분할되었습니다.
|
|
이는 15개의 면 또는 30개의 삼각형이죠. 두 번째 구체는 24 x 10, 240면 또는
|
|
480개의 삼각형입니다. 마지막 구체는 50 x 50으로 무려 2500면 또는 5000개의
|
|
삼각형에 해당하죠.</p>
|
|
<p>얼마나 많이 세분할지는 필요에 따라 다르게 설정하면 됩니다. 위 예제만 보면
|
|
많이 분할할수록 좋아보이나, 선과 플랫 쉐이딩(flat shading)만 제거해도
|
|
아래와 같은 결과가 나옵니다.</p>
|
|
<div class="spread">
|
|
<div data-diagram="SphereGeometryLowSmooth"></div>
|
|
<div data-diagram="SphereGeometryMediumSmooth"></div>
|
|
<div data-diagram="SphereGeometryHighSmooth"></div>
|
|
</div>
|
|
|
|
<p>5000 삼각형인 오른쪽 구체가 480 삼각형인 중간 구체보다 훨씬 좋다고
|
|
이야기하기 모호합니다. 만약 지구본을 만들기 위한 구체 하나를 만든다고
|
|
하면, 10000개의 삼각형으로 구체를 만드는 것이 나쁜 선택은 아닙니다.
|
|
하지만 1000개의 삼각형으로 만든 구체 1000개를 렌더링할 경우, 이는 총
|
|
천만개의 삼각형이 됩니다. 이를 부드럽게 움직이려면 브라우저가 1초에
|
|
60프레임을 렌더링해야 하니, 결과적으로 이는 1초에 6억개의 삼각형을
|
|
렌더링하라고 하는 것과 같죠. 절대 간단한 연산이 아닙니다.</p>
|
|
<p>물론 선택이 쉬운 경우도 있습니다. 예를 들어 평면을 분할한다고 해보죠.</p>
|
|
<div class="spread">
|
|
<div data-diagram="PlaneGeometryLow"></div>
|
|
<div data-diagram="PlaneGeometryHigh"></div>
|
|
</div>
|
|
|
|
<p>왼쪽의 평면은 2 삼각형입니다. 오른쪽 평면은 200 삼각형이죠.
|
|
구체와 다르게 평면은 대부분의 경우 퀄리티 저하가 아예 없습니다.
|
|
평면을 변형해 다른 것을 만드는 경우가 아니면, 평면을 분할해야할
|
|
이유는 없죠.</p>
|
|
<p>그러니 상황에 따라 적절한 값을 선택하기 바랍니다. 물체를 덜 분할할수록
|
|
성능도 올라가고 메모리 점유율도 낮아질 테니까요. 상황에 따라 어떤 것을
|
|
포기할지 결정하는 것은 순전히 여러분의 몫입니다.</p>
|
|
<p>원시 모델 중 어떤 것도 실제 프로젝트에 적용하기가 어렵다면,
|
|
<a href="load-obj.html">.obj 파일</a> 또는 <a href="load-gltf.html">.gltf 파일</a>을
|
|
로드하여 사용할 수 있습니다. 또는
|
|
<a href="custom-buffergeometry.html">커스텀 BufferGeometry</a>를 생성할 수도 있죠.</p>
|
|
<p>다음 장에서는 <a href="scenegraph.html">씬 그래프와 그 사용법</a>에 대해
|
|
알아보겠습니다.</p>
|
|
<p><link rel="stylesheet" href="../resources/threejs-primitives.css"></p>
|
|
<script type="module" src="../resources/threejs-primitives.js"></script>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/manual/resources/prettify.js"></script>
|
|
<script src="/manual/resources/lesson.js"></script>
|
|
|
|
|
|
|
|
|
|
</body></html>
|