Web/Frontend

[three.js 기초 #0] 시작하기 & 환경 세팅

AllTheTech 2024. 5. 12. 13:31

※ 순수 자바스크립코드와 three 라이브러리를 사용한 기초 실습입니다. 

유튜버 GIS DEVELOPER 님의 강의(https://youtu.be/vjKuk5Vp93k?si=aoRRPljQ3pKDDJO8 )를 보고 정리한 내용입니다.

1. Three.js 란?

WebGL 위에 구축된 고수준의 Javascript 라이브러리.

3D 그래픽을 쉽게 웹 브라우저에 표시하고, 저수준의 WebGL을 직접 다룰 필요 없이 3D 장면, 모델, 카메라, 애니메이션 등을 구축할 수 있음.

WebGL

Web Graphics Library 는 웹 브라우저에서 실시간 2D 및 3D 그래픽을 렌더링하기 위한 저수준의 그래픽 API.

OpenGL ES의 웹 기반 버전으로, HTML5의 <canvas> 요소를 활용하여 GPU 가속을 통한 이미지와 애니메이션의 렌더링을 가능하게 함.

WebGL을 사용하려면 GLSL(OpenGL Shading Language)로 셰이더를 작성해야 하며, 그래픽 파이프라인의 모든 단계를 직접 제어해야 함.

  • GLSL(OpenGL Shading Language) : GPU에서 실행되는 커스텀 셰이더 프로그램을 작성하기 위한 C언어 기반의 고수준 프로그래밍 언어

Three 기본 구성 요소

  • Renderer: 장면을 출력장치에 렌더링
  • Scene: 3차원 객체
  • Camera: 시점을 정의(각도, 거리)
  • Light: 객체의 광원
  • Mesh: 객체의 형상, 색상을 정의

2. Three.js 를 시작하기 위한 준비

node & VSC 설치

node와 VSC가 설치 방법은 아래 포스팅을 참고해주세요.

https://eunjitech.tistory.com/entry/MBTI-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%A7%8C%EB%93%A4%EA%B8%B0-0-Visusal-Studio-Code-%EC%84%A4%EC%B9%98%EC%99%80-Create-react-app-%EC%83%9D%EC%84%B1

 

[MBTI 테스트 사이트 만들기 #0] Visusal Studio Code 설치와 Create-react-app 생성

Visusal Studio Code 설치와 Create-react-app 생성 수익형 웹사이트에 꽂혀서 MBTI 테스트 사이트를 만들어볼 것이다. 노트북이 고장 나서 친구 컴퓨터로 해야 되는데, 세팅부터 차근차근해보도록 한다. nod

eunjitech.tistory.com

필요한 extension: Live server

three.js 코드 다운로드

  1.  아래 공식 사이트에서 Code > download 클릭
  2. three.js-master 압축풀기
  3. vsc로 폴더 추가

https://threejs.org/ 

 

Three.js – JavaScript 3D Library

 

threejs.org

파일구조(study 제외)

  • examples: three.js 예제들을 확인할 수 있음
  • three.module.js: three 모듈 파일(여기서 관련 api를 import)

3. 작업 폴더 추가

three.js-master 폴더에 하위폴더를 생성해줍니다.

study라고 폴더를 생성하고, 폴더 내에 '01-basic.html', '01-basic.css', '01-basic.js' 를 각각 생성합니다.

01-basic.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="01-basic.css">
    <!-- 모듈 버전으로 import 하기위해 -->
    <!-- defer는 해당 모듈이 모두 로드 된 후에 실행한다는 것 -->
    <script type='module' src='01-basic.js' defer></script>
    <title>Document</title>
</head>

<body>
    <div id="webgl-container"></div>
</body>

</html>

01-basic.css

* {
  outline: none;
  margin: 0;
}

body {
  overflow: hidden;
}

#webgl-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

01-basic.js

import * as THREE from "../build/three.module.js";

class App {
	constructor() {
		const divContainer = document.querySelector("#webgl-container");
		this._divcontainer = divContainer; //필드화

		const renderer = new THREE.WebGLRenderer({ antialias: true }); //antialias: 계단현상 제거
		renderer.setPixelRatio(window.devicePixelRatio); //픽셀값은 디바이스픽셀값으로 정의
		divContainer.appendChild(renderer.domElement);
		this._renderer = renderer;

		const scene = new THREE.Scene();
		this._scene = scene; //필드화

		this._setupCamera();
		this._setupLight();
		this._setupModel();

		window.onresize = this.resize.bind(this);
		this.resize();
		requestAnimationFrame(this.render.bind(this));
	}

	_setupCamera() {
		const width = this._divcontainer.clientWidth;
		const height = this._divcontainer.clientHeight;
		const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 100);
		camera.position.z = 2;
		this._camera = camera;
	}

	_setupLight() {
		const color = 0xffffff;
		const intensity = 1;
		const light = new THREE.DirectionalLight(color, intensity);
		light.position.set(-1, 2, 4);
		this._scene.add(light);
	}

	_setupModel() {
		const geometry = new THREE.BoxGeometry(1, 1, 1);
		const material = new THREE.MeshPhongMaterial({ color: 0x44a88 });

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

		this._scene.add(cube); //scene의 하위 객체
		this._cube = cube;
	}

	resize() {
		const width = this._divcontainer.clientWidth;
		const height = this._divcontainer.clientHeight;

		this._camera.aspect = width / height;
		this._camera.updateProjectionMatrix();

		this._renderer.setSize(width, height);
	}

	render(time) {
		//애니메이션 효과
		this._renderer.render(this._scene, this._camera);
		this.update(time);
		requestAnimationFrame(this.render.bind(this));
	}

	update(time) {
		time *= 0.001; //밀리세컨단위를 second unit 변경
		this._cube.rotation.x = time;
		this._cube.rotation.y = time;
	}
}

window.onload = function () {
	new App();
};
  • App 클래스 이외에 _시작하는 메소드를 불러오면 X
  • antialias: 렌더러 시 계단현상 제거
  • 렌더러, 카메라는 창 크기 변경 시 크기에 맞게 재설정해야 하기 때문에 resize 메소드 지정
반응형