렌더러도 여러 종류가 있지만 보통 WebGLRenderer를 사용합니다.

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
//scene의 background를 설정하지 않았다면 밑의 코드로 배경색을 정할수도 있습니다.
// renderer.setClearColor(0x81ecec);
document.body.appendChild(renderer.domElement);

//실제 렌더링 하는 코드입니다.
renderer.render(scene, camera);

코드를 보시면 antialias에 true를 전달한 것이 보이시죠?

예전 게임들 보시면 캐릭터 등 모양이 각져 있는 것을 볼 수 있는데, 이는  사각형 점을 찍어서 모양을 나타내기 때문입니다. antialias는 형체의 끝부분과 연결된 부분을 배경색과 형체색의 중간색으로 해서 이 각진 부분을 부드럽게 만들어 주는 것입니다. 저는 이 옵션을 사용하겠다고 전달한 것입니다.

 

렌더링할 사이즈(캔버스의 크기)를 설정하신 다음 body태그에 renderer.domElement를 자식으로 추가해주시면 됩니다. renderer.domElement는 우리가 그린 것들이 담겨 있는 캔버스 태그입니다.

 

이제 모든 준비가 끝났으니 렌더 메소드에 scene과 camera를 전달해서 렌더링 해주시면 됩니다.

 

빈 배경화면 나타나게 됩니다.

 

모든 것을 다 scene에 더하고 렌더링을 했는데 왜 빈 배경화면만 나타나게 될까요? 이는 카메라와 오브젝트(mesh)가 겹쳐져 있기 때문에 그렇습니다. 카메라의 위치를 우리쪽으로 옮기던가 mesh의 위치를 뒤쪽으로 미뤄야 보이게 되는 것이죠.

document.body.appendChild(renderer.domElement);

//중간에 코드를 추가해주세요.
camera.position.z = 30;
mesh.rotation.x = (Math.PI * 20) / 180;
mesh.rotation.y = (Math.PI * 20) / 180;
//

renderer.render(scene, camera);

 

이제 다시 새로고침을 해볼까요?

예쁜 상자가 보입니다.

 

길었지만 드디어 예쁜 상자를 얻었습니다. 코드 중에서 궁금하실 부분은 (Math.PI * 20) / 180 부분이겠죠? 우선 먼저 설명할 것은 위치는 position 속성을 통해서 옮기지만 회전은 rotation 속성을 통해서 회전시킵니다. 똑같이 x, y, z 값을 줄 수 있기도 합니다.

 

three.js는 회전시킬 때 라디안을 사용합니다. Math.PI(자바스크립트에서 파이값을 반환 ) * 변환시킬 각도 / 180을 해주시면 해당하는 각도만큼 회전시킵니다.

 

 

 

이벤트 추가하기

예제를 좀 더 진행시켜보도록 하겠습니다. three.js나 여타 다른 상황에서라도 캔버스 태그를 사용할 때 주의할 점은 이벤트가 진행될 때나 오브젝트(mesh)에 어떤 상황이 일어날 때 브라우저가 하는 일은 기존에 그려져있던 것을 지우고, 다시 새로 정의된 값으로 그린다는 것입니다. 

 

우선은 웹 브라우저의 사이즈가 변경될 때 거기에 맞게 우리의 scene과 camera도 변경시키는 이벤트를 더해보도록 하겠습니다.

//Init 함수 내부에 이어서 적어주시면 됩니다.

const handleResize = () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.render(scene, camera);
};

window.addEventListener("resize", handleResize);

 

사이즈가 변경되면 카메라와 렌더러에 그 사이즈를 전달하고 다시 그리게 됩니다. 웹 브라우저의 크기를 변경해보세요. 잘 작동되나요? 

 

이번에는 상자를 돌려보도록 하겠습니다.

//Init 함수 내부에 이어서 적어주시면 됩니다.
//해당 코드는 상자를 회전시킵니다.

const rotateObj = () => {
    const speed = Math.floor(Math.random() * 3);
    mesh.rotation.y += (Math.PI * speed) / 180;
    renderer.render(scene, camera);
    requestAnimationFrame(rotateObj);
};
requestAnimationFrame(rotateObj);

함수를 일정시간 마다 계속 실행하도록 하는 것은 setInterval도 있습니다만 requestAnimationFrame을 함수를 재귀형식으로 사용한 이유는 자원을 절약하기 위해서 입니다. 가령 다른 탭을 눌러서 우리의 튜토리얼 화면에서 다른 화면을 볼 때는 실행되지 않다가 다시 화면을 볼 때 실행되는 것이죠. setInterval은 그런 것과 관련 없이 계속 실행되기 때문에 requestAnimationFrame을 사용했습니다.

 

상자가 돌아가니 신기하지 않나요?

 

 

 

인터랙션 추가하기

three.js에는 기본적으로 제공해주는 인터랙션들이 있습니다. 맨 처음엔 three.min.js 파일만 사용했지만 제공해주는 인터랙션을 사용하기 위해서는 풀버전을 받으셔야 합니다.

 

공식홈페이지에서 download를 누르면 three.js-master(용량이 꽤 큽니다.)를 다운로드 할 수 있습니다. 저는 다운로드 받은 후에 examples/js/controls 폴더를 복사해서 튜토리얼 폴더에 넣었습니다.

//index.html에는 해당 스크립트를 추가해주세요. 
//<script src="./controls/DragControls.js"></script>

mesh.rotation.x = (Math.PI * 20) / 180;
mesh.rotation.y = (Math.PI * 20) / 180;

//드래그 컨트롤을 추가해주세요.
//꼭 이 위치가 아니더라도 상관 없습니다.
const obj = [mesh];
const dragControls = new THREE.DragControls(obj, camera, renderer.domElement);

renderer.render(scene, camera);

 

코드는 아주 간단합니다. 드래그 컨트롤할 오브젝트들의 배열을 전달만 해주시면 됩니다. 아주 간단하죠?

전체소스

더보기
<!doctype html>
<html><head>
	<meta charset="UTF-8">
	<title>hello dragcontrols</title>
	<script type="text/javascript" src="./three.js"></script>
	<script type="text/javascript" src="./DragControls.js"></script>
</head>
<body>
<script>

const Init = () => {
    const WIDTH = window.innerWidth,
			HEIGHT = window.innerHeight;

    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x81ecec);

    const camera = new THREE.PerspectiveCamera(75, WIDTH / HEIGHT, 0.1, 1000);
    scene.add(camera);

    const geo = new THREE.BoxGeometry(5, 5, 5);
    const material = new THREE.MeshLambertMaterial({ color: 0x55efc4 });
    const mesh = new THREE.Mesh(geo, material);
    scene.add(mesh);

    const light = new THREE.PointLight();
    light.position.set(50, 50, 50);
    scene.add(light);

    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(WIDTH, HEIGHT);
    //renderer.setClearColor(0x81ecec);
    document.body.appendChild(renderer.domElement);

    camera.position.z = 30;
    mesh.rotation.x = (Math.PI * 20) / 180;
    mesh.rotation.y = (Math.PI * 20) / 180;
    
    const obj = [mesh];
    const dragControls = new THREE.DragControls(obj, camera, renderer.domElement);

    const rotateObj = () => {
        const speed = Math.floor(Math.random() * 3);
        mesh.rotation.y += (Math.PI * speed) / 1000;	//180->1000
        renderer.render(scene, camera);
        requestAnimationFrame(rotateObj);
    };
    requestAnimationFrame(rotateObj);
};

window.addEventListener("load", Init);


</script>
</body>
</html>

See the Pen VwYJQYO by 최충현 (@nenara) on CodePen.

 

 

 

 

 

 

 

출처 : https://justmakeyourself.tistory.com/entry/three-interaction?category=729470

 

+ Recent posts