공식문서 왈
three.js로 무언가를 표현하려면 scene, camera 그리고 renderer가 필요합니다. 이를 통해 카메라로 장면을 구현할 수 있습니다.
씬에는 3d object(mesh+geo) , light, camera 가 필요함
const renderer= new THREE.webGLRenderer({canvas});
renderer.setSize(window.innerWidth, window.innerHeight);
const scene= new THREE.Scene();//렌더러를 만든 삽입
scene.add(camera)//마지막에 삽입
모든 물체는 mesh로 이루어져있고,(mesh=geometry+material)
카메라에는 시야각(fov)이 존재함.
mesh는 near(카메라 절두체 근평면)와 far(카메라 절두체 원평면)사이에 있고 시야각(fov)에 들어와야 보인다.
카메라의 생성자는 원근카메라, 직교카메라 두 개가 있음
좌 원근 우 직교
원근이 적용됨
PerspectiveCamera(fov,aspect,near,far)
const camera=new THREE.PerspectiveCamera(
75,//시야각
window.innerWidth/window.innerHeight, //종횡비(aspect)
0.1,//near
1000//far
)
카메라의 기본 위치는 0,0,0임.
카메라의 position은 camera 오브젝트의 position속성을 이용한다.
camera.position.z=5;
거리와 상관없이 크기가 똑같이 유지됨 => 게임에서 주로 쓴다
생성자는 OrthographicCamera.
여기는 시야각 대신 절단면의 값을 매개변수로 받는다.
의외의 사실~ 카메라 각도 조절은 position조절이 아닌, camera.zoom을 이용한다!
camera.zoom=0.5//기본값은 1이기 때문에, 줌아웃을 하는 것
줌아웃 이후 updateProjectionMatrix()를 함께 써야 한다.
메쉬는 모양과 껍질로 이루어짐
const geometry = new THREE.BoxGeometry(1,1,1);
//1,1,1사이즈의 정육면체 박스를 만들자
const material = new THREE.MeshBasicMaterial({
//material에는 오브젝트를 만들어 인자에 넣어서 호출을 하는데,
//여기에 색깔 등 오브젝트의 정보를 넣는다.
color=0xff0000
//color='red'
//color=#ff0000
//위처럼 color을 3가지 방법으로 표현이 가능하다.
});
const mesh=new THREE.Mesh(geometry,material);
scene.add(mesh)
여기서 잠깐!
MeshBasicMaterial의 경우, 조명에 반응을 안한다. => 조명이 없어도 보이고, 조명이 있어도 명암에 변화가 없다.
마지막에는 항상 renderer을 써먹어야한다!
renderer.render(scene,camera)
모델의 회전은 mesh객체의 rotation값을 조절한다.
mesh.rotation.y+=0.1; //0.1라디안 = 18도 회전
mesh.rotation.y+=THREE.MathUtils.degToRad(1); //1라디안이 아닌 1도로 회전
이 때, 기본 단위는 '라디안'이다. (2라디안=360도)
따라서, 우리리가 아는 '도'를 표현하고 싶을 때는 Three.js 내장 함수인 degToRad를 이용하자.
반응형(?)이라고 해야할까
브라우저 리사이징을 할 때마다 씬도 함께 리사이징을 시키기 위해서는 별도의 함수를 생성해야한다.
function setSize(){
camera.aspect = window.innerWidth/window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.render(scene,camera);
}
window.addEventListner('resize',setSize); //브라우저 크기 조정시 이벤트 발생
window.devicePixelRatio:기기 픽셀 비율, 화면에 담기는 픽셀의 밀집도라고 생각하면 편하다. => 고해상도를 표현하는 데에 사용되는 함수
renderer.setPixelRatio(window.devicePixelRatio);
만약 window.devicePixelRatio가 2라고 친다면
100px짜리 화면을 나타내는 데에 사실상 200px이 소요된다는 것
=> 픽셀 밀집도가 높아 고해상도로 표현된다.
그런데 요즘은 고해상도 디스플레이가 많다보니 픽셀밀집도가 정수로 떨어지지 않는 곳이 많다. 그래서 그냥...
renderer.setPixelRatio(window.devicePixelRatio>1?2:1);
//픽셀 밀집도가 1보다 크다면 2로, 아니면 1로 설정해라
로 하는게 성능상 좋다.
배경을 투명처리시킬 것인지는 렌더러에서 설정해야한다.
const renderer = new THREE.WebGLRenderer({
canvas,
alpha: true//배경 투명 허용
});
하지만 불투명도를 0이나 100이 아닌 반투명하게 만들고 싶다면, 렌더러의 내장 메서드를 이용한다.
renderer.setClearColor('#00ff00');//배경색 설정
renderer.setClearAlpha(0.5)//불투명도 50%
배경색은 scene에서도 설정이 가능하다
const scene = new THREE.Scene();
scene.background = new THREE.Color('blue');
조명에는 여러 종류가 있다. 추후에 자세히 다뤄보자.
const light = new THREE.DirectionalLight(0xffffff,1);
//뒤에 1은 광도를 의미함. 0에서부터 1000까지 가능(500쯤 넣어도 최대)
//카메라와 마찬가지로 position을 이용해 조명 위치를 조절할 수 있다.
light.position.z=5;
light.position.y=1;
scene.add(light);
//씬에 조명 추가하는 것을 잊지 말자
베이스는 window.requestAnimationFrame().을 이용한다.
원하는 애니메이션을 알리고 다음 리페인트가 진행되기 전에 애니메이션을 업데이트하는 함수를 호출하게 한다.
즉, 프레임마다 다음 애니메이션의 정보를 가져와 리페인트시킨다.
function draw(){
mesh.rotation.y+=THREE.MathUtils.degToRad(1);
renderer.render(scene,camera);
window.requestAnimationFrame(draw);
}
Three.js의 내장함수를 이용하는 방법도 있다.
window.setAnimationLoop대신 renderer.setAnimationLoop를 사용한다.
AR,VR을 웹에서 구현하는 경우, renderer의 내장함수를 이용해야한다!
각 컴퓨터마다 성능이 다르기 때문에, 동일한 개수의 애니메이션 프레임을 호출하는 것은 비효율 적일 수 있다.
=> 컴퓨터의 실행속도에 맞게 애니메이션을 구상하자
const clock=new THREE.Clock();
const time = clock.getElapsedTime();//경과 시간. 컴퓨터 성능이 느릴수록 호출될 때 찍히는 시간 간격이 커짐
mesh.rotation.y=1*time; //속도를 빠르게 하고 싶다면 time의 배수를 높이면 된다.
const clock=new THREE.Clock();
const delta=clock.getDelta();//실행 간격(거의 상수)
mesh.rotation.y=1*delta; //속도를 빠르게 하고 싶다면 time의 배수를 높이면 된다.
이 방법은 THREE.js 내장 객체가 아니므로, 바닐라 js의 canvas에서도 사용 가능함
let oldTime=Date.now();
function draw(){
const newTime=Date.now();
const deltaTime=newTime-oldTime;
oldTime=newTime;
mesh.rotation.y=1*deltaTime;
};
기본적인 애니메이션이라면, 라이브러리를 이용해 간단히 애니메이션을 구현할 수도 있다.
본 강의에서는 자바스크립트 애니메이션 라이브러리 'GSAP'을 이용한다.
npm i gsap
패키지 설치 후 import하는 것도 잊지 말자.
import gsap from 'gsap';
//mesh라는 이름의 Box객체를 만들었다고 치자.
gsap.to{
mesh.position,
{
duration:1,
y:2,
z:3
}
}
//현재 위치에서 목적지로 duration만큼 이동하는 함수
여기서 말하는 안개란, 우리가 보통 알고있는 희뿌연 연기가 아니라,
은은하게 색상이 들어오는 효과를 의미하는 거라고 보면 된다.
THREE 모듈 내장 객체인 Fog로 불러온다.
scene.fog = new THREE.Fog('blue',3,7);
//색상값과 near, far을 입력받는다.
안개 색상을 배경색과 똑같이 하면 은은하게 객체가 사라지는 효과를 줄 수 있다.