📖 광원 (Light)
📌 광원의 종류
✅ Three.js 제공 광원과 Drei 제공 광원

📌 실습: R3F(Three.js)에서 제공하는 광원
✅ 기본 코드
import { OrbitControls } from "@react-three/drei";
import { useFrame } from "@react-three/fiber";
import * as THREE from "three"
const torusGeometry = new THREE.TorusGeometry(0.4, 0.1, 32, 32)
const torusMaterial = new THREE.MeshStandardMaterial({
color: "#9b59b6",
roughness: 0.5,
metalness: 0.9
})
function MyElement3D() {
useFrame((state) => {
const time = state.clock.elapsedTime
const smallSpherePivot = state.scene.getObjectByName("smallSpherePivot")
smallSpherePivot.rotation.y = THREE.MathUtils.degToRad(time * 50)
})
return (
<>
<OrbitControls />
<ambientLight color="#ffffff" intensity={5} />
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<planeGeometry args={[10, 10]} />
<meshStandardMaterial
color={"#2c3e50"}
roughness={0.5}
metalness={0.5}
side={THREE.DoubleSide}
/>
</mesh>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<sphereGeometry args={[1.5, 64, 64, 0, Math.PI]} />
<meshStandardMaterial
color={"#ffffff"}
roughness={0.1}
metalness={0.2}
/>
</mesh>
{new Array(8).fill().map((item, index) => {
return (
<group key={index} rotation-y={THREE.MathUtils.degToRad(45 * index)}>
<mesh
geometry={torusGeometry}
material={torusMaterial}
position={[3, 0.5, 0]}
/>
</group>
)
})}
<group name="smallSpherePivot">
<mesh position={[3, 0.5, 0]}>
<sphereGeometry args={[0.3, 32, 32]} />
<meshStandardMaterial
color={"#e74c3c"}
roughness={0.2}
metalness={0.5}
/>
</mesh>
</group>
</>
)
}
export default MyElement3D
✅ ambientLight
import { OrbitControls } from "@react-three/drei";
import { useFrame } from "@react-three/fiber";
import * as THREE from "three"
const torusGeometry = new THREE.TorusGeometry(0.4, 0.1, 32, 32)
const torusMaterial = new THREE.MeshStandardMaterial({
color: "#9b59b6",
roughness: 0.5,
metalness: 0.9
})
function MyElement3D() {
useFrame((state) => {
const time = state.clock.elapsedTime
const smallSpherePivot = state.scene.getObjectByName("smallSpherePivot")
smallSpherePivot.rotation.y = THREE.MathUtils.degToRad(time * 50)
})
return (
<>
<OrbitControls />
{}
<ambientLight color="#ff0000" intensity={10} />
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<planeGeometry args={[10, 10]} />
<meshStandardMaterial
color={"#2c3e50"}
roughness={0.5}
metalness={0.5}
side={THREE.DoubleSide}
/>
</mesh>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<sphereGeometry args={[1.5, 64, 64, 0, Math.PI]} />
<meshStandardMaterial
color={"#ffffff"}
roughness={0.1}
metalness={0.2}
/>
</mesh>
{new Array(8).fill().map((item, index) => {
return (
<group key={index} rotation-y={THREE.MathUtils.degToRad(45 * index)}>
<mesh
geometry={torusGeometry}
material={torusMaterial}
position={[3, 0.5, 0]}
/>
</group>
)
})}
<group name="smallSpherePivot">
<mesh position={[3, 0.5, 0]}>
<sphereGeometry args={[0.3, 32, 32]} />
<meshStandardMaterial
color={"#e74c3c"}
roughness={0.2}
metalness={0.5}
/>
</mesh>
</group>
</>
)
}
export default MyElement3D
✅ HemisphereLight
import { OrbitControls } from "@react-three/drei";
import { useFrame } from "@react-three/fiber";
import * as THREE from "three"
const torusGeometry = new THREE.TorusGeometry(0.4, 0.1, 32, 32)
const torusMaterial = new THREE.MeshStandardMaterial({
color: "#9b59b6",
roughness: 0.5,
metalness: 0.9
})
function MyElement3D() {
useFrame((state) => {
const time = state.clock.elapsedTime
const smallSpherePivot = state.scene.getObjectByName("smallSpherePivot")
smallSpherePivot.rotation.y = THREE.MathUtils.degToRad(time * 50)
})
return (
<>
<OrbitControls />
{}
<hemisphereLight args={["00f", "#f00", 2]} />
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<planeGeometry args={[10, 10]} />
<meshStandardMaterial
color={"#2c3e50"}
roughness={0.5}
metalness={0.5}
side={THREE.DoubleSide}
/>
</mesh>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<sphereGeometry args={[1.5, 64, 64, 0, Math.PI]} />
<meshStandardMaterial
color={"#ffffff"}
roughness={0.1}
metalness={0.2}
/>
</mesh>
{new Array(8).fill().map((item, index) => {
return (
<group key={index} rotation-y={THREE.MathUtils.degToRad(45 * index)}>
<mesh
geometry={torusGeometry}
material={torusMaterial}
position={[3, 0.5, 0]}
/>
</group>
)
})}
<group name="smallSpherePivot">
<mesh position={[3, 0.5, 0]}>
<sphereGeometry args={[0.3, 32, 32]} />
<meshStandardMaterial
color={"#e74c3c"}
roughness={0.2}
metalness={0.5}
/>
</mesh>
</group>
</>
)
}
export default MyElement3D
✅ directionalLight
import { OrbitControls, useHelper } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { useEffect, useRef } from "react";
import * as THREE from "three"
const torusGeometry = new THREE.TorusGeometry(0.4, 0.1, 32, 32)
const torusMaterial = new THREE.MeshStandardMaterial({
color: "#9b59b6",
roughness: 0.5,
metalness: 0.9
})
function MyElement3D() {
useFrame((state) => {
const time = state.clock.elapsedTime
const smallSpherePivot = state.scene.getObjectByName("smallSpherePivot")
smallSpherePivot.rotation.y = THREE.MathUtils.degToRad(time * 50)
smallSpherePivot.children[0].getWorldPosition(light.current.target.position)
})
const light = useRef()
useHelper(light, THREE.DirectionalLightHelper)
const {scene} = useThree()
useEffect(() => {
scene.add(light.current.target)
return () => {
scene.remove(light.current.target)
}
}, [light])
return (
<>
<OrbitControls />
{}
<directionalLight
ref={light}
color={"#0xffffff"}
intensity={1}
position={[5, 5, 0]}
target-position={[1, 0, 0]}
/>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<planeGeometry args={[10, 10]} />
<meshStandardMaterial
color={"#2c3e50"}
roughness={0.5}
metalness={0.5}
side={THREE.DoubleSide}
/>
</mesh>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<sphereGeometry args={[1.5, 64, 64, 0, Math.PI]} />
<meshStandardMaterial
color={"#ffffff"}
roughness={0.1}
metalness={0.2}
/>
</mesh>
{new Array(8).fill().map((item, index) => {
return (
<group key={index} rotation-y={THREE.MathUtils.degToRad(45 * index)}>
<mesh
geometry={torusGeometry}
material={torusMaterial}
position={[3, 0.5, 0]}
/>
</group>
)
})}
<group name="smallSpherePivot">
<mesh position={[3, 0.5, 0]}>
<sphereGeometry args={[0.3, 32, 32]} />
<meshStandardMaterial
color={"#e74c3c"}
roughness={0.2}
metalness={0.5}
/>
</mesh>
</group>
</>
)
}
export default MyElement3D
✅ pointLight
import { OrbitControls, useHelper } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { useEffect, useRef } from "react";
import * as THREE from "three"
const torusGeometry = new THREE.TorusGeometry(0.4, 0.1, 32, 32)
const torusMaterial = new THREE.MeshStandardMaterial({
color: "#9b59b6",
roughness: 0.5,
metalness: 0.9
})
function MyElement3D() {
useFrame((state) => {
const time = state.clock.elapsedTime
const smallSpherePivot = state.scene.getObjectByName("smallSpherePivot")
smallSpherePivot.rotation.y = THREE.MathUtils.degToRad(time * 50)
smallSpherePivot.children[0].getWorldPosition(light.current.position)
})
const light = useRef()
useHelper(light, THREE.PointLightHelper, 0.5)
return (
<>
<OrbitControls />
{}
<pointLight
ref={light}
color={"#ffffff"}
intensity={2}
position={[0, 5, 0]}
distance={0}
/>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<planeGeometry args={[10, 10]} />
<meshStandardMaterial
color={"#2c3e50"}
roughness={0.5}
metalness={0.5}
side={THREE.DoubleSide}
/>
</mesh>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<sphereGeometry args={[1.5, 64, 64, 0, Math.PI]} />
<meshStandardMaterial
color={"#ffffff"}
roughness={0.1}
metalness={0.2}
/>
</mesh>
{new Array(8).fill().map((item, index) => {
return (
<group key={index} rotation-y={THREE.MathUtils.degToRad(45 * index)}>
<mesh
geometry={torusGeometry}
material={torusMaterial}
position={[3, 0.5, 0]}
/>
</group>
)
})}
<group name="smallSpherePivot">
<mesh position={[3, 0.5, 0]}>
<sphereGeometry args={[0.3, 32, 32]} />
<meshStandardMaterial
color={"#e74c3c"}
roughness={0.2}
metalness={0.5}
/>
</mesh>
</group>
</>
)
}
export default MyElement3D
✅ spotLight
import { OrbitControls, useHelper } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { useEffect, useRef } from "react";
import * as THREE from "three"
const torusGeometry = new THREE.TorusGeometry(0.4, 0.1, 32, 32)
const torusMaterial = new THREE.MeshStandardMaterial({
color: "#9b59b6",
roughness: 0.5,
metalness: 0.9
})
function MyElement3D() {
useFrame((state) => {
const time = state.clock.elapsedTime
const smallSpherePivot = state.scene.getObjectByName("smallSpherePivot")
smallSpherePivot.rotation.y = THREE.MathUtils.degToRad(time * 50)
smallSpherePivot.children[0].getWorldPosition(light.current.target.position)
})
const light = useRef()
useHelper(light, THREE.SpotLightHelper)
const { scene } = useThree()
useEffect(() => {
scene.add(light.current.target)
return () => {
scene.remove(light.current.target)
}
}, [light])
return (
<>
<OrbitControls />
{}
<spotLight
ref={light}
color={"0xffffff"}
intensity={1}
position={[0, 5, 0]}
target-position={[0, 0, 0]}
distance={0}
angle={THREE.MathUtils.degToRad(30)}
penumbra={0.1}
/>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<planeGeometry args={[10, 10]} />
<meshStandardMaterial
color={"#2c3e50"}
roughness={0.5}
metalness={0.5}
side={THREE.DoubleSide}
/>
</mesh>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<sphereGeometry args={[1.5, 64, 64, 0, Math.PI]} />
<meshStandardMaterial
color={"#ffffff"}
roughness={0.1}
metalness={0.2}
/>
</mesh>
{new Array(8).fill().map((item, index) => {
return (
<group key={index} rotation-y={THREE.MathUtils.degToRad(45 * index)}>
<mesh
geometry={torusGeometry}
material={torusMaterial}
position={[3, 0.5, 0]}
/>
</group>
)
})}
<group name="smallSpherePivot">
<mesh position={[3, 0.5, 0]}>
<sphereGeometry args={[0.3, 32, 32]} />
<meshStandardMaterial
color={"#e74c3c"}
roughness={0.2}
metalness={0.5}
/>
</mesh>
</group>
</>
)
}
export default MyElement3D
✅ rectAreaLight
import { Environment, OrbitControls, useHelper } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { useEffect, useRef } from "react";
import * as THREE from "three"
import {RectAreaLightUniformsLib} from "three/examples/jsm/lights/RectAreaLightUniformsLib"
import {RectAreaLightHelper} from "three/examples/jsm/helpers/RectAreaLightHelper"
const torusGeometry = new THREE.TorusGeometry(0.4, 0.1, 32, 32)
const torusMaterial = new THREE.MeshStandardMaterial({
color: "#9b59b6",
roughness: 0.5,
metalness: 0.9
})
RectAreaLightUniformsLib.init()
function MyElement3D() {
useFrame((state) => {
const time = state.clock.elapsedTime
const smallSpherePivot = state.scene.getObjectByName("smallSpherePivot")
smallSpherePivot.rotation.y = THREE.MathUtils.degToRad(time * 50)
})
const light = useRef()
useHelper(light, RectAreaLightHelper)
return (
<>
<OrbitControls />
<Environment
blur={0.05}
background
files={"././public/images/blue_photo_studio_4k.hdr"}
/>
<rectAreaLight
ref={light}
color="#ffffff"
intensity={30}
width={2}
height={5}
position={[0, 5, 0]}
rotation-x={THREE.MathUtils.degToRad(-90)}
/>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<planeGeometry args={[10, 10]} />
<meshStandardMaterial
color={"#2c3e50"}
roughness={0.5}
metalness={0.5}
side={THREE.DoubleSide}
/>
</mesh>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<sphereGeometry args={[1.5, 64, 64, 0, Math.PI]} />
<meshStandardMaterial
color={"#ffffff"}
roughness={0.1}
metalness={0.2}
/>
</mesh>
{new Array(8).fill().map((item, index) => {
return (
<group key={index} rotation-y={THREE.MathUtils.degToRad(45 * index)}>
<mesh
geometry={torusGeometry}
material={torusMaterial}
position={[3, 0.5, 0]}
/>
</group>
)
})}
<group name="smallSpherePivot">
<mesh position={[3, 0.5, 0]}>
<sphereGeometry args={[0.3, 32, 32]} />
<meshStandardMaterial
color={"#e74c3c"}
roughness={0.2}
metalness={0.5}
/>
</mesh>
</group>
</>
)
}
export default MyElement3D
📌 실습: Drei 에서 제공하는 컴포넌트
✅ Environment
import { Environment, OrbitControls, useHelper } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { useEffect, useRef } from "react";
import * as THREE from "three"
import {RectAreaLightUniformsLib} from "three/examples/jsm/lights/RectAreaLightUniformsLib"
import {RectAreaLightHelper} from "three/examples/jsm/helpers/RectAreaLightHelper"
const torusGeometry = new THREE.TorusGeometry(0.4, 0.1, 32, 32)
const torusMaterial = new THREE.MeshStandardMaterial({
color: "#9b59b6",
roughness: 0.5,
metalness: 0.9
})
function MyElement3D() {
useFrame((state) => {
const time = state.clock.elapsedTime
const smallSpherePivot = state.scene.getObjectByName("smallSpherePivot")
smallSpherePivot.rotation.y = THREE.MathUtils.degToRad(time * 50)
return (
<>
<OrbitControls />
<Environment
blur={0.05}
background
files={"././public/images/blue_photo_studio_4k.hdr"}
/>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<planeGeometry args={[10, 10]} />
<meshStandardMaterial
color={"#2c3e50"}
roughness={0.5}
metalness={0.5}
side={THREE.DoubleSide}
/>
</mesh>
<mesh rotation-x={THREE.MathUtils.degToRad(-90)}>
<sphereGeometry args={[1.5, 64, 64, 0, Math.PI]} />
<meshStandardMaterial
color={"#ffffff"}
roughness={0.1}
metalness={0.2}
/>
</mesh>
{new Array(8).fill().map((item, index) => {
return (
<group key={index} rotation-y={THREE.MathUtils.degToRad(45 * index)}>
<mesh
geometry={torusGeometry}
material={torusMaterial}
position={[3, 0.5, 0]}
/>
</group>
)
})}
<group name="smallSpherePivot">
<mesh position={[3, 0.5, 0]}>
<sphereGeometry args={[0.3, 32, 32]} />
<meshStandardMaterial
color={"#e74c3c"}
roughness={0.2}
metalness={0.5}
/>
</mesh>
</group>
</>
)
}
export default MyElement3D