Three.js 란?
Three.js 는 웹페이지에서 3D객체를 쉽게 렌더링 할수있게 도와주는 라이브러리입니다.
WebGL을 사용하여 3D를 구현하는데 자세한 구조설명등은 생략하고 실질적으로 사용하는 내용으로만
작성하여 나가겠습니다.
좀더 자세한 내용을 원하시면
three.js – JavaScript 3D library
threejs.org
위 공식 사이트에서 찾아보실수 있습니다
현재 라이브러리는 모듈로 불러와서 사용하는게 대부분인듯 합니다
하지만 IE에서도 동작을 해야한다면 모듈을 사용할수 없겠죠
그래서 모듈이 아닌 라이브러리를 사용하겠습니다
우선 Three.js 를 불러옵니다
<script src="js/three.js-master/build/three.js"></script>
그리고 HTML에 캔버스를 만들 Container 를 만들겠습니다
<body>
<div id="container"></div>
</body>
이제 Script를 작성하여 Canvas 를 Container에 추가해보겠습니다.
const renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
var container = document.getElementById('container');
var canvas = renderer.domElement;
container.appendChild(renderer.domElement);
const renderer = new THREE.WebGLRenderer({antialias:true});
renderer를 생성합니다. new THREE.WebGLRenderer(); 만 호출하여도 되지만
안티 에일리어싱 을 사용할 것이기 때문에 옵션값을 추가했습니다.
setPixelRatio , setSize 로 픽셀비율과 사이즈를 정하는데 저는 전체화면에 띄우기위해
윈도우의 사이즈와 픽셀비율을 불러와 set 하였습니다.
그리고 container 를 불러와 renderer 에서 뽑은 Canvas를 caonrainer의 자식으로 추가합니다.
3D객체를 그릴 판을 만들었으니 이제 그 판을 볼 카메라를 추가해 줍니다.
const fov = 75;
const aspect = window.innerWidth / window.innerHeight;
const near = 0.1;
const far = 500;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
fov 는 카메라 화각, aspect 는 화면비율, near 는 카메라 시작점, far 는 카메라 끝 점 입니다.
기본으로 생성된 카메라의 위치는 0,0,0 이므로 생성한 객체를 보기위해 살짝 이동시켜보겠습니다.
camera.position.z = 2;
이제 정육면체를 만들어서 넣어보겠습니다.
캔버스에 객체를 넣기위해 Scene에 추가해야합니다. 먼저 씬을 만들겠습니다.
그리고 정육면체를 만들어서 해당 씬에 추가를 해보겠습니다.
const scene = new THREE.Scene();
const boxWidth = 1;
const boxHeight = 1;
const boxDepth = 1;
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
const material = new THREE.MeshBasicMaterial({color: 0x44aa88});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
renderer.render(scene, camera);
new THREE.Scene();
씬을 생성하고 박스의 크기를 설정하는
new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
사이즈는 1 , 1 , 1 로 정육면체의 정보입니다.
그리고 정육면체의 재질 정보를 넣어줍니다.
new THREE.MeshBasicMaterial({color: 0x44aa88});
컬러값은 CSS의 RGB의 코드와 동일하게 사용할수있습니다.
이제 크기와 재질의 정보를 만들었으니 실질적인 상자를 생성합니다.
new THREE.Mesh(geometry, material);
자 이제 생성된 상자를 씬에 추가하고 renderer.render(scene, camera); 로 랜더링을 해줍니다
캔버스에 해당 씬을 해당 카메라로 랜더링 하는것입니다.
위 소스까지만 적용하면 3D인지 확인이 안되니 애니메이션을 통하여 돌아가도록 해보겠습니다.
function render(time) {
time *= 0.001; // convert time to seconds
cube.rotation.x = time;
cube.rotation.y = time;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
애니메이션을 만들기위해 requestAnimationFrame 함수를 통하여 루프 안에서 랜더링을 해줍니다.
하지만 광원이 없기때문에 음영이 보이질 않아서 3D같지가 않습니다
이제 광원도 추가하고 재질도 반사가 가능한것으로 바꾸어서 추가해보겠습니다
MeshBasicMaterial 을 MeshPhongMaterial 으로 바꾸어 주고 직사광 하나를 추가하겠습니다.
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
scene.add(light);
}
광원의 색은 흰색 쌔기는 1 로
new THREE.DirectionalLight() 를 호출하여 생성하고 광원의 위치를 왼쪽으로 1 높이 2 위로 4 올린것입니다.
X, Y, Z 순인데 좌우, 위아래, 앞뒤 가 적용됩니다.
이제 광원과 재질의 빛 반사,음영이 생겨서 3D로 보이게 되었습니다.
아래는 전체 소스입니다.
function main3D(){
const renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(200, 200);
var container = document.getElementById('container3d');
var canvas = renderer.domElement;
container.appendChild(renderer.domElement);
const fov = 75;
const aspect = 1;
const near = 0.1;
const far = 5;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 2;
const scene = new THREE.Scene();
const boxWidth = 1;
const boxHeight = 1;
const boxDepth = 1;
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
const material = new THREE.MeshPhongMaterial({color: 0x44aa88});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
scene.add(light);
}
function render(time) {
time *= 0.001; // convert time to seconds
cube.rotation.x = time;
cube.rotation.y = time;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main3D();
아래 보여지는 사이즈를 맞추기위해 좌우 200px 로 맞추고 컨테이너의 id 도 바꾸었습니다.
캔버스의 비율은 1:1 이므로 카메라의 aspect를 1로 변경하였습니다.