React/ReactThreeFiber

Light & Shadow

최 수빈 2025. 3. 7. 02:56

 

Light & Shadow 

React Three Fiber(R3F)에서 빛과 그림자는 3D 장면을 보다 현실감 있게 만드는 요소

 

빛이 없다면 아무것도 보이지 않으며, 그림자가 없다면 입체감이 부족하게 보일 수 있음

현실 세계를 가상으로 모방하는 3D 그래픽에서는 빛과 그림자의 효과를 적절하게 조절하는 것이 필수적

 

 

빛(Light)

  • ambientLight : 장면 전체를 균일하게 밝게 비춤
  • pointLight : 특정 위치에서 전 방향으로 빛을 방출
  • spotLight : 특정 위치에서 원뿔 형태로 빛을 쏨
  • directionalLight : 태양광처럼 특정 방향에서 평행하게 빛을 쏨

 

ambientLight (전체적인 밝기 조절)

<ambientLight intensity={0.7} />

 

 

directionalLight (태양광과 같은 평행한 빛)

<directionalLight
    castShadow
    intensity={2}
    target-position={[0, -1, 0]}
    shadow-mapSize={[5000, 5000]}
    position={[-4, -2.1, 4]}
/>

 

 

빛의 위치 조절

position={[-4, -2.1, 4]}
  • 빛의 위치를 설정하면, 조명의 방향과 강도를 조절 가능

 

useHelper를 활용한 빛의 방향 확인

Helper

장면(Scene) 내 특정 요소의 시각적 디버깅을 돕는 도구

 

 

DirectionalLightHelper 사용

import { useHelper } from "@react-three/drei";
import { DirectionalLightHelper } from "three";
import { useRef } from "react";

const Elements = () => {
    const lightRef = useRef(null);
    useHelper(lightRef, DirectionalLightHelper, 1, "blue");

    return (
        <>
            <ambientLight intensity={0.7} />
            <directionalLight ref={lightRef} {...} />
        </>
    );
};
  • 빛이 어디에서 오는지 쉽게 확인 가능

 

그림자(Shadow)

 

3D 장면의 입체감을 강조하며, 물체가 공간에 위치하고 있음을 시각적으로 표현

 

 

그림자 활성화 단계

 

1. 빛에 그림자 활성화

<directionalLight castShadow ... />

 

2. 물체에 그림자 받기 활성화

<mesh receiveShadow ... />


3. Canvas에서 그림자 활성화

<Canvas shadows ... />

 

 

그림자 품질 조절

 

기본적으로 그림자는 계단현상이 있을 수 있음

→ 해상도를 조절하여 계단현상 개선

shadow-mapSize={[5000, 5000]}

 

빛의 방향 조절

target-position={[0, -1, 0]}
  • directionalLight의 방향을 조절할 수 있음

 

App.jsx

import './App.css'
import { useRef } from "react";
import { Canvas } from "@react-three/fiber";
import { OrbitControls, useHelper } from '@react-three/drei';
import { useLoader, useThree } from "@react-three/fiber";
import * as THREE from "three";

const CardData = [
  {
    imageUrl: "/card_1.jpg",
    position: [-1.1, -1.15, 0.4],
    rotationY: 10,
    rotationZ: 30,
  },
  {
    imageUrl: "/card_2.jpg",
    position: [-0.7, -1.05, 0.2],
    rotationY: 10,
    rotationZ: 10,
  },
  {
    imageUrl: "/card_3.jpg",
    position: [0, -1.05, 0],
    rotationY: 0,
    rotationZ: 0,
  },
  {
    imageUrl: "/card_4.jpg",
    position: [0.7, -1.15, -0.2],
    rotationY: -10,
    rotationZ: -10,
  },
  {
    imageUrl: "/card_5.jpg",
    position: [1.3, -1.30, -0.4],
    rotationY: -10,
    rotationZ: -30,
  },
]

const CardComponent = ({ position, rotationY, rotationZ, imageUrl }) => {
  const { scene } = useThree();
  const texture = useLoader(THREE.TextureLoader, imageUrl)
  texture.colorSpace = THREE.SRGBColorSpace;

  scene.rotation.set(0, 20, 0);

  const materials = [
    new THREE.MeshStandardMaterial(), // 오른쪽
    new THREE.MeshStandardMaterial(), // 왼쪽
    new THREE.MeshStandardMaterial(), // 윗면
    new THREE.MeshStandardMaterial(), // 바닥면
    new THREE.MeshStandardMaterial({ map: texture }), // 앞면 (이미지 적용)
    new THREE.MeshStandardMaterial({ map: texture }), // 뒷면 (이미지 적용)
  ];

  return (
    <mesh
      castShadow
      receiveShadow
      position={position}
      rotation-y={THREE.MathUtils.degToRad(rotationY)}
      rotation-z={THREE.MathUtils.degToRad(rotationZ)}
      material={materials}
    >
      <axesHelper />
      <boxGeometry args={[1, 1.6, 0.02]} />
    </mesh>
  )
}

const Elements = () => {
  const lightRef = useRef(null);
  useHelper(lightRef, THREE.DirectionalLightHelper, 1, "blue");
  return (
    <>
      <OrbitControls />
      <ambientLight intensity={1} /> {/* ambientLight : 환경광 (모든 방향에서 균일하게 씌워지는 빛)-모든 오브젝트가 동일한 강도로 조명을 받는 빛 */}
      <directionalLight
        castShadow ref={lightRef}
        intensity={3}
        target-positon={[0, -1, 0]}
        shadow-mapSize={[5000, 5000]}
        position={[-4, 2, 5]} />
      {
        CardData.map((props) => {
          return <CardComponent key={props.imageUrl} {...props} />

        })
      }
    </>
  )
}

function App() {
  return (
    <Canvas shadows>
      <Elements />
    </Canvas>
  );
}

export default App;

 

Light & Shadow

 

'React > ReactThreeFiber' 카테고리의 다른 글

Obj 3D & Transform  (0) 2025.03.06
Material & Texture  (1) 2025.03.05
Geometry  (0) 2025.03.04
GUI Controller  (2) 2025.03.03
3D 개발을 도와주는 도구들 - OrbitControls, AxesHelper, GridHelper  (0) 2025.03.02