React에서 Threejs 사용 기록 📐

zaman·2022년 9월 15일
1

ETC

목록 보기
1/3
post-thumbnail

1. Three.js

three.js: js 3d modeling 라이브러리
공식 홈페이지에서 한글 설명을 지원하기 때문에 다른 공식문서에 보기 편했다. 시작전 한번 살펴보고 오자!

https://threejs.org

설치

npm install three
yarn add three

나는 설치하지 않고 examples에서 필요한 파일을 뽑아썼다.

기본 3요소


위 그림을 간단하게 설명하면

장면을 만듦 👉 그 안에 3D 오브젝트를 넣음 👉 카메라로 비추고 renderer를 통해 html 파일에서 보여줌

  1. scene
    : 생성한 오브젝트를 담는 도화지 역할
  • 최종 변수, 최상위 노드
  • mesh, 3D 오브젝트, light 등이 모여있음
  1. camera
    : 시점, scene에 담긴 장면을 화면에 담는 역할
  • scene 안팎에 위치 가능
  1. renderer
    : scene과 camera의 객체 데이터를 넘겨 받아 화면 안 이미지로 렌더링하는 역할
  • 브라우저에 렌더링!



Three.js 예시

사용한 gltf링크

1. 이미지 찾기

코딩 전 먼저 sketchfab에서 사용하고자 하는 이미지를 찾는다. 라이센스를 확인하는걸 잊지말자!
이미지를 찾았으면 GLTF형식으로 다운로드를 받아준다.

짧은 코드지만 html과 js 파일을 분리해서 작성했다.

2. html 작성

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="./style.css" />
    <script type="module" src="./main.js"></script>
  </head>
  <body>
    <canvas id="c" width="700" height="600"></canvas> 
  </body>
</html>

3. main.js 작성

import * as THREE from "../../build/three.module.js";
import { GLTFLoader } from "../../build/GLTFLoader.js";
import { OrbitControls } from "../../build/OrbitControls.js";

const canvas = document.querySelector("#c");

const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true }); // antialias: true --> 계단 현상 방지
// 색상 인코딩 방식
renderer.outputEncoding = THREE.sRGBEncoding;

// THREE.PerspectiveCamera: 원근법 적용
//THREE.OrthographicCamera: 원근법 적용 ㄴㄴ
const camera = new THREE.PerspectiveCamera(
  30,
  window.innerWidth / window.innerHeight,
  1,
  10000
);

// 마우스 컨트롤
const controls = new OrbitControls(camera, renderer.domElement);
camera.position.set(0, 20, 90);

controls.update();

// 조명
// 1. PointLight: A light that gets emitted from a single point in all directions
const PointLight = new THREE.PointLight(0xffffff, 1);
scene.add(PointLight);
// 2. DirectionalLight: A light that gets emitted in a specific direction
const DirectionalLight = new THREE.DirectionalLight(0xffffff, 1);
scene.add(DirectionalLight);
// 3. AmbientLight: A light globally illuminates all objects in the scene equally
const AmbientLight = new THREE.AmbientLight(0xffffff, 1);
scene.add(AmbientLight);

const loader = new GLTFLoader();
// gltf 파일 사용
loader.load("viking_room/scene.gltf", function (gltf) {
  scene.add(gltf.scene);
  renderer.render(scene, camera);
  // 애니메이션
  function animate() {
    requestAnimationFrame(animate); // 초당 60번 실행
    gltf.scene.rotation.y += 0.005; // y 축 회전
    controls.update();
    renderer.render(scene, camera);
  }
  animate();
});

➕ WebGL?

위 코드의 renderer 부분으로 보면 WebGLRenderer라는 함수가 보인다
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });

renderer는 알겠는데 그럼 WebGL은 뭐지?

WebGL: Web Graphics Library

  • 웹에서 2D 및 3D를 렌더링하기위한 JavaScript API
  • OpenGL ES 2.0 기반으로 HTML5의 canvas 위에 그려짐

찾아보니까 장점이 많이 나오긴 하는데 솔직히 이해 못했다 ㅎㅎ
다음에 또 공부해서 기록해 두어야겠다



2. react-three-fiber

설치

npm install @react-three/fiber
yarn add @react-three/fiber

react-three-fiber 예시

폴더 구조

.
├── App.tsx
├── components
│   └── Room.tsx
├── index.css
└── index.tsx

App.tsx

import { Canvas } from "@react-three/fiber";
import React from "react";
import Room from "./components/Room";

const color = 0xffffff;
const intensity = 1;

function App() {
  return (
    <Canvas
      camera={{
        fov: 30,
        near: 1,
        aspect: window.innerWidth / window.innerHeight,
        far: 1000,
        position: [0, 20, 90],
      }}
    >
      <pointLight color={color} intensity={intensity} />
      <directionalLight color={color} intensity={intensity} />
      <ambientLight color={color} intensity={intensity} />
      <Room />
    </Canvas>
  );
}

export default App;

Room.tsx

import React, { useRef, Suspense } from "react";
import * as THREE from "three";
import { useFrame } from "@react-three/fiber";
import { OrbitControls, useGLTF } from "@react-three/drei";

// npx gltfjsx scene.gltf로 생성(아래 링크 유튭 참조!)
function Model(props: any) {
  const { nodes, materials }: any = useGLTF("/scene.gltf"); // 동작만 확인했기 때문에 일단 any로 둠
  return (
    <group {...props} dispose={null}>
      <group rotation={[-Math.PI / 2, 0, 0]}>
        <group rotation={[Math.PI / 2, 0, 0]}>
          <mesh
            geometry={nodes.mesh_all1_Texture1_0.geometry}
            material={materials.Texture1}
          />
        </group>
      </group>
    </group>
  );
}

function Room() {
  const object3d = useRef<THREE.Object3D>(null!);
  useFrame((state, delta) => (object3d.current.rotation.y += 0.005));
  return (
    // object3D: 빈 지역 공간
    <object3D ref={object3d}>
      <OrbitControls />
      <Suspense fallback={null}>
        <Model />
      </Suspense>
    </object3D>
  );
}

export default Room;



후기

변환 자체는 react-three-fiber가 거의 다 해줘서 간단한데 GLTF 파일 경로때문에 몇시간을 삽질했다ㅠ

threeJS 아직은 잘 모르지만 신기하고 재미있었다! 이제 틈틈히 취미삼아 해봐야겠다 😎


참조
threejs 공식문서
코딩애플 - 웹 포트폴리오에 간지나게 3D 모델을 추가해보자(threeJS)
유튜브: https://www.youtube.com/watch?v=2jwqotdQmdQ&t=1476s
사진 출처: https://designbase.co.kr/threejs-03/

profile
개발자로 성장하기 위한 아카이브 😎

0개의 댓글