Scene
씬은 3D 오브젝트들을 배치하는 추상적인 영역이다.
씬이 추상적인 이유는 직접 씬을 볼 수는 없기 때문이다.
const scene = new THREE.Scene();
... // 다른 객체들 생성
/* 빛, 3D 오브젝트 등의 객체를 씬에 추가 */
scene.add(otherObject);
Camera
PerspectiveCamera 객체는 씬을 원근법에 기반하여 바라본다.
OrthographicCamera 객체는 씬을 직교법에 기반하여 바라본다.
const camera = new THREE.PerspectiveCamera(
FOV값: number,
카메라종횡비: number,
렌더링최소거리?: number,
렌더링최대거리?: number
);
// 주로 쓰는 종횡비값: window.innerWidth / window.innerHeight
camera.position.set(200, 100, 150);
camera.rotation.set(0, -40, 0);
camera.scale.set(1, 1, 1);
WebGLRenderer
카메라로 바라본 씬을 렌더링한다.
const renderer = new THREE.WebGLRenderer({
// Vanilla ver.
canvas: document.getElementById("canvas"),
// React ver.
canvas: canvas.current,
// 3D Object의 계단현상 제거
antialias: true,
});
...
/* 씬과 카메라를 파라미터로 넣고 렌더링 */
renderer.render(scene, camera);
색상 인코딩 설정
가져온 3D 오브젝트의 렌더링을 RGB 컬러로 인코딩한다.
renderer.outputEncoding = THREE.sRGBEncoding;
조명 설정
- DirectionalLight: 광원에서 뻗어나가는 직사광선. 태양광.
- AmbientLight: 씬의 모든 객체에 동일 강도의 빛을 제공. 그림자를 생성하지 않음.
- PointLight: 특정 위치에서 모든 방향으로 빛을 방출하는 광원 생성. 빛의 세기는 광원에서 물체의 거리에 따라 감소함.
- SpotLight: 특정 위치에서 특정 방향으로 빛을 방출하는 광원 생성. 빛은 원뿔형의 영역을 형성. 거리에 따라 빛의 세기 감소.
- HemisphereLight: 하늘과 지면을 시뮬레이션 하기 위한 빛. 두개의 서로 다른 색상을 사용하여, 물체의 위쪽과 아래쪽을 다른 색상으로 조명.
- RectAreaLight: 직사각형 영역에서 빛을 방출하는 광원. 이 빛은 직사각형 영역의 높이와 폭을 정의할 수 있으며 직사각형 영역 면을 따라 균일하게 조명.
const light = new THREE.DirectionalLight(0xffffff, 100);
scene.add(light);
3D Object Loader
maya, blender 등으로 제작된 3D Object를 로드한다.
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
const loader = new GLTFLoader();
loader.load("resource-path", (gltf) => {
gltf.scene.position.set(0, 0, 0);
gltf.scene.scale.set(10, 10, 10);
scene.add(gltf.scene);
function animate() {
/* 프레임마다 요청 */
requestAnimationFrame(animate);
/* 컨트롤러 업데이트 */
controls.update();
/* 렌더링 업데이트 */
renderer.render(scene, camera);
}
animate();
},
undefined,
(error) => {
console.error(error);
});
Controller
마우스, 키보드 등의 입력 제어
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
const controls = new OrbitControls(camera, renderer.domElement);
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
function onMouseClick(event) {
const rect = renderer.domElement.getBoundingClientRect();
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0) {
console.log(intersects[0].object);
}
}
renderer.domElement.addEventListener("click", onMouseClick, false);
...
loader.load("...", (gltf) => {
...
function animate() {
...
controls.update();
...
}
animate();
});