Three.js - Scene 만들기

nearworld·2022년 7월 2일
1

three.js

목록 보기
1/2

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개의 인자를 받는 것을 알 수 있습니다. FOVField Of View의 약자로 위 코드에서는 75도로 맞춰져 있습니다.


저 같은 경우는 위의 이미지를 토대로 FOV를 이해했습니다.

두번째 인자는 aspect ratio로 보통 16:9 같은 형식으로 표현되는 화면비입니다.
찾아보니 웹개발에서는 16/9처럼 표현되고 수식은 가로 / 높이 로 되어있습니다.
위 코드에서는 window.innerWidth / window.innerHeight으로 윈도우 가로 / 윈도우 세로로 화면비를 표현하고 있습니다.

세번째 인자는 near0.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 물체의 verticesfaces 를 추가합니다. vertices는 꼭짓점, faces는 면을 의미합니다.
그 다음, MeshBasicMaterialMaterial을 설정하며 위 코드에서는 녹색을 입히는 데 사용되었습니다. Mateiral도 여러 종류가 있는데 여기선 기본 머테리얼 인스턴스가 사용되었습니다.
마침내, Mesh에 지오메트리를 추가하고 추가된 지오메트리에 머테리얼을 지정해줍니다.
그리고 이 메쉬를 scene에 추가합니다.

주의할 부분!

Meshscene에 추가하고 나면, 카메라와 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씩 회전하도록 추가했더니 큐브가 제자리에서 회전하는 것이 웹페이지에 렌더링됩니다.

profile
깃허브: https://github.com/nearworld

1개의 댓글