티스토리 뷰
프론트엔드
[React.js 3D 에니메이션 만들기(2)] 3D text geometry 생성 및 조명 설정 with react three fiber
실전압축코딩 2024. 11. 20. 10:52https://ljy1011.tistory.com/224
이어서.
이번에는 react-trhee-fiber 를 활용해 3d text geometry를 생성해 보도록 하겠다.
설치 라이브러리
npm i three three-stdlib @react-three/fiber @react-three/drei @react-three/rapier framer-motion framer-motion-3d
1. three
- 설명: WebGL 기반 3D 그래픽을 쉽게 구현할 수 있는 JavaScript 라이브러리.
- 용도: 3D 모델링, 애니메이션, 조명, 텍스처 맵핑 등 3D 그래픽의 기본적인 빌딩 블록 제공.
2. three-stdlib
- 설명: Three.js의 추가 유틸리티 모음.
- 용도: OrbitControls, GLTFLoader 같은 자주 쓰이는 툴과 확장을 제공.
- 참고: 이 패키지는 Three.js의 확장 기능이 점점 자체 패키지로 분리되는 경향이 있어, 필요한 유틸리티를 제공함.
3. @react-three/fiber
- 설명: React에서 Three.js를 효율적으로 사용할 수 있도록 돕는 React Renderer.
- 용도: React 컴포넌트 기반으로 Three.js 오브젝트와 씬을 선언적으로 생성하고 관리.
4. @react-three/drei
- 설명: React Three Fiber를 위한 확장 컴포넌트 모음.
- 용도: OrbitControls, Text, Sky, Environment 등 추가적인 유용한 3D 구성 요소를 쉽게 사용할 수 있음.
5. @react-three/rapier
- 설명: Rapier(빠르고 경량의 물리 엔진)를 React Three Fiber와 통합하기 위한 라이브러리.
- 용도: 충돌 감지, 중력, 강체(Rigid Body) 등 물리 엔진 기능을 구현.
6. framer-motion
- 설명: React 애니메이션 라이브러리로 간단하면서 강력한 애니메이션 구현 가능.
- 용도: 모션 컴포넌트 및 키프레임 기반 애니메이션을 활용해 자연스러운 UI 동작 구현.
7. framer-motion-3d
- 설명: Framer Motion의 기능을 Three.js 오브젝트에도 확장한 라이브러리.
- 용도: React Three Fiber 환경에서 3D 오브젝트의 애니메이션을 간단히 작성.
구현
1. 주요 라이브러리와 설정
import { extend, Object3DNode, useFrame, useThree } from "@react-three/fiber";
import { FontLoader } from "three/examples/jsm/loaders/FontLoader";
import myFont from "../Roboto_Bold.json";
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry";
import { useEffect, useRef, useState } from "react";
extend({ TextGeometry });
- @react-three/fiber: React에서 Three.js를 효율적으로 사용할 수 있도록 돕는 라이브러리.
- FontLoader: Three.js에서 3D 텍스트를 생성하기 위해 사용하는 글꼴 로더.
- TextGeometry: 3D 텍스트를 생성할 때 사용하는 기하학 객체. three.js 로 부터 Import 한다.
- extend: TextGeometry를 React Three Fiber에서 사용할 수 있도록 확장.
폰트 파일(Roboto_Bold.json)을 FontLoader를 통해 로드한 후, 이를 3D 텍스트의 글꼴로 사용한다.
// Add types to ThreeElements elements so primitives pick up on it
declare module "@react-three/fiber" {
interface ThreeElements {
textGeometry: Object3DNode<TextGeometry, typeof TextGeometry>;
}
}
Three.js에서 제공하는 TextGeometry는 기본적으로 React Three Fiber에 포함되지 않으므로, 이를 사용하려면 추가적인 타입 선언이 필요하다. declare module을 설정해 주자.
2. TextGemetry component 생성
// @ts-ignore
const font = new FontLoader().parse(myFont);
const Impossible = () => {
return (
<group dispose={null} position={[-6.5, -0.5, 2.5]}>
<mesh receiveShadow castShadow rotation={[0, 0, -0.1]}>
<textGeometry
args={["I", { font: font, size: 2.5, height: 1 }]}
></textGeometry>
<meshStandardMaterial roughness={0.5} color="#ff0000" />
</mesh>
<mesh
receiveShadow
castShadow
rotation={[0, 0, -0.1]}
position={[1.2, 0, 0]}
>
<textGeometry
args={["mpossible", { font: font, size: 2, height: 1 }]}
></textGeometry>
<meshStandardMaterial roughness={0.5} color="#ff0000" />
</mesh>
</group>
);
};
- 구성 요소:
- group: 여러 개의 3D 객체를 하나로 묶는 컨테이너. group에 position을 설정하면 해당 위치에 객체가 생성된다.
- mesh: 3D 텍스트를 포함하는 요소로, textGeometry와 meshStandardMaterial을 사용.
- receiveShadow: 해당 객체가 그림자를 받을지 여부를 결정.
- castShadow: 해당 객체자 그림자를 생성할지 여부를 결정
- 텍스트 설정:
- args: ["텍스트 내용", { font, size, height }] 형태로 3D 텍스트의 속성 설정.
- font: 폰트 객체 (Roboto_Bold.json 사용).
- size: 텍스트 크기.
- height: 깊이(3D 텍스트의 두께).
- 색상 및 재질:
- meshStandardMaterial: 표준 재질로, roughness와 color 속성 설정.
- args: ["텍스트 내용", { font, size, height }] 형태로 3D 텍스트의 속성 설정.
3. 조명 설정하기
Three.js에서 조명은 3D 씬의 조도와 분위기를 설정하고 객체의 깊이와 입체감을 표현하는 데 필수적이다. 적절한 조명을 사용하면 장면의 사실감과 미적 표현을 극대화할 수 있다.
text에 조명을 주기 위해 3가지 조명을 적용해 보았다.
Three.js Lights
- AmbientLight (환경광)
- 설명: 씬 전체에 균일한 조명을 비춘다.
- 특징:
- 특정 방향성이 없음
- 그림자를 생성하지 않음
- 씬의 기본 밝기를 설정하는 데 유용
<ambientLight intensity={0.1} />
- DirectionalLight (직사광)
- 설명: 태양과 같은 무한한 거리에서 한 방향으로 빛을 비춘다.
- 특징:
- 특정 방향으로 평행한 빛을 방출
- 그림자를 생성할 수 있음
- 빛의 세기가 거리와 무관하게 동일
function DirectionalLight() {
const directionalLightRef = useRef();
useHelper(directionalLightRef, PointLightHelper, 1, "cyan");
const config = useControls("DirecLights", {
color: "#ffffff",
intensity: { value: 5, min: 0, max: 10, step: 0.1 },
position: { value: [0, 5, 10] },
});
return (
<directionalLight
ref={directionalLightRef}
transition={{ duration: 1 }}
{...config}
/>
);
}
- SpotLight (스포트라이트)
- 설명: 특정 방향으로 빛을 집중시켜 원뿔 모양으로 비춘다.
- 특징:
- 거리와 각도에 따라 빛이 감소
- 그림자를 생성 가능
- 원뿔 모양의 빛이 강조된 연출에 적합
function SpotLight() {
const spotLightRef = useRef();
useHelper(spotLightRef, PointLightHelper, 1, "cyan");
const config = useControls("SpotLights", {
color: "#ffffff",
intensity: { value: 300, min: 0, max: 5000, step: 0.1 },
position: { value: [0, 20, 12] },
angle: { value: 1, min: 0, max: 5, step: 0.1 },
});
return (
<spotLight
ref={spotLightRef}
transition={{ duration: 1 }}
shadow-mapSize-width={2048}
shadow-mapSize-height={2048}
shadow-bias={-0.00001}
castShadow
{...config}
/>
);
}
그림자를 투영할 planeGeometry 설정
{/* 그림자 바닥 */}
<mesh
receiveShadow
renderOrder={1000}
position={[0, 0, 0]}
rotation={[-Math.PI / 2, 0, 0]}
>
<planeGeometry args={[20, 20]} />
<motion.shadowMaterial transparent opacity={0.15} />
</mesh>
1. <mesh>
- 역할: Three.js에서 물체를 정의하는 기본 구성 요소로, 기하학(geometry)과 재질(material)을 결합하여 화면에 렌더링
- 속성:
- receiveShadow: 해당 물체가 그림자를 받을 수 있게 활성화.
- renderOrder={1000}: 렌더링 순서를 명시적으로 지정.
- 숫자가 높을수록 후순위에 렌더링됩니다.
- 그림자가 올바르게 보이도록 순서를 조정할 때 사용.
- position={[0, 0, 0]}: 평면의 위치를 원점에 배치.
- rotation={[-Math.PI / 2, 0, 0]}: 평면을 X축 기준으로 90도 회전하여 바닥처럼 놓이게 설정.
2. <planeGeometry>
- 역할: 2D 평면 기하 구조를 정의.
- 속성:
- args={[20, 20]}: 평면의 크기를 설정.
- 여기서는 폭 20, 높이 20의 큰 정사각형 평면을 생성.
- args={[20, 20]}: 평면의 크기를 설정.
3. <motion.shadowMaterial>
- 역할: 그림자가 투영될 때 사용되는 특수한 재질로, 그림자만 표시하고 투명한 영역은 배경과 혼합
- 속성:
- transparent: 재질의 투명도 활성화.
- 그림자가 있는 영역만 보이게 합니다.
- opacity={0.15}: 투명도 설정.
- 값이 낮을수록 그림자가 옅게 보입니다(15% 불투명).
- transparent: 재질의 투명도 활성화.
전체 역할
- 바닥 평면 생성:
- planeGeometry로 바닥 모양을 생성.
- rotation을 통해 평면을 아래로 눕힘.
- 그림자 렌더링:
- shadowMaterial을 사용해 그림자가 투명하게 투영될 수 있도록 설정.
- opacity로 그림자의 강도를 조절.
- 렌더링 우선순위 조정:
- renderOrder로 바닥 평면이 그림자보다 먼저 렌더링되도록 보장.
DirectionalLight 만 적용
SpotLight 만 적용
DirectionalLight & SpotLight 동시 적용
다음 글은 leva 라이브러리를 사용하여 light를 설정하는 방법을 다뤄보겠다.
'프론트엔드' 카테고리의 다른 글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- react 3d 에니메이션
- react 3d text
- react three fiber
- Vue.js
- vue3
- next.js import glsl
- rollup ts react npm
- 카카오 카드 짝 맞추기 자바스크립트
- react three fiber leva
- 카카오 2021 카드 짝 맞추기
- next.js glsl
- react 3d
- 카드 짝 맞추기 자바스크립트
- rollup typescript react
- leva
- webpack glsl
- three.js leva
- react fiber 3d
- typescript gsls
- react 3d animation
- vue
- rollup typescript
- eslint
- attempted import error: bvh_struct_definitions' is not exported from './gpu/bvhshaderglsl.js' (imported as 'bvhshaderglsl').
- 카드 짝 맞추기 javascript
- rollup react.js npm
- react leva
- react glsl
- 카카오 카드 짝 맞추기 javascript
- ts glsl
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함