์ค๋์ ์ด์ด์ Part3 [Three.js]์ Chapter03 3D ํ ์คํธ ๊ฐ์๋ฅผ ๋ค์์ต๋๋ค.(01~03๊ฐ)
๊ทธ๋ผ ์ค๋ ๊ฐ์์์ ๋ฐฐ์ด ๋ด์ฉ๋ค๊ณผ ๋๋์ ์ ๊ฐ๋ตํ๊ฒ ์์ฑํด ๋ณผ๊ฒ์!
๐01. ํฐํธ ๋ณํํ๊ธฐ
Three.js์์ ํ ์คํธ๋ฅผ ๋ณด์ฌ์ค๋๋ text geometry๋ฅผ ์ฌ์ฉํ๋๋ฐ์, ์ด๋ ์ ๋ฌํ๋ ํฐํธ์ ํ์์ด ์ผ๋ฐ์ ์ผ๋ก ๋ง์ด ์ฌ์ฉํ๋ ttf,otf ๊ฐ์ ํ์์ด ์๋๋ผ TypeFace๋ผ๋ json ํ์์ ์ฝ๋์ฌ์ผ ํฉ๋๋ค. ๊ฐ์ฅ ๊ฐ๋จํ ์ ์ฉํด ๋ณผ ์ ์๋ ํฐํธ๋ ์๋์ฝ๋์ฒ๋ผ ๊ฐ์ ธ์ฌ ์ ์๋๋ฐ์.
import typeface from 'three/examples/fonts/gentilis_bold.typeface.json'
์ ํฐํธ๋ค์ ํ๊ธ์ง์์ด ์๋๋์ง๋ผ ๊ฐ์์์๋ ํ๊ธ ์ง์์ด ๋๋ ํฐํธ๋ฅผ ์๋ก ๋ฐ์ ํ TypeFace๋ก ๋ณํํ์ฌ ์ฌ์ฉํ์์ต๋๋ค.
์ ๋ ์ ๊ฐ ๊ฐ์ง๊ณ ์๋ ์ง๋ง์ผ์ฐ์คOTF ํ์ผ์ TypeFace ํ์์ผ๋ก ๋ณํํด์ ์ฌ์ฉํ์ต๋๋ค.
๊ฐ ์ ์ผ๋ก ์์ฃผ์ฌ์ฉํ๋ ์์ ํฐํธ์ ๋๋ค ใ ใ ใ ์๋ ์ง๋ง์ผ ํํ์ด์ง์์ ๋ค์ด๋ฐ์ผ์ค ์ ์์ด์.
https://corp.gmarket.com/fonts/
์๋ ์ฌ์ดํธ์ ๊ฐ์ง๊ณ ์๋ ํฐํธํ์ผ์ ์ฌ๋ฆฌ๋ฉด TypeFace ํ์์ผ๋ก ๋ณํ์ด ๊ฐ๋ฅํฉ๋๋ค.
https://gero3.github.io/facetype.js/
Facetype.js
gero3.github.io
๐02. ํฐํธ ๋ถ๋ฌ์ค๊ธฐ
typeface๋ก ๋ณํํ ํ์ผ์ main.js์์ ๋ถ๋ฌ์ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค. ํฐํธ๋ฅผ ๋ถ๋ฌ์ฌ ๋๋ Three.js๊ฐ ์ ๊ณตํ๋ FontLoader ํด๋์ค๋ฅผ ์ฌ์ฉํ์๋ฉด ๋ฉ๋๋ค. FontLoader๋ JSON format ํ์ผ์ ๋ถ๋ฌ์ค๊ณ Shapes ๋ฐฐ์ดํํ์ธ 'font'๋ฅผ ๋ฆฌํดํด์ค๋๋ค.
์์ธํ ๋ด์ฉ์ ์๋ ๊ณต์๋ฌธ์๋ฅผ ์ฐธ์กฐํด์ฃผ์ธ์.
https://threejs.org/docs/index.html?q=font#examples/en/loaders/FontLoader
three.js docs
threejs.org
ํฐํธ๋ฅผ ๋ก๋ํ๋ ์ฒซ๋ฒ์งธ ๋ฐฉ๋ฒ์ fontLoader์ load ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์ ๋๋ค.
load ๋ฉ์๋์ ์ฒซ๋ฒ์งธ ์ธ์๋ก๋ ํฐํธ ํ์ผ์ ์์น, ๊ทธ๋ฆฌ๊ณ ์์๋๋ก onLoad, onProgree, onError cbํจ์๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
// FontLoader ํด๋์ค ํธ์ถ
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
// ์ธ์คํด์ค ์์ฑ
const fontLoader = new FontLoader();
// load ๋ฉ์๋๋ก ํฐํธ ๋ถ๋ฌ์ค๊ธฐ
fontLoader.load(
"./assets/fonts/Gmarket Sans Bold_Regular.json", //๊ฒฝ๋ก ์ง์
(font) => {
console.log("onload", font);
},
(event) => {
console.log("progress", event);
},
(error) => {
console.log("error", error);
}
);
์ฝ์์ ํ์ธํด๋ณด๋ฉด onProgress ์ฝ๋ฐฑ์ด ํธ์ถ๋ ๋ loaded๊ฐ์ด ์ ์ ์ปค์ง๋ฉด์ total ๊ฐ๊ณผ ๊ฐ์์ง๊ณ ๋ง์ง๋ง์ onload ํจ์๊ฐ ํธ์ถ๋๋ ๊ฑธ ๋ณผ ์ ์์ต๋๋ค.
ํฐํธ๋ฅผ ๋ก๋ํ๋ ๋๋ฒ์งธ ๋ฐฉ๋ฒ์ typeface๊ฐ์ฒด ์์ฒด๋ฅผ main.js์์ ์ง์ ๋ถ๋ฌ์ค๊ณ three.js๊ฐ ์ดํดํ ์ ์๊ฒ ํ์ฑํด์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
import jsonFont from './assets/fonts/Gmarket Sans Bold_Regular.json';
const font = fontLoader.parse(jsonFont);
๊ฐ์์์๋ Load๋ฉ์๋์ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ ๋ฐฉ์์ ์ฌ์ฉํ์ต๋๋ค.
๐03. ํ ์คํธ ์ถ๊ฐํ๊ธฐ
์ ๋ฒ์ ๋ถ๋ฌ์จ ํฐํธ๋ฅผ ์ ์ฉํ text geometry๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. ๋จผ์ ์๋ ํธ์ถ๋ฌธ์ผ๋ก TextGeometry class๋ฅผ import ํด์ฃผ์ธ์
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
TextGeometry์ ๋ํ ์์ธํ ๋ด์ฉ์ ์๋ ๊ณต์ ๋ฌธ์๋ฅผ ํ์ธํด์ฃผ์ธ์
https://threejs.org/docs/index.html?q=text#examples/en/geometries/TextGeometry
three.js docs
threejs.org
๊ทธ๋ฆฌ๊ณ load๋ฉ์๋์ onload ์ฝ๋ฐฑ๋ถ๋ถ์ ์๋์ฒ๋ผ ๋ณ๊ฒฝํด์ค๋๋ค.
fontLoader.load("./assets/fonts/Gmarket Sans Bold_Regular.json", (font) => {
const textGeometry = new TextGeometry("์๋
ํ์ธ์", {
font, // ๋ถ๋ฌ์จ ํฐํธ ์ง์
size: 0.5, // ํฌ๊ธฐ ์ค์
height: 0.1, // ๋๊ป ์ง์
});
const textMaterial = new THREE.MeshPhongMaterial({ color: 0x00c896 });
const text = new THREE.Mesh(textGeometry, textMaterial);
scene.add(text);
});
์ฌ๊ธฐ๊น์ง ์์ฑํ์ จ์ ๋๋ ํ๋ฉด์ ์๋ฌด๊ฒ๋ ๋ณด์ด์ง ์๋๋ฐ์, ์ด์ ๋ MeshPhongMaterial์ด ๋น์ ์ํฅ์ ๋ฐ๋ ์ฌ์ง์ด๊ธฐ ๋๋ฌธ์ ๋น์ด ์์ผ๋ฉด ์๋ฌด๊ฒ๋ ๋ณด์ด์ง ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋ ์ต๋๋ค ใ ใ ;
ambientLight์ pointLight๋ฅผ ์ฅ๋ฉด์ ์ถ๊ฐํด์ฃผ์๋ฉด ํ ์คํธ๊ฐ ์ ๋ณด์ด๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ฐ๋ฐ ์ ๋ ์ ์๋ณด์ด๋๋ผ๊ตฌ์..ใ ํํซ.. ์๋์ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
onError ์ฝ๋ฐฑ์์ ํ์ธํ์ ๋ ๋ก๋์์ฒด ๋ฌธ์ ๋ ์๋ ๊ฒ ๊ฐ๊ณ ํฐํธ๋ฅผ ๋ถ๋ฌ์จ ํ ๊ธ์ path ๋ฅผ ๊ทธ๋ฆฌ๋ ๊ณผ์ ์์ ๋ญ๊ฐ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ ๊ฐ์ต๋๋ค..๐ง ํน์๋ชฐ๋ผ ๊ฐ์ฌ๋์ด ์ฌ์ฉํ์ ํฐํธ๋ก ๋ณ๊ฒฝํด์ ํด๋ณด๋ ์๋๋๋ผ๊ตฌ์? ๊ทธ๋์ ํน์ OTF, TTF ๋ฌธ์ ์ผ๊น ์ถ์ด์ ์ง๋ง์ผ ์ฐ์ค TTFํ์ผ์ ๋ค์ด๋ก๋๋ฐ์ typeface๋ก ๋ณํํ ์ฌ์ฉํด๋ณด๋ ์ ๋๋ ๊ฒ์ ํ์ธํด๋ณผ ์ ์์์ต๋๋ค.
๋ง์ง๋ง์ผ๋ก ํ์คํ ํด๋ณด๊ธฐ์ํด ๊ฐ์ฌ๋์ด ์ฌ์ฉํ์ ์ ์ค์ฒด OTF ํฐํธ๋ฅผ ๋ณํํ ์ ์ฉํด๋ณด๋ ์๋ฌ์ฝ๋๋ ์๋์ง๋ง ๊ธ์๊ฐ ๊นจ์ ธ๋ณด์ด๋ ํ์์ด ๋ฐ์ํ์ต๋๋ค. ์ ํํ ์ด์ ๋ ์์์์ผ๋ OTFํ์ผ์ https://gero3.github.io/facetype.js/ ์ฌ์ดํธ์์ typeface๋ก ๋ณํํ๋๋ฐ ๋ญ๊ฐ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ ์๋๊ฐ ์ถ๋ค์.
์ดํ์๋ ์กฐ๋ช ๊ณผ ์กฐ๋ช ์ ์์น์๋ฐ๋ผ ํ ์คํธ์ ๋ช ์์ด ๋ค๋ฅด๊ฒ ์ค์ ๋๋ ๊ฒ์ ํ์ธํ๊ธฐ ์ํด
1. OrbitControls ์ถ๊ฐ
2. lil-gui ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น ๋ฐ GUI ์ค์ ์ถ๊ฐ
๋ฅผ ์งํํด์ฃผ์์ต๋๋ค.
๊ณ ๋ฌ๋ฉด ์๋ ๊ฒฐ๊ณผ๋ฌผ์ฒ๋ผ PoistionLight์ ์์น์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ๋ณด์ด๋ ํ ์คํธ ์ง์ค๋ฉํธ๋ฆฌ๋ฅผ ํ์ธํ์ค ์ ์์ต๋๋ค.
const ambientLight = new THREE.AmbientLight(0xffffff, 2);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 3);
const pointLightHelper = new THREE.PointLightHelper(pointLight, 0.5);
pointLight.position.set(3, 0, 2);
scene.add(pointLight, pointLightHelper);
gui.add(pointLight.position, "x").min(-3).max(3).step(0.1);
(p.s ๊ฐ์ฌ๋์ ambientLight, pointLight ๊ฐ์ ๋๋ค 0.5, 1์ ๋ก ์๊ฒ ์ค์ ํ์ ๋ ํ๋ฉด์์ ํ ์คํธ๊ฐ ๋ฐ๊ฒ ์๋ณด์ด๋๋ฐ ์ ๋ ์ด์ํ๊ฒ ์ข ์ด๋ก๊ฒ ๋ณด์ด๋๋ผ๊ตฌ์..? ๊ทธ๋์ ์กฐ๋ช ๊ฐ๋๋ฅผ ์ข ๋์๋๋ฐ ์ด ๋ถ๋ถ์ ๋์ค์ ์ถ๊ฐ๋ก ์์๋ด์ผํ ๊ฒ ๊ฐ์ต๋๋ค ใ กใ ใ ก)
โจ์ค๋์ ๊ฒฐ๊ณผ๋ฌผ
์ค๋์ ์ผ๋ฐ ํฐํธ๋ฅผ typeface.js ๋ก ๋ณ๊ฒฝํ๊ณ three.js ํ๋ก์ ํธ์ ์ ์ฉํ๋ ์์ ์ ์งํํ์ต๋๋ค. ์ ๋ฒ๊ฑฐ๋กญ๊ฒ typeface๋ผ๋ ํ์์ ์ฌ์ฉํ ๊น์ถ์๋๋ฐ ์๊ฐํด๋ณด๋ฉด js๋ฅผ ์ฌ์ฉํด์ ํฐํธ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฑฐ๋ฉด ํ์ด์ง ์ฑ๋ฅ ์ต์ ํ๋ ๋ค์ํ ๋ธ๋ผ์ฐ์ , OS์์๋ ์ผ๊ด์ฑ์ ์ ์งํ ์ ์๋ค๋ ์ฅ์ ์ด ์๋ ๊ฒ ๊ฐ์ต๋๋ค!
https://churchm.ag/standardizing-your-web-projects-with-typeface-js/
Standardizing Your Web Projects with Typeface.js - ChurchMag
One of the challenges that web developers face is providing a consistent experience across not only a variety of web browsers but operating systems, as well. This experience not only translates to the layout of a website, but the typography, too. There are
churchm.ag
โจ์ค๋์ ํ์ต ์ธ์ฆ ์ท
๋ณธ ํฌ์คํ ์ ํจ์คํธ์บ ํผ์ค ํ๊ธ ์ฑ๋ฆฐ์ง ์ฐธ์ฌ๋ฅผ ์ํด ์์ฑํ์์ต๋๋ค.
https://fastcampus.co.kr/event_online_challenge_2401_mission
์ปค๋ฆฌ์ด ์ฑ์ฅ์ ์ํ ์ต๊ณ ์ ์ค๋ฌด๊ต์ก ์์นด๋ฐ๋ฏธ | ํจ์คํธ์บ ํผ์ค
์ฑ์ธ ๊ต์ก ์๋น์ค ๊ธฐ์ , ํจ์คํธ์บ ํผ์ค๋ ๊ฐ์ธ๊ณผ ์กฐ์ง์ ์ค์ง์ ์ธ '์ (ๆฅญ)'์ ์ฑ์ฅ์ ๋๊ณ ์ ๋ชจ๋ ์ข ๋ฅ์ ๊ต์ก ์ฝํ ์ธ ์๋น์ค๋ฅผ ์ ๊ณตํ๋ ๋ํ๋ฏผ๊ตญ No. 1 ๊ต์ก ์๋น์ค ํ์ฌ์ ๋๋ค.
fastcampus.co.kr