FRONT

내가 셋을 세면 시작하는 거야...!! 원!!!!! 투!!! 쓰리.js

뚜따따 2024. 11. 1. 18:47

 

밤새도록 돌아가는~ 자동차🎵

어찌저찌 돌아가는~ 내 인생 🎵

 

더보기


차례

  • 0. 쓰잘데기 없는 데모 (위에서 끝남)
  • 1. Three.js 모임 회고
  • 2. Three.js란?
    • 장면(Scene)
    • 카메라(Camera)
    • 렌더러(Renderer)
  • 3. 원시 모델 (Primitives)
    • 기하학(Geometry)
    • 재질(Material)
    • 조명(Lighting)
  •  4. 마치며

1. Three.js 모임 회고 (사실 감사글이자 반성글)

 
지난 10월 20일, 쓰리제이에스 킥오프를 다녀왔다. 기대를 그렇게 크게 하진 않았는데, 원규님께서 Three.js 발표를 하시며 지식을 꽂아 넣어주셨다. (그날,,, 그는 빛으로 이루어진 무언가셨다) 뇌로 직접 듣는 Three.js 발표를 해주신 원규님에 대한 감사한 마음을 여기에 다시 한 번 적는다. anyway 정말 값진 시간이었다. 
그리고 우리 조원들과도 말이 잘 통해 뒷풀이도 즐겁게 다녀웠다. 다들 너무 감사하게도 내 얘기(한강 작가님 노벨상 개쩔지 않아요?! MBTI 를 믿나여! etc etc)를  즐겁게 들어주셔서 조금 과하게 신이 나버렸던 것 같다. 너무 감사합니다! 이젠 강하게 나의 신남을 단속할 필요가 있다. anyway 좋은 주관들을 수집할 정말정말 값진 시간이었다.
 

2. Three.js란?

쓰리.js 란 무엇일까. Three.js는 사용하기 쉬운, 가볍고, 크로스 브라우저 호환성을 가진 자바스크립트 3D 라이브러리
라고 한다. 쉽고, 가볍고, 호환되는 3D 녀석이다!

오잉? 근데 3D 할 거면 Three.js 꼭 써야 해?

예전에 이런 걸 만든 적 있다.

멍하니 보고 있으면 왠지 기분이 좋다


CSS 의 transform 이랑 animation 으로 만들어진 걸 머리 안 쓰고 배껴와서 가공한 녀석이다.

'& .box': {
      position: 'relative',
      transformStyle: 'preserve-3d'
    },
    '& .box__face': {
      width: '100px',
      height: '100px',
      position: 'absolute',
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center',
      color: '#fff',
      fontSize: '1rem',
      borderRadius: '20%'
    },
    '& .--front': {
      background: '#e76554',
      opacity: '0.9',
      transform: 'rotateY(0deg) translateZ(50px)'
    },
    '& .--back': {
      background: 'rgba(98, 155, 206, 0.9)',
      transform: 'rotateY(0deg) translateZ(-50px) scaleX(-1)'
    },
    '& .--right': {
      background: 'rgba(80, 188, 223, 0.9)',
      transform: 'rotateY(90deg) translateZ(50px)'
    },
    '& .--left': {
      background: 'rgba(149, 98, 206, 0.9)',
      transform: 'rotateY(-90deg) translateZ(50px)'
    },
    '& .--top': {
      background: '#ABA45F',
      transform: 'rotateX(90deg) translateZ(50px)'
    },
    '& .--bottom': {
      background: '#A45FAB',
      transform: 'rotateX(-90deg) translateZ(50px)'
    }

원본 코드 출처: https://nykim.work/26
 

도메인에 따라서 간단한 CSS 와 html 로 빠르고 간결하게 3D 에니메이션을 뽑아내야 할 떄도 있을 거다. 그럴 때는 저렇게css 의 translate 를 써도 상관 없겠지만, 저 네모네모 주사위를 3D 그래픽스로 부르기는 좀 힘들어 보인다. 왜냐, 저 네모네모에겐 Three.js 의 특징 3가지가 없기 때문이다. 바로 요 녀석들이다.

  • 장면(Scene)
  • 카메라(Camera)
  • 렌더러(Renderer)

삼형제생성기 출처: http://vbcstatic.s3-website-us-west-2.amazonaws.com/brothers/ ㅋㅋㅋㅋ 지금 보니 글자 짤림 엌ㅋㅋㅋㅋ 죄송ㅋㅋㅋ


그럼 지금부터 삼형제를 한 명씩 만나러 가보자

장면(Scene)

출처: Three.js 메뉴얼 https://threejs.org/manual/#ko/fundamentals

위 도식화처럼 Scene은 Renderer 가 그려준 녀석 중 카메라를 제외한 모든 녀석이다. 위에서 말한 것처럼  '무대' 이다. 무대니까 카메라가 저래 위에 걸쳐 있다.
Mesh 와 Light 는 후술.

카메라(Camera)

어디서 무대를 보고 있는지를 나타낸다.

출처: Three.js 메뉴얼 https://threejs.org/manual/#ko/scenegraph 작은 탱크한테 걸리면 아주 뿅 되는거야!

 
위 3D Object 인 탱크의 시점이 변하는 것처럼, 카메라는 시야각, 시작과 끝 지점, 종횡비 같은 걸 설정한다.
 
카메라의 종류는 크게 원근 카메라정투영 카메라가 있는데, 일반적으로 원근 카메라가 쓰인다. 

1. 원근 카메라 (Perspective Camera)

  • 원근 카메라는 사람의 눈과 비슷하게 작동하여, 물체가 가까이 있을수록 크게 보이고 멀리 있을수록 작게 보이는 원근감을 표현한다
  • 용도: 게임, 시뮬레이션, 가상현실(VR) 등 현실적인 시각 효과가 필요한 장면에 주로 사용.
  • 주요 속성:
    • fov (Field of View): 카메라의 수직 시야각을 설정. 각도가 커질수록 더 넓은 범위를 볼 수 있다.
    • aspect (Aspect Ratio): 화면의 가로 세로 비율로, 일반적으로 캔버스의 크기 비율에 맞춘다.
    • near | far: 가까운(near) 곳과 먼(far) 곳의 거리 제한을 설정한다.
               
                const fov = 40;
                const aspect = 1;
                const near = 0.1;
                const far = 1000;
                const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 

 
Near 과 Far 개념이 잘 이해가 안 가서 near 을 100으로 올려봤다.

near 만 100 으로 올렸을 때
near 가 0.1 일때
near 가 0.001 일 때 (으악!)









near 과 far 가 의 값이 너무 멀어지게 되면 위처 서로 가까이 위치한 두 객체가 정확히 구분되지 않아, 떨리거나 깜박이는 시각적 오류가 발생한다
깊이 버퍼 정밀도 부족으로  발생하는 이 증상을 Z-파이팅이라고 부른다!

결론) 적당히 설정하자

2. 정투영 카메라 (Orthographic Camera)

  • 정투영 카메라는 물체의 원근감을 제거하여 거리에 상관없이 모든 객체가 동일한 크기로 보이게 한다. 물체의 형태가 왜곡되지 않으므로, 주로 건축 도면, UI 디자인, 2D 게임 등에 유용하다. 끝

렌더러(Renderer)

이렇게 쓴다. WEBGL 기술을 활용하며, 계단현상 막는 것 외로 그림자 등 여러 옵션을 제공한다.

       
        const rederer = new THREE.WebGLRenderer({
                canvas: document.querySelector('#c'),
                antialias: true,
                alpha: true
        });
 

 

3.  원시 모델 (Primitives)

Three.js의 원시 모델이란, 주로 런타임에서 다양한 인자들로 정의한 3D 모양을 의미한다. (ex 원뿔, n각형, 글씨 이런 거)

Geometry (기하학)

기하학은 3D 객체의 형태를 결정하는 데이터 구조이다. 점(Vertex), 면(Face), 
리고 각 점의 위치와 간격으로 객체의 기본 모양을 정의한다.

구성 요소

  • Vertex (정점): 3D 공간에서 객체의 특정 위치를 나타내는 좌표로, 기하학의 가장 기본 요소
  • Face (면): 정점들이 모여 이루는 면. 면을 여러 개 합쳐 3D 형태가 만들어진다.
  • Edges (모서리): 두 개의 정점을 연결하는 선분, 객체의 외형을 구성.
 

Material (재질)

시각적인 효과를 부여하는 요소.  빛을 반사하거나, 투명하거나, 색상을 가지도록 만든다.
 
재질 종류

  • MeshBasicMaterial: 빛의 영향을 받지 않는 단순한 색상 재질
  • MeshLambertMaterial: 부드러운 조명 효과가 필요한 경우 사용. 환경에 따라 색상이 조금씩 다르게 보인다.
  • MeshPhongMaterial: 광택 효과가 있는 재질로, 반사와 하이라이트 표현이 가능
  • MeshStandardMaterial: 물리 기반 렌더링(PBR) 재질로, 사실적인 표현이 필요할 때 사용된다.

조명(Lighting)

조명은 3D 장면에 사실감을 더하고, 각 객체가 시각적으로 구분되도록 하는 요소이다. 그 중에는 여러 조명이 있지만, 두 개가 주로 쓰이는 것 같으니, 두 개만 설명하겠다! (당당)

특성 PointLight AmbientLight
빛의 방향 한 지점에서 모든 방향으로 발산 방향성 없음, 모든 객체에 균일하게 적용
거리 감쇠 distance와 decay로 조절 가능 없음
그림자 생성 그림자 생성 가능 그림자 없음
용도 전구, 촛불 등 집중된 빛을 표현 장면의 기본적인 밝기를 조절하는 배경 조명

 

4. 마치며

[공부 -> 글쓰기] 를 통해 시간을 아끼고 더 효율적인 글쓰기를 할 예정이었건만 어째
[공부 -> 글쓰기 -> 아, 정리한 거 봐도 잘 모르겠네 -> 서칭 -> 공부 -> 글쓰기] 의 모양세가 되어 생가보다 시간이 오래 걸렸다. 퀄리티가 일정한 글을 유지하고자 노력했는데, 아무래도 실패한 것 같다. 다음엔 초반에 힘을 좀 더 빼고 들어가야지.. 어쨌든 정신 사나운 글을 끝까지 봐주셔서 감사합니다.

글 쓰는데 걸린 시간: 5시간 30분
 
참고 자료: Three.js docs
 

'FRONT' 카테고리의 다른 글

깊은 복사와 얕은 복사  (0) 2025.01.31
플러터 개쩐다  (2) 2025.01.19