three.js
의 공식 문서를 따라 독학 중입니다.
먼저, three.js
를 간략히 소개하자면 웹 페이지에 3D 애니메이션을 구현하기 위해 사용되는 라이브러리입니다.
첫번째 절차는 프로젝트 디렉토리에 js
파일 하나를 생성 후, 아래 링크에 있는three.js
코드를 복붙합니다.
https://threejs.org/build/three.js
두번째 절차는 three.js
코드에 html
파일에 script
태그를 추가하는 것입니다.
저는 three.js
파일을 js
폴더 안에 넣어준 후 해당 경로를 src
attribute에 추가했습니다.
<script src='js/three.js'></script>
다음 코드는 3D 오브젝트를 렌더링 하기 위한 캔버스를 추가하고 있습니다.
<script src='js/three.js'></script>
<script>
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 );
</script>
three.js
는 여러 종류의 카메라를 지원하는데요. 이 예제에서는 PerspectiveCamera
를 사용합니다. PerspectiveCamera
를 좀 더 자세히 알아보겠습니다.
PerspectiveCamera(FOV, ASPECT_RATIO, near, far)
, 총 4개의 인자를 받는 것을 알 수 있습니다. FOV
는 Field Of View
의 약자로 위 코드에서는 75
도로 맞춰져 있습니다.
저 같은 경우는 위의 이미지를 토대로 FOV
를 이해했습니다.
두번째 인자는 aspect ratio
로 보통 16:9
같은 형식으로 표현되는 화면비입니다.
찾아보니 웹개발에서는 16/9
처럼 표현되고 수식은 가로 / 높이
로 되어있습니다.
위 코드에서는 window.innerWidth / window.innerHeight
으로 윈도우 가로 / 윈도우 세로
로 화면비를 표현하고 있습니다.
세번째 인자는 near
로 0.1
이라는 값이 설정되어 있는데 공식 문서를 보니 0.1
아래이면
카메라에 더 가깝다는 이야기이고 0.1
보다 가까이 있는 건 렌더링하지않고 0.1
부터 렌더링을 하는 듯 합니다.
네번째 인자는 far
로 얼마나 멀리까지 렌더링을 하느냐인 거 같습니다. 세번째, 네번째 인자 둘다 어디서부터 어디까지 렌더링을 할것인가 렌더링 거리를 설정하는 인자들입니다.
그 다음 줄을 확인하면 아래의 코드가 나옵니다.
const renderer = new THREE.WebGLRenderer();
만약, 브라우저가 구형이라면 WebGL
지원이 안되므로 위 렌더러가 작동하지 않습니다.
renderer.setSize( window.innerWidth, window.innerHeight );
렌더러의 크기를 정하는 코드인데요. 제가 직접 브라우저를 통해 확인한 결과, 렌더링 영역이 검정 바탕화면을 가진 영역으로 나타나는데 그 영역의 크기를 지정한다고 보면 될 거 같습니다.
마지막 코드,
document.body.appendChild( renderer.domElement );
위 코드는 렌더러를 <canvas>
태그로 DOM
트리에 추가하는 코드입니다.
이 코드들 가지고는 웹 브라우저에 아무것도 나타나질 않습니다. 이유는 렌더링할 어떤 3D 오브젝트도 추가되지 않았기 때문입니다. 그래서 큐브를 하나 추가하겠습니다.
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
BoxGeometry
는 3D 물체의 vertices
와 faces
를 추가합니다. vertices
는 꼭짓점, faces
는 면을 의미합니다.
그 다음, MeshBasicMaterial
은 Material
을 설정하며 위 코드에서는 녹색을 입히는 데 사용되었습니다. Mateiral
도 여러 종류가 있는데 여기선 기본 머테리얼 인스턴스가 사용되었습니다.
마침내, Mesh
에 지오메트리를 추가하고 추가된 지오메트리에 머테리얼을 지정해줍니다.
그리고 이 메쉬를 scene
에 추가합니다.
Mesh
를 scene
에 추가하고 나면, 카메라와 3D 오브젝트 둘다 기본좌표 0,0,0
에 겹쳐서 렌더링되므로 카메라의 위치를 따로 지정해줍니다. 위 예제 코드에서는 카메라를 z
축으로 5만큼 이동하였습니다.
이제 큐브
오브젝트 하나가 웹 페이지에 렌더링되는 것을 볼 수 있습니다. 그 다음은 이 큐브에 애니메이션을 추가하는 것입니다.
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
animate()
함수는 animate loop
이라 불리며 이유는 보통 스크린에 1초에 60번 렌더링을 반복하기 때문입니다.
그럼 여기서 의문이 생길 수 있습니다. 왜 굳이 setInterval
을 놔두고 animate loop
를 써야하는가..?
그 이유는 requestAnimationFrame(animate)
를 사용할 경우 유저가 브라우저에서 다른 탭으로 이동할 경우 렌더링을 중지하기 때문에 자원을 절약해줍니다.
하지만 저 코드만으로는 큐브가 움직이지 않습니다. 이유는 다른 좌표에 값들을 아직 주지 않았기 때문입니다.
function animate() {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
}
animate();
render()
위에 x
, y
축을 기준으로 0.01
씩 회전하도록 추가했더니 큐브가 제자리에서 회전하는 것이 웹페이지에 렌더링됩니다.