[카테고리:] 미분류

  • Three.js 입문 가이드: 처음부터 멋진 예제까지

    Three.js는 웹에서 3D 그래픽을 쉽게 구현할 수 있게 해주는 JavaScript 라이브러리입니다. 복잡한 WebGL을 추상화하여 개발자가 3D 그래픽에 집중할 수 있게 해줍니다. 이 포스팅에서는 Three.js를 처음 접하는 분들을 위해 기초부터 멋진 예제를 만들어가는 과정을 단계별로 설명하겠습니다.

    1. Three.js 시작하기

    기본 셋업

    Three.js를 사용하기 위한 기본 HTML 구조부터 시작해봅시다:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>My First Three.js App</title>
        <style>
            body { margin: 0; overflow: hidden; }
            canvas { display: block; }
        </style>
    </head>
    <body>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
        <script>
            // Three.js 코드가 여기에 들어갑니다
        </script>
    </body>
    </html>
    

    기본 구성요소 이해하기

    Three.js로 무언가를 렌더링하기 위해 필요한 세 가지 핵심 요소가 있습니다:

    1. 장면(Scene): 모든 3D 객체가 배치되는 공간
    2. 카메라(Camera): 장면을 어떤 시점에서 볼지 결정
    3. 렌더러(Renderer): 장면과 카메라 정보를 받아 화면에 그려줌

    다음은 이 세 요소를 설정하는 코드입니다:

    // 장면 생성
    const scene = new THREE.Scene();
    
    // 카메라 생성 (시야각, 종횡비, 근거리 클리핑, 원거리 클리핑)
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.z = 5;
    
    // 렌더러 생성 및 설정
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    

    2. 첫 번째 3D 객체 만들기

    이제 간단한 큐브를 만들어 화면에 렌더링해 봅시다:

    // 큐브 지오메트리와 재질 생성
    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); // 장면에 추가
    
    // 애니메이션 루프 함수
    function animate() {
        requestAnimationFrame(animate);
        
        // 큐브 회전
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
        
        // 렌더링
        renderer.render(scene, camera);
    }
    
    animate();
    

    이 코드는 초록색 큐브를 생성하고 지속적으로 회전시키는 애니메이션을 보여줍니다.

    3. 재질과 조명 이해하기

    앞서 만든 큐브는 MeshBasicMaterial을 사용했는데, 이 재질은 조명의 영향을 받지 않습니다. 조명을 추가하고 조명에 반응하는 재질을 사용해 봅시다:

    // 기존 재질 대신 조명에 반응하는 재질 사용
    const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
    
    // 조명 추가
    const light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(5, 5, 5);
    scene.add(light);
    
    // 주변광 추가
    const ambientLight = new THREE.AmbientLight(0x404040);
    scene.add(ambientLight);
    

    Three.js는 다양한 재질을 제공합니다:

    • MeshBasicMaterial: 조명에 반응하지 않는 단순 색상
    • MeshLambertMaterial: 비광택 표면에 적합
    • MeshPhongMaterial: 광택이 있는 표면에 적합
    • MeshStandardMaterial: 물리 기반 렌더링에 적합

    4. 다양한 지오메트리 탐색하기

    Three.js는 다양한 내장 지오메트리를 제공합니다:

    // 구체
    const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
    const sphere = new THREE.Mesh(sphereGeometry, material);
    sphere.position.x = -3;
    scene.add(sphere);
    
    // 원뿔
    const coneGeometry = new THREE.ConeGeometry(1, 2, 32);
    const cone = new THREE.Mesh(coneGeometry, material);
    cone.position.x = 3;
    scene.add(cone);
    
    // 토러스(도넛)
    const torusGeometry = new THREE.TorusGeometry(0.5, 0.2, 16, 100);
    const torus = new THREE.Mesh(torusGeometry, material);
    torus.position.y = 3;
    scene.add(torus);
    

    5. 텍스처 추가하기

    단순한 색상 대신 텍스처를 사용하여 객체에 이미지를 입힐 수 있습니다:

    // 텍스처 로더 생성
    const textureLoader = new THREE.TextureLoader();
    
    // 텍스처 로드 및 재질에 적용
    const texture = textureLoader.load('https://example.com/texture.jpg');
    const material = new THREE.MeshStandardMaterial({ map: texture });
    
    // 텍스처가 적용된 큐브 생성
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    

    6. 사용자 상호작용 추가하기

    OrbitControls를 사용하면 마우스로 카메라를 회전, 확대/축소할 수 있습니다:

    <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
    

    그리고 JavaScript에서:

    // 컨트롤 생성
    const controls = new THREE.OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true; // 부드러운 애니메이션 효과
    controls.dampingFactor = 0.05;
    
    // 애니메이션 루프 함수 업데이트
    function animate() {
        requestAnimationFrame(animate);
        
        // 컨트롤 업데이트
        controls.update();
        
        renderer.render(scene, camera);
    }
    

    7. 응답형 디자인 구현하기

    브라우저 창 크기가 변경될 때 Three.js 캔버스도 조정되도록 합시다:

    // 윈도우 크기 변경 이벤트 리스너
    window.addEventListener('resize', () => {
        // 카메라 종횡비 업데이트
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        
        // 렌더러 크기 업데이트
        renderer.setSize(window.innerWidth, window.innerHeight);
    });
    

    8. 고급 예제: 인터랙티브 파티클 시스템

    이제 좀 더 멋진 예제를 만들어 봅시다. 마우스 움직임에 반응하는 파티클 시스템을 구현해보겠습니다:

    // 파티클 시스템 생성
    const particlesGeometry = new THREE.BufferGeometry();
    const particleCount = 5000;
    
    // 파티클 위치 배열 생성
    const positions = new Float32Array(particleCount * 3);
    const colors = new Float32Array(particleCount * 3);
    
    for (let i = 0; i < particleCount * 3; i++) {
        // 임의의 위치에 파티클 배치
        positions[i] = (Math.random() - 0.5) * 10;
        // 임의의 색상 설정
        colors[i] = Math.random();
    }
    
    particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    particlesGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
    
    // 파티클 재질
    const particlesMaterial = new THREE.PointsMaterial({
        size: 0.05,
        vertexColors: true,
        transparent: true,
        opacity: 0.8
    });
    
    // 파티클 메시 생성
    const particles = new THREE.Points(particlesGeometry, particlesMaterial);
    scene.add(particles);
    
    // 마우스 움직임 추적
    const mouse = new THREE.Vector2();
    window.addEventListener('mousemove', (event) => {
        // 마우스 좌표를 정규화 (-1 ~ 1 범위)
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
    });
    
    // 애니메이션 루프 업데이트
    function animate() {
        requestAnimationFrame(animate);
        
        // 파티클 움직임 업데이트
        const positions = particlesGeometry.attributes.position.array;
        
        for (let i = 0; i < particleCount; i++) {
            const i3 = i * 3;
            
            // 마우스 위치에 따라 파티클 이동
            positions[i3] += (mouse.x * 0.02) + (Math.random() - 0.5) * 0.01;
            positions[i3 + 1] += (mouse.y * 0.02) + (Math.random() - 0.5) * 0.01;
            
            // 경계 체크
            if (positions[i3] > 5) positions[i3] = -5;
            if (positions[i3] < -5) positions[i3] = 5;
            if (positions[i3 + 1] > 5) positions[i3 + 1] = -5;
            if (positions[i3 + 1] < -5) positions[i3 + 1] = 5;
        }
        
        particlesGeometry.attributes.position.needsUpdate = true;
        
        // 파티클 전체 회전
        particles.rotation.x += 0.001;
        particles.rotation.y += 0.002;
        
        renderer.render(scene, camera);
    }
    

    9. 다음 단계: Three.js 마스터하기

    Three.js의 기본 개념을 이해했다면, 다음 단계로 탐색해볼 수 있는 주제들입니다:

    1. 쉐이더 프로그래밍: GLSL을 사용하여 커스텀 비주얼 효과 만들기
    2. 물리 엔진 통합: Cannon.js나 Ammo.js 같은 물리 엔진과 Three.js 통합하기
    3. 후처리 효과: 블룸, 모션 블러, 깊이 효과 등 적용하기
    4. 3D 모델 불러오기: glTF, OBJ, FBX 등의 포맷으로 된 3D 모델 불러오기
    5. VR/AR 지원: WebXR API를 통한 가상 현실/증강 현실 구현하기

    결론

    Three.js는 강력하고 유연한 3D 라이브러리로, 웹에서 인상적인 3D 경험을 구현할 수 있게 해줍니다. 이 포스팅에서는 기본 개념부터 시작하여 점차 고급 기능으로 나아가며 Three.js의 기초를 다뤘습니다.

    멋진 Three.js 예제들은 상상력의 한계만큼 다양하게 만들 수 있습니다. 공식 웹사이트(https://threejs.org/)의 예제를 참고하고, 다양한 속성과 기능을 실험해보면서 자신만의 멋진 3D 웹 경험을 만들어보세요!

    여러분만의 Three.js 작품을 만들어 공유해주세요. 행운을 빕니다! 🚀