[Three.js] 01 Camera & Animation Loop

9rganizedChaos·2021년 5월 23일
2
post-thumbnail

(해당 글은 Udemy의 Three.js and TypeScript 강의를 수강하며 필기한 내용입니다.)

Camera 🎥

1) Perspective Camera

Perspective Camera란?

사람의 시야와 가장 비슷한 형태의 카메라.
3D 렌더링에 사용되는 가장 일반적인 프로젝션 모드.

Perspective Camera 코드 샘플

const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );
scene.add( camera );

Perspective Camera 변수

PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )

  • fov: 카메라 절두체의 수직 시야
  • aspect: 카메라 절두체 종횡비
  • near/ far: 카메라 절두체의 가까운 쪽/ 먼 쪽 평면

2) Orthographic Camera

Orthographic Camera란?

개체의 크기가 카메라와의 거리에 관계 없이 일정하게 유지된다.
2D 장면이나 UI요소를 렌더링 할 때 이용된다.

Orthographic Camera 코드 샘플

const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
scene.add( camera );

Orthographic Camera 변수

OrthographicCamera( left : Number, right : Number, top : Number, bottom : Number, near : Number, far : Number )

  • left/ right/ top / bottom: 카메라 절두체의 왼쪽/ 오른쪽/ 위쪽/ 아래쪽 평면
  • near / far: 카메라 절두체의 가까운 쪽/ 먼 쪽 평면

3) 실습

코드

import * as THREE from "/build/three.module.js";
import { OrbitControls } from "/jsm/controls/OrbitControls";

const scene: THREE.Scene = new THREE.Scene();
// scene.background = new THREE.Color(0xFF0000);
const camera1: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(
  80,
  1 / 2,
  0.1,
  10
);
const camera2: THREE.OrthographicCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 10);
const camera3: THREE.OrthographicCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 10);
const camera4: THREE.OrthographicCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 10);

const canvas1: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("c1");
const canvas2: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("c2");
const canvas3: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("c3");
const canvas4: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("c4");
const renderer1: THREE.WebGLRenderer = new THREE.WebGLRenderer({canvas: canvas1});
renderer1.setSize(200, 200);
const renderer2: THREE.WebGLRenderer = new THREE.WebGLRenderer({canvas: canvas2});
renderer2.setSize(200, 200);
const renderer3: THREE.WebGLRenderer = new THREE.WebGLRenderer({canvas: canvas3});
renderer2.setSize(200, 200);
const renderer4: THREE.WebGLRenderer = new THREE.WebGLRenderer({canvas: canvas4});
renderer2.setSize(200, 200);
// document.body.appendChild(renderer.domElement);

const controls = new OrbitControls(camera1, renderer1.domElement);

const geometry: THREE.BoxGeometry = new THREE.BoxGeometry();
const material: THREE.MeshBasicMaterial = new THREE.MeshBasicMaterial({
  color: 0x00ff00,
  wireframe: true,
});

const cube: THREE.Mesh = new THREE.Mesh(geometry, material);
scene.add(cube);

camera1.position.z = 2;
camera2.position.y = 2;
camera2.lookAt(new THREE.Vector3(0, 0, 0));
camera3.position.z = 2;
camera4.position.x = 2;
camera4.lookAt(new THREE.Vector3(0, 0, 0));

var animate = function () {
  requestAnimationFrame(animate);

  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;

  controls.update();

  renderer1.render(scene, camera1);
  renderer2.render(scene, camera2);
  renderer3.render(scene, camera3);
  renderer4.render(scene, camera4);
};

animate();

camera1: perspective camera
camera2: orthographic camera (포지션 설정: y)
camera3: orthographic camera (포지션 설정: z)
camera4: orthographic camera (포지션 설정: x)

출력된 모습

Animation Loop ⚙️

보통의 경우 animate라는 재귀함수를 사용한다!
그러나 매 순간 계속해서 렌더링이 필요한 경우(예를 들어, rotation)가 아니라면, 이벤트리스너를 통해Resize에 해당하는 함수를 할당해주고 animate 함수를 사용하지 않아도 괜찮다.

코드 예시

import * as THREE from '/build/three.module.js'
import { OrbitControls } from '/jsm/controls/OrbitControls'

const scene: THREE.Scene = new THREE.Scene()

const camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)

const renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

const controls = new OrbitControls(camera, renderer.domElement)
// controls.addEventListener('change', render) //this line is unnecessary if you are re-rendering within the animation loop 


const geometry: THREE.BoxGeometry = new THREE.BoxGeometry()
const material: THREE.MeshBasicMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true })

const cube: THREE.Mesh = new THREE.Mesh(geometry, material)
scene.add(cube)

camera.position.z = 2

window.addEventListener('resize', onWindowResize, false)
function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
    // render()
}

var animate = function () {
    requestAnimationFrame(animate)

    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    renderer.render(scene, camera)
};

// function render() {
//     renderer.render(scene, camera)
// }
// render()
animate();
profile
부정확한 정보나 잘못된 정보는 댓글로 알려주시면 빠르게 수정토록 하겠습니다, 감사합니다!

0개의 댓글