본문은 Three.js 를 맛보기위해 Three.js Document 의 내용을 간단하게 익혀본다.
가장 먼저 HTML 파일을 만들고 tree.js
파일을 가져와서 실행한다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="js/three.js"></script>
<script>
// 트리 JS 코딩
</script>
</body>
</html>
three.js 로 뭔가를 표현하기 위해선 scene
, camera
, renderer
가 필요하다.
다음과 같이 장면을 구현할 수 있다.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75,
window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
여러 종류의 카메라가 있지만, 지금은 PerspectiveCamera
를 사용해보자.
매개변수는 다음과 같다.
field of view(시야각)
FOV 는 해당 시점의 화면이 보일 정도를 나타낸다.aspect ratio(종횡비)
는 해당 요소를 틀어져 보일 수 있는 정도이다.near
은 해당 값보다 가까이 있는 오브젝트는 렌더링되지 않는다.far
은 near
과 반대로 멀 수록 렌더링되지 않는다.near
과 far
은 앱 성능 향상을 위해 사용할 수 있다.
renderer
는 WebGL 지원을 안할 때의 대비용으로 사용한다.
인스턴스로 생성하면 렌더링할 사이즈를 설정해야 한다.
사이즈는 그대로 유지하되 더 낮은 해상도로 렌더링하고 싶으면 세 번째 매개변수에 false
를 전달한다.
마지막으로 렌더링한 것을 <canvas>
엘리먼트로 HTML 문서에 넣어준다.
이제 큐브를 추가한다.
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
큐브를 만들 객체로 BoxGeometry
를 사용한다.
geometry 에 색칠을 해줄 요소로 MeshBasicMaterial
에 매개변수로 녹색인 0x00ff00
을 전달한다.
CSS 나 Photoshop 처럼 hex colors 도 가능하다.
세 번째로 Mesh
로 화면 안에 삽입하여 자유롭게 해줄 수 있는 객체를 사용한다.
scene.add()
로 추가를 하고, 기본 설정으로 (0, 0, 0)
속성을 가진다.
아직 렌더링을 하지 않아 보이지 않을 것이다.
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
1초에 60번 렌더링될 것이다.
setInterval 보다 requestAnimationFrame 사용이 더 이점이 많으니 이를 사용한다.
초록 박스를 확인할 수 있다. 이제 큐브를 회전시켜보자.
다음 코드를 추가한다.
function animate() {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
}
몇몇 브라우저에선 WebGL 이 지원하지 않을 수 있다.
지원 여부를 체크하여 가능한지 메시지를 띄우는 코드를 작성해본다.
스크립트를 추가하고 렌더링하기 전 아래 코드를 실행해보자.
if ( WEBGL.isWebGLAvailable() ) {
animate();
} else {
const warning = WEBGL.getWebGLErrorMessage();
document.getElementById( 'container' ).appendChild( warning );
}
Mesh
를 사용하지 않고 선이나 원을 그려보자.
먼저 renderer
, scene
, camera
를 설정한다.
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const camera = new THREE.PerspectiveCamera( 45,
window.innerWidth / window.innerHeight, 1, 500 );
camera.position.set( 0, 0, 100 );
camera.lookAt( 0, 0, 0 );
const scene = new THREE.Scene();
다음으로 재질을 설정한다.
LineBasicMaterial
이나 LineDashedMaterial
를 사용하면 된다.
const material = new THREE.LineBasicMaterial( { color: 0x0000ff } );
다음으로 꼭짓점에 대한 벡터를 설정한다.
const points = [];
points.push( new THREE.Vector3( - 10, 0, 0 ) );
points.push( new THREE.Vector3( 0, 10, 0 ) );
points.push( new THREE.Vector3( 10, 0, 0 ) );
const geometry = new THREE.BufferGeometry().setFromPoints( points );
선은 연속된 꼭짓점 쌍으로 그려져 첫 번째와 마지막 꼭짓점엔 그려지지 않는다. (선이 닫혀있지 않음)
이제 두 선을 그리기 위한 점과 재질을 합쳐 선으로 만든다.
const line = new THREE.Line( geometry, material );
이제 scene 에 추가하고 render 하자
scene.add( line );
renderer.render( scene, camera );
텍스트 만들기엔 여러 방법이 있다.
HTML 로 텍스트를 추가한다.
z-index 를 활용하여 절대 위치를 설정한다.
캔버스에 텍스트 그리기
3D 모델을 사용
절차적 텍스트 geometry
THREE.js 만의 절차적 및 동적 3D 텍스트 geometry 를 사용하고 싶다면 THREE.TextGeomtry 의 인스턴스인 mesh 를 사용한다.
new THREE.TextGeometry( text, parameters );
이 작업을 수행하려면 TextGeometry 의 font
파라미터가 THREE.Font 인스턴스로 설정돼있어야 한다.
BMFonts (비트맵 폰트) 는 단일 BufferGeometry에 글자들을 일괄적으로 활용할 수 있다.
렌더링은 word-wrapping, letter spacing, kerning 등을 지원한다.
3D 모델을 다양한 three.js 의 로더로 불러올 수 있다.
가능하다면 glTF(GL Transmission Format)를 사용하는 것을 추천한다.
.GLB
, .GLTF
버전의 포맷 모두 잘 지원될 것이다.
glTF 는 런타임 자원 효율에 초점을 맞추고 있어 로딩이 빠르고 정확하다.
속성으로는 meshes
, materials
, textures
, skins
, skeletons
, morph targets
, animations
, lights
그리고 cameras
가 있다.
glTF 파일은 Sketchfab 사이트 등에서 이용할 수 있다.
three.js 엔 몇몇 로더를 제외하고(예: ObjectLoader) 기본적으로 포함되어있지 않아 개별적으로 추가해야 한다.
import { GLTFLoader } from 'loader/GLTFLoader.js';
로더를 import 한 후, scene 모델을 로드한다.
glTF의 경우 스크립트는 다음과 같다.
const loader = new GLTFLoader();
loader.load('path/model.glb', function ( gltf ) {
scene.add( gltf.scene )
}, undefined, function ( error ) {
console.error( error );
} );
위 자동차 모델은 무료 모델을 가져와 GLTFLoader 를 사용하여 모델을 사용해보았다.
모델링이 아예 나오지 않거나 색이 안칠해져있을 경우가 있는데 이런 경우엔 다음 순서로 해결해보자.
위 문제 해결 절차도 먹히지 않는다면 three.js 포럼에 문제 제기를 해보자.
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
meta 태그로 모바일 브라우저들의 뷰포트 크기와 확대정도를 조절한다.
모든 오브젝트들이 카메라의 거리와 상관 없이, 화면 사이즈가 변경된다고 해도, 같은 크기로 보여지고 싶다고 가정하자면 다음 공식을 통해 유지할 수 있다.
visible_height = 2 * Math.tan( ( Math.PI / 180 ) * camera.fov / 2 ) * distance_from_camera;
컬링의 문제로 뒷편의 면을 제거해 버리면 된다. 이 문제가 의심된다면 재질의 면을 THREE.DoubleSide로 변경해보자.
material.side = THREE.DoubleSide