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

<!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) =&gt; {
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>