[3JS] First Three.js Project

Chenยท2024๋…„ 5์›” 29์ผ

Three.js

๋ชฉ๋ก ๋ณด๊ธฐ
2/4
post-thumbnail

Build Tool

  • builds the final website after writing web code like HTML/CSS/JS.

  • do the optimizations, cache breaking, source mapping, running a local server, etc.

  • lots of build tools like Vite, Gulp, Parcel etc

Vite

  • Faster to install
  • Faster to run
  • Less prone to bugs
  • Much better dev. experience

Though the lectures are recorded using Webpack, the config. is the same

์„ค์น˜

npm init -y
npm i vite
npm i three

package.json ์˜ scripts ๋ณ€๊ฒฝ

  "scripts": {
    "dev" : "vite",
    "build" : "vite build"
  },

import * as THREE from 'three';

console.log(THREE)

์•„๋ž˜์ฒ˜๋Ÿผ ๋‹ค์–‘ํ•œ ํด๋ž˜์Šค์™€ ์†์„ฑ๋“ค์ด ์กด์žฌํ•จ


First Scene

๋ฒˆ๋“ค๋Ÿฌ๋‚˜ ๋””ํŽœ๋˜์‹œ, ๊ทธ ์–ด๋–ค ๋ชจ๋“ˆ ์—†์ด Html๊ณผ JS ๋งŒ์œผ๋กœ three.js๋ฅผ ํ™œ์šฉํ•ด๋ณผ ๊ฒƒ

< 4 elms for basic scene >

  1. Scene
  2. Objects
  3. Camera
  4. Renderer

1. Scene

scene์€ three.js์—์„œ ์ฝ˜ํ…Œ์ด๋„ˆ. Obj, models, particle, lights ๋“ฑ์„ ๋‹ด์Œ

// Scene
const scene = new THREE.Scene();

2. Object

Obj์—๋Š” ๊ธฐ๋ณธ์ ์ธ geometries ๋ถ€ํ„ฐ import๋œ model, particles, lights ๋“ฑ ๋ฌด์ง€๋ฌด์ง€ ๋งŽ๋‹ค

Mesh ๋Š” geometry(the shape)์™€ material(how it looks)์˜ ๊ฒฐํ•ฉ

๋งŒ๋“œ๋Š” ์ˆœ์„œ

  1. geometry, material ๊ฐ๊ฐ ์ƒ์„ฑ
  2. Mesh๋ฅผ ํ†ตํ•ด ๋‘˜์„ ๊ฒฐํ•ฉ
  3. ๊ฒฐํ•ฉํ•œ Mesh๋ฅผ Scene์— ์ถ”๊ฐ€ํ•˜๊ธฐ (scene์— ์•ˆ ๋„ฃ์œผ๋ฉด ํ™•์ธ ๋ถˆ๊ฐ€๋Šฅ)
// Object
const geometry =  new THREE.BoxGeometry(1, 1, 1); // width, height, depth
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); 
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);


3. Camera

์นด๋ฉ”๋ผ๋Š” ๋ˆˆ์— ๋ณด์ด์ง€ ์•Š๊ณ , ์‚ฌ์‹ค์ƒ '์‹œ์ '์— ๊ฐ€๊นŒ์›€. ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์นด๋ฉ”๋ผ๋ฅผ ์“ธ ์ˆ˜๋„ ์žˆ๊ณ , ์—ฌ๋Ÿฌ ํƒ€์ž…์˜ ์นด๋ฉ”๋ผ๊ฐ€ ์กด์žฌ. ์—ฌ๊ธฐ์„  ์›๊ทผ๊ฐ์ด ์žˆ๋Š” perspectiveCamera๋งŒ ๋‹ค๋ฃธ

// Sizes 
const sizes = {
    width: 800,
    height: 600
}

// Camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height);
camera.position.z = 3;
scene.add(camera);

PerspectiveCamera

๋‘ ๊ฐ€์ง€ param์„ ๊ฐ€์ง

1. the field of view (์‹œ์•ผ๊ฐ ์กฐ์ ˆ)

  • ํฐ ์•ต๊ธ€ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  ๋ฐฉํ–ฅ์„ ํ•œ ๋ฒˆ์— ๋ณผ ์ˆ˜ ์žˆ์ง€๋งŒ, ์™œ๊ณก ์ƒ๊น€
  • ์ž‘์€ ์•ต๊ธ€ => ์‚ฌ๋ฌผ ํ™•๋Œ€๋œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž„
  • ์‚ฌ๋žŒ์˜ ์‹œ์•ผ์™€ ์œ ์‚ฌํ•œ ๊ฑด 75๋„

2. the aspect ratio (= width / height)

  • ์บ”๋ฒ„์Šค ๋„“์ด / ์บ”๋ฒ„์Šค ๋†’์ด

Renderer

  • ์•„์ง๊นŒ์ง€ ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๋ณด์ž„ ๐Ÿ‘€ => Renderer ํ•„์š”
  • Renderer์—๊ฒŒ render ์š”์ฒญํ•˜๋ฉด Renderer๋Š” ์นด๋ฉ”๋ผ ์‹œ์ ์—์„œ ๋ณด์ด๋Š” ๋ชจ์Šต์„ ์บ”๋ฒ„์Šค ์œ„์— ๊ทธ๋ ค๋ƒ„
  1. ์ผ๋‹จ Renderer๊ฐ€ ๊ทธ๋ฆผ์„ ๊ทธ๋ฆด canvas๋ฅผ html์— ์ถ”๊ฐ€
  2. Renderer์˜ setSize๋ฉ”์„œ๋“œ๋กœ ์บ”๋ฒ„์Šค ํฌ๊ธฐ ์กฐ์ •
  3. render ๋ฉ”์„œ๋“œ์— scene๊ณผ camera๋ฅผ param์œผ๋กœ ๋„˜๊ฒจ์ฃผ๊ธฐ
  • render the scene seenf rom the camera's point of view

  • result will be drawn into canvas

// Renderer
const renderer = new THREE.WebGLRenderer({
    canvas: canvas
})
renderer.setSize(sizes.width, sizes.height);

// take the picture of the scene, from the camera point of view
renderer.render(scene, camera);

Render!!

both the obj. and camera are in the default position, the center of the scene
=> cannot see an obj from its inside (๊ธฐ๋ณธ์ ์œผ๋กœ object์˜ ๋‚ด๋ถ€์—์„œ๋Š” ๋ฌผ์ฒด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์—†์Œ)

๋•Œ๋ฌธ์— object์˜ ์œ„์น˜๋ฅผ ๋ณ€๊ฒฝํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ, can transform objs using position, rotation, scale

โญ๏ธ ์ค‘์š”ํ•œ ๊ฒƒ์€ render ์ „์— ์œ„์น˜๋ฅผ ๋ณ€๊ฒฝํ•ด์ค˜์•ผํ•จ!!

< ์˜ต์…˜ ๋‘ ๊ฐ€์ง€ >

1. Move Mesh forward
2. Move Camera backward


ํ€ด์ฆˆ ์ธ์ฆ

์ฐธ๊ณ  :
[9rganizedChaos๋‹˜ ๊ฐ•์˜๋…ธํŠธ](https://velog.io/@9rganizedchaos/Three.js-journey-%EA%B0%95%EC%9D%98%EB%85%B8%ED%8A%B8-01-03


โค๏ธ Webpack์ด๋ž€?

๋ฒˆ๋“ค๋ง(bundle)์„ ๋จผ์ € ์•Œ์•„์•ผ

๋ฒˆ๋“ค

js ํŒŒ์ผ๋“ค, ์ด๋ฏธ์ง€, css ๋“ฑ ์ด๋Ÿฐ ๊ฒƒ๋“ค์„ ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ๋กœ ๋ณด๊ณ  ์ด ๋ชจ๋“ˆ๋“ค์„ ๋ฐฐํฌ์šฉ์œผ๋กœ ๋ณ‘ํ•ฉํ•˜๊ณ  ํฌ์žฅํ•˜๋Š” ์ž‘์—…

๋ฒˆ๋“ค๋ง ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํˆด์„ ๋ฒˆ๋“ค๋Ÿฌ๋ผ๊ณ  ํ•จ. ๋ฒˆ๋“ค๋Ÿฌ ์ค‘์—์„œ Webpack์ด ํ˜„์žฌ ์‹œ์  ๊ฐ€์žฅ ์ธ๊ธฐ ๋งŽ์€ ์•„์ด

babel

์ตœ์‹  ๋ฌธ๋ฒ•์œผ๋กœ ๊ฐœ๋ฐœํ•œ js๋ฅผ ์˜ˆ์ „ ํŒŒ์ผ์—์„œ๋„ ์ž˜ ๋Œ์•„๊ฐ€๋Š” ํŒŒ์ผ๋กœ ๋ณ€ํ™˜ํ•ด์คŒ(ํŠธ๋žœ์ŠคํŒŒ์ผ๋Ÿฌ)

์›นํŒฉ์ด๋ž‘ ๊ฐ™์ด ์“ฐ๋ฉด ์ข‹์Œ. ๊ทธ๋ž˜์„œ ๋ฐ”๋ฒจ์„ ๋กœ๋”๋กœ ๋ถˆ๋Ÿฌ์™€์„œ ๊ฐ™์ด ์‹คํ–‰ํ•ด์คŒ

// babel.config.js

module.exports = {
	presets: [
		['@babel/preset-env', {
			targets: {
				chrome: '58',
				ie: '11',
			},
			useBuiltIns: 'usage',
			corejs: {
				version: 3,
			}
		}]
	]
};
// webpack.config.js

const webpackMode = process.env.NODE_ENV || 'development';

module.exports = {
	mode: webpackMode,
	entry: {
		main: './src/main.js',
	},
	output: {
		path: path.resolve('./dist'),
		filename: '[name].min.js'
	},
	// es5๋กœ ๋นŒ๋“œ ํ•ด์•ผ ํ•  ๊ฒฝ์šฐ ์ฃผ์„ ์ œ๊ฑฐ
	// ๋‹จ, ์ด๊ฑฐ ์„ค์ •ํ•˜๋ฉด webpack-dev-server 3๋ฒˆ๋Œ€ ๋ฒ„์ „์—์„œ live reloading ๋™์ž‘ ์•ˆํ•จ
	// target: ['web', 'es5'],
	devServer: {
		liveReload: true
	},
	optimization: {
		minimizer: webpackMode === 'production' ? [
			new TerserPlugin({
				terserOptions: {
					compress: {
						drop_console: true
					}
				}
			})
		] : [],
		splitChunks: {
			chunks: 'all'
		}
	},
	module: {
		rules: [
			{
				test: /\.js$/,
				loader: 'babel-loader',
				exclude: /node_modules/
			},
			{
				test: /\.js$/,
				enforce: 'pre',
				use: ['source-map-loader'],
			}
		]
	},
	plugins: [
		new HtmlWebpackPlugin({
			template: './src/index.html',
			minify: process.env.NODE_ENV === 'production' ? {
				collapseWhitespace: true,
				removeComments: true,
			} : false
		}),
		new CleanWebpackPlugin(),
		// CopyWebpackPlugin: ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•  ํŒŒ์ผ๋“ค์„ ์„ค์ •ํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ
		// ์•„๋ž˜ patterns์— ์„ค์ •ํ•œ ํŒŒ์ผ/ํด๋”๋Š” ๋นŒ๋“œ ์‹œ dist ํด๋”์— ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
		// patterns์— ์„ค์ •ํ•œ ๊ฒฝ๋กœ์— ํ•ด๋‹น ํŒŒ์ผ์ด ์—†์œผ๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
		// ์‚ฌ์šฉํ•˜๋Š” ํŒŒ์ผ์ด๋‚˜ ํด๋” ์ด๋ฆ„์ด ๋‹ค๋ฅด๋‹ค๋ฉด ๋ณ€๊ฒฝํ•ด์ฃผ์„ธ์š”.
		// ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ํŒŒ์ผ๋“ค์ด ์—†๋‹ค๋ฉด CopyWebpackPlugin์„ ํ†ต์งธ๋กœ ์ฃผ์„ ์ฒ˜๋ฆฌ ํ•ด์ฃผ์„ธ์š”.
		new CopyWebpackPlugin({
			patterns: [
				{ from: "./src/main.css", to: "./main.css" },
				{ from: "./src/images", to: "./images" },
			],
		})
	]
};
profile
ํ˜„์‹ค์ ์ธ ๋ชฝ์ƒ๊ฐ€

0๊ฐœ์˜ ๋Œ“๊ธ€