three js 는 자바스크립를 기반으로한 WebGl엔진을 사용해서 3D인터렉티브한 웹을 쉽게 만들수있는 라이브러리이다
HTML5의 Canva로 그려진다.
three.js is a JavaScript-based WebGL engine that can run GPU-powered games and other graphics-powered apps straight from the browser. The three.js library provides many features and APIs for drawing 3D scenes in your browser.
-mdn web doc
그래픽을 계산하여 렌더링하는 Hardware rendering과 Software rendering 있는데
software rendering: cpu로만 계산하여 렌더링
Hardware rendering: GPU의 도움을 받아 그래픽을 계산하여 렌더링
GPU의 도움을 받아 렌더링을 하기때문에 cpu의 부담을 덜어주어 작업을 분산해준다.
HTML5의 canvas를 통해 좌표로 그려지는 2D 또 3D를 통해 여러 그래픽을 그려낼수있는데 코드가 상당히 복잡해지기 때문에 three.js를 통해 보다 쉽게 구현가능하고 이런 three.js 기반으로 만들어진 renderer가 R3F (React three fiber)이다.
R3F를 사용하는 큰이유는 여러가지 built-in hook(useFrame, useThree)을 사용해서 애니메이션또는 객체에 접근이 쉽고, 또한 개발 생태계에서 사용하는 여러 추가적인 요소들을 사용할수있어서이다 특히 drei 같은 helper 라이브러리는 three.js를 더욱 쉽게 구현하게 도와준다.
DOM/SVG :
→ HTML , XML 문법으로 작성할수있다.
→ 검색기능이 가능하다. SEO 가능하다.
Canvas:
→ JS로 작성가능하지만 검색기능을 할수없다 텍스트 검색 불가
→ DOM와 같이 픽셀이기때문에 깨짐
→ 성능적인 측면으로 우수 하지만 많은 요소일때만 차이가 난다 . (10000개 이상 요소들)
대표적으로 사용하는 라이브러리
SVG: D3.js
Canvas:
2D → p5.js, pixi.js(2D-Game)
3D → Three.js, Babylon.js
R3F + Three.js 에서 사용하는 개념 정리
Object3D: 가장 base 클래스로 3D.공간을 만들기 위한 속성들과 오브젝트를 조절하게 해주는 클래스 Scene 또한 여기에 들어가 있다. 3D를 위한 컨테이너
Mesh: 실제 모델로 사용되는 도구들을 사용. (Geometry객체 + material 객체)들을 활용해서 mesh 객체를 생성하여 scene에 추가.
Scene: 실제 찍히고 있는 장면
Camera: Scene 을 찍고있는 카메라
Renderer: 카메라를 통해 보이는 화면단
영화촬용을 예로 들면...
scene: 실제 찍히는 인물과 사물들
camera: scene을 찍고있는 카메라(위치, 각도, etc.. )
renderer: 카메라로 보이는 화면, 촬영된 화면
기존에 랜더링을 할때는 requestAnimationFrame 함수와 Renderer로 계속 호출을 해야한다, 하지만 R3F 에서는 useThree 랑 useFrame으로 미리 지정되어있는 함수를 호출해서 사용가능하다
useThree: size, gl ,camera, scene
useFrame:
state= webGL , frame으로 state 반영
delta= 랜덩링된 시간
orthographic camera 사용할려면 canvas에 orthographic 프로퍼티 따로 사용 따로 추가해줘야한다. + zoom(default 1)
<Canvas
//orthographic
camera={{
zoom: 100,
near: 1,
far: 20,
fov: 75,
position:[3,3,0]
}}
>
<ThreeElement/>
</Canvas>
Mesh :scene에 추가되는 객체 (geometry, material)
three.js에 원하는 모형이 없을때 직접 만들거나 인테넷에서 찾을수있다.
3D-modeling: 모델링은 4각형이 만들기 편하다 하지만 컴퓨터가 이해하기위해서는 3각형으로 변환해야된다.
geometry는 mesh 없이 사용불가하고, material은 geometry없이 사용이 불가능하다, 모형이 없기 때문에 당연하다.
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
....
<mesh
ref={boxRef}
rotation={[
THREE.MathUtils.degToRad(45),
THREE.MathUtils.degToRad(45),
0,
]}>
<boxGeometry />
<meshStandardMaterial color="red" />
</mesh>
list of geometry
https://threejs.org/docs/index.html#api/en/geometries/BoxGeometry
구현을 하다보면 다양한 각도에서 보고, 특히 leva 같은 helper는 구현한 결과를 확인할때 도움이 많이 되었다
gridHelper :
바탕에 grid를 표시해준다
args={[size ,division, colorCenterLine, colorGrid]}
- size: size of the grid (default: 10)//10meter
- division : number of division (default: 10)//10meter
- colorCenterLine: color of center line
- color Grid : color of lines of the grid

leva
GUI component that you can interact with scene
leva는 useControls를 사용할수있게 도와주는거일뿐, 바탕색을바꾸는건 three.js만으로도 가능하다. 미리보기 가능
....control
const grid = useControls({
segment: { value: 10, min: 2, max: 100, step: 1 },
});
<gridHelper args={[10, grid.segment]} />
.....
import {useControls} from 'leva'
const color = useControls({
value: 'green',
})
//Cavas 바탕색 바꾸기
<Canvas>
<color attach="background" args={[color.value]} />
<color attach="background" args={[green]}/>
</Canvas>

Position: 해당 Object에 위치
Scale: Object의 크기
Rotation: Object 의 각도, Radiant를 사용하고 있어서, THREE.MathUtils.degToRad(0) 을 사용해서 degree로 바꾸는 작업을 해줘야한다.
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
<mesh geometry={new THREE.BoxGeometry(1,1,1)}>
<meshStandardMaterial color="blue"/>
</mesh>
import {Box} from "@react-three/drei"
<Box position={[-2,0,0]}>
<meshStandardMaterial color="blue"/>
</Box>
Wireframe:
mesh 하나에 하나의 material 이 들어간다 따라서 wireframe 처럼 표시하고싶으면 따로 mesh를 추가해서 해야된다.
이번에 three.js + R3F을 배우면서 공부하며서 많은 속성들과 3D 그래픽을 다룰수있게되어 재밌으면서도 어떻게 프로젝트에 반영할지 고민이 많이 되었다. 여러가지 시도를 할수있고 무궁무진한 가능성을 가지고있어서 다양한걸 시도해보면서 추가할예정이다.