codepen&etc

3D 애니매이션 threejs로 만들어 보기

grovy 2023. 3. 22. 09:45
728x90

 

 

three.js란? 

three.js는 컴퓨터내의 그래픽카드 리소스를 사용해서 좀더 부드럽게 동작이 가능해요 

웹 브라우저에서 3차원 컴퓨터 그래픽스 애니메이션 응용을 만들고 표현하기 위해 사용되는 JS 라이브러리입니다 

 

어떻게 그게 가능하죠 ? ?

Three.js는 웹페이지에 3D 객체를 쉽게 랜더링할 수 있도록 도와주는 Javascript 3D 라이브러리에요
WebGL 기술을 기반으로 랜더링과 카메라, 조명 등의 3D 프로그래밍 기술을 간단하게 사용하게끔 만들어줘요 ! 

 

소스를 보면서 같이 작업해 볼게요 ! 

소스보기 ! 

 

1 . Importing 

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.min.js"></script>

저같은경우 주소를 임포트했어요 . 임포트하던 직접 다운받던 선택해서 우선적으로 작업하셔야 해요 ! 

 

2. Three.js는 크게 Scene, Camera, Renderer으로 나뉘어요 !  

아래 소스 주석상세하게 달아놨으니 참조해주세요 ! 

let renderer, scene, camera, composer, tryangle, skelet, particle;
function init(){
    //렌더링 설정 
    renderer = new THREE.WebGLRenderer({antialias:true,  alpha: true});
    renderer.setPixelRatio((window.devicePixelRatio) ? window.devicePixelRatio : 1);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.autoClear = false;
    renderer.setClearColor(0x000000,0.0);
    
    //바디안에 <div id="canvas"></div>에 작업물을 추가하는거에요
    document.getElementById("canvas").appendChild(renderer.domElement);

    //scnen & 카메라 설정 ! 
    scene = new THREE.Scene();
    camera= new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.z =400;
    scene.add(camera);

    //도형설정 삼각형, 삼각형 실선, 하트 
    tryangle = new THREE.Object3D();
    skelet = new THREE.Object3D();
    particle = new THREE.Object3D();

    //scene 설정한 도형을 scene(화면)에 추가
    scene.add(tryangle);
    scene.add(skelet);
    scene.add(particle);


    //삼각형 작은모델 추가 
    let geom = new THREE.OctahedronGeometry(4,0);
    let mat = new THREE.MeshPhongMaterial({
        color : 0xffffff,
        shading : THREE.FlatShading
    });
    let planet = new THREE.Mesh(geom,mat);
    
   	//위치지정
    planet.scale.x = planet.scale.y = planet.scale.z = 16;
    tryangle.add(planet);

    //삼각형 실선 큰모델 추가 
    let geom2 = new THREE.OctahedronGeometry(10,0);
    let mat2 = new THREE.MeshPhongMaterial({
        color : 0xffffff,
        wireframe: true,
        side : THREE.DoubleSide
    });

    let planet2 = new THREE.Mesh(geom2, mat2);
    //위치지정
    planet2.scale.x = planet2.scale.y = planet2.scale.z = 16;

    skelet.add(planet2);

    //particle추가 heart모양이에요 ! 
    const heartShape = new THREE.Shape();
    const x = 0, y = 0;
    heartShape.moveTo( x + 5, y + 5 );
    heartShape.bezierCurveTo( x + 5, y + 5, x + 4, y, x, y );
    heartShape.bezierCurveTo( x - 6, y, x - 6, y + 7,x - 6, y + 7 );
    heartShape.bezierCurveTo( x - 6, y + 11, x - 3, y + 15.4, x + 5, y + 19 );
    heartShape.bezierCurveTo( x + 12, y + 15.4, x + 16, y + 11, x + 16, y + 7 );
    heartShape.bezierCurveTo( x + 16, y + 7, x + 16, y, x + 10, y );
    heartShape.bezierCurveTo( x + 7, y, x + 5, y + 5, x + 5, y + 5 );

    let geometry = new THREE.ShapeGeometry(heartShape);
    let marerial = new THREE.MeshBasicMaterial({
        color: 0xff0000
        // shading: THREE.Flatshading
    });


    //particle추가 heart모양이에요 for문을 돌려 Math.random()구문으로 임의의위치에 1000개 추가했어요 ! 
    for(let i=0 ; i <1000 ; i++){
        let mesh = new THREE.Mesh(geometry, marerial);
        mesh.position.set(Math.random()-0.5, Math.random()-0.5,Math.random()-0.5 ).normalize();
        mesh.position.multiplyScalar(90+ (Math.random()*700));
        mesh.rotation.set(Math.random()*2,Math.random()*2,Math.random()*2);
        particle.add(mesh);
    }

    //조명
    //조명이 없으면 색상이 어떤색인지 보이지 않아요 조명부분을 scene에 추가하지 않을경우 검은색 도형만 보임!
    let lights =[];
    lights[0] = new THREE.DirectionalLight(0xffffff, 1);
    lights[0].position.set(1,0,0);
    lights[2] = new THREE.DirectionalLight(0x11e8bb, 1);
    lights[2].position.set(0.75,0,0.75);
    lights[3] = new THREE.DirectionalLight(0x8200c9, 1);
    lights[3].position.set(-0.75,-1,0.5);

    scene.add(lights[0]);
    scene.add(lights[1]);
    scene.add(lights[2]);

    let ambientLight = new THREE.AmbientLight(0x999999);
    window.addEventListener("resize", onWindowResize, false);
    scene.add(ambientLight);
}

//리사이징시 camera 위치 조정 
function onWindowResize(){
    camera.aspect = window.innerWidth /window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
}

//requestAnimationFrame을 통해 animate()재귀함수를 실행시켜요 
//각 도형들의 rotation을 설정해서 움직임을 정해요 ! 
function animate(){
    requestAnimationFrame(animate);
    tryangle.rotation.x -=0.005;            
    tryangle.rotation.y -=0.007;

    skelet.rotation.x +=0.02;            
    skelet.rotation.y +=0.04;

    particle.rotation.x +=0.001;            
    particle.rotation.y +=0.004;
    renderer.render(scene, camera);
    render.clear();
}

 

https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene

 

three.js 위 링크 참조하여 작업했고 docs가 잘되있어서 어려움이 없었어요 

 

직접적으로 3d를 작업하려면 블랜더로 직접 3d모델링해야 하는데 기초적인 모델이라 그럴 필욘 없었어요

케릭터를 직접적으로 만들려면 작업해야하지만... 간단한건 스크립트로만 구현이 가능해서 좋았어요