Three.js 기본

·2023년 2월 22일
1

Three.js

목록 보기
1/8

씬의 구성 요소

공식문서 왈

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의 내장함수를 이용해야한다!

애니메이션 성능보정

각 컴퓨터마다 성능이 다르기 때문에, 동일한 개수의 애니메이션 프레임을 호출하는 것은 비효율 적일 수 있다.
=> 컴퓨터의 실행속도에 맞게 애니메이션을 구상하자

getElapsedTime이용

const clock=new THREE.Clock();
const time = clock.getElapsedTime();//경과 시간. 컴퓨터 성능이 느릴수록 호출될 때 찍히는 시간 간격이 커짐
mesh.rotation.y=1*time; //속도를 빠르게 하고 싶다면 time의 배수를 높이면 된다.

getDelta이용

const clock=new THREE.Clock();
const delta=clock.getDelta();//실행 간격(거의 상수)
mesh.rotation.y=1*delta; //속도를 빠르게 하고 싶다면 time의 배수를 높이면 된다.

Date객체 이용

이 방법은 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 라이브러리 이용 애니메이션

기본적인 애니메이션이라면, 라이브러리를 이용해 간단히 애니메이션을 구현할 수도 있다.

본 강의에서는 자바스크립트 애니메이션 라이브러리 '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을 입력받는다.

안개 색상을 배경색과 똑같이 하면 은은하게 객체가 사라지는 효과를 줄 수 있다.

profile
백엔드 호소인

0개의 댓글