Three.js

notion image
[1](images/1.png)
notion image
![2](images/2.png)
notion image
![3](images/3.png)
notion image
![4](images/4.png)
Β 
--- title: "Three.js" author: "μž„ν›ˆ" date: 2024-11-01T14:00:04+09:00 category: ["POSTS"] tags: ["React"] og_image: "/images/gamer.png" keywords: ['React', 'Three.js'] --- ## Three.jsλž€ ![1](images/1.png) - Renderer : Sceneκ³Ό Camera객체λ₯Ό λ„˜κ²¨ λ°›λŠ”λ‹€. 3D씬을 평면(2차원) μ΄λ―Έμ§€λ‘œ λ Œλ”λ§ν•œλ‹€. - Scene Graph : Node(μš”μ†Œ)λ₯Ό κ³„μΈ΅κ΅¬μ‘°λ‘œ 그림으둜 λ‚˜νƒ€λ‚Έ 것. ![2](images/2.png) ![3](images/3.png) * 지역곡간 : νƒœμ–‘μ΄ λ΄€μ„λ•Œ, νƒœμ–‘μ„ κ³΅μ „ν•˜λŠ” 지ꡬ, 지ꡬλ₯Ό κ³΅μ „ν•˜λŠ” 달 , κ΄€μ μ°¨μ΄λ‘œ 지역곡간이 ν˜•μ„±λœλ‹€. ## Three.js + react κΈ°λ³Έ νŠœν† λ¦¬μ–Ό + μ½”λ“œ - Three jsλŠ” λΈŒλΌμš°μ €μ—μ„œ 3D κ·Έλž˜ν”½μ„ 더 μ‰½κ²Œ 생성할 수 있게 ν•΄μ£ΌλŠ” λΌμ΄λΈŒλŸ¬λ¦¬μž…λ‹ˆλ‹€ - μΊ”λ²„μŠ€ + WebGL을 μ‚¬μš© ν•˜μ—¬ 3D λͺ¨λΈκ³Ό μ• λ‹ˆλ©”μ΄μ…˜μ„ ν‘œμ‹œν•©λ‹ˆλ‹€. - react-three-fiber λŠ” μ›Ή 및 react-native용 React λ Œλ”λŸ¬ 둜, Three.jsλ₯Ό μ‚¬μš©ν•˜μ—¬ 3D λͺ¨λΈ 및 μ• λ‹ˆλ©”μ΄μ…˜μ„ μƒμ„±ν•˜λŠ” 속도λ₯Ό ν–₯μƒμ‹œν‚΅λ‹ˆλ‹€. ### react-three-fiberthreeJSReact μƒνƒœ, 후크 및 μ†Œν’ˆμ„ μ‚¬μš©ν•˜μ—¬ μ½”λ“œ ꡬ성 μš”μ†Œ - mesh : λͺ¨λΈμ˜ λͺ¨μ–‘을 μ •μ˜ν•˜λŠ” 데 도움이 λ˜λŠ” 속성 - hooks : react-three-fiberμ •μ˜ 후크 도움이 우리의 도움과 같은 μ‚¬μš©μž 이벀트λ₯Ό μ •μ˜ν•˜λŠ” 것이 ν•¨μˆ˜λ₯Ό μž‘μ„±ν•˜λŠ” 것이 onClick 및 onPointOver ```jsx import React, { useRef, useState, useMemo } from "react"; import { Canvas, useFrame } from "@react-three/fiber"; import * as THREE from "three"; import Doge from "./assets/streamline-icon-dogecoin@400x400.png"; import { OrbitControls, Stars } from "@react-three/drei"; import "./app.css"; const Box = (props) => { const mesh = useRef(); const [active, setActive] = useState(false); useFrame(() => { mesh.current.rotation.x = mesh.current.rotation.y += 0.01; }); const texture = useMemo(() => new THREE.TextureLoader().load(Doge), []); return ( <mesh {...props} ref={mesh} scale={active ? [2, 2, 2] : [1.5, 1.5, 1.5]} onClick={(e) => setActive(!active)} > <boxBufferGeometry args={[1, 1, 1]} /> <meshBasicMaterial attach="material" transparent side={THREE.DoubleSide}> <primitive attach="map" object={texture} /> </meshBasicMaterial> </mesh> ); }; function App() { return ( <Canvas> <Stars /> <ambientLight intensity={0.5} /> <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} /> <pointLight position={[-10, -10, -10]} /> <Box position={[-1, 0, 0]} /> <Box position={[2.5, 0, 0]} /> </Canvas> ); } export default App; ``` ### `<BoxBufferGeometry>` vs `<BoxGeometry>` * `<BoxGeometry>`λŠ” μ‘°μž‘μ— μ’‹λ‹€. μ €μž₯이 μž˜μ•ˆλ˜λŠ” 단점 ```js 정점을 μˆ˜μ •ν•˜λ €λ©΄.. //with Geometry you just get vertex 5 and have access to it's x... //AND the methods of the class -> Vector3.add(Vector3) myGeom.vertices[5].add(new THREE.Vector3(1,2,3)) ``` * `<BoxBufferGeometry>` WebGL μΉœν™”μ μΈ ν˜•μ‹, λ Œλ”λ§μ— μ’‹κ³  μ €μž₯ν•˜κΈ° μ’‹μ§€λ§Œ μ‘°μž‘μ΄ νž˜λ“€λ‹€. ```js 정점을 μˆ˜μ •ν•˜λ €λ©΄.. //xyz are just numbers, so with a stride of 3 //we select x , and then the next two for y and z //we have to know that the 15th number in this array is x of vertex 5... const stride = 3 const index = 5 let offset = index * stride myGeom.attributes.position.array[offset++] += 1 myGeom.attributes.position.array[offset++] += 2 myGeom.attributes.position.array[offset ] += 3 ``` * Mesh μ΄λ²€νŠΈν•Έλ“€λŸ¬ ![4](images/4.png) [Load 3D Models in glTF Format](https://discoverthreejs.com/book/first-steps/load-models/)