WebGL를 사용해서 3D 그래픽을 표현하려면 고급의 기술이 필요하다.

그래서 JavaScript 라이브러리를 통해 WebGL를 쉽게 다룰 수 있도록 Three.js를 사용한다.

일반 프로그래밍을 처음 접할때는 helloworld 를 만들어보지만 3D 프로그래밍 에서는 hello cube 를 만든다고 한다.

지금부터 hello cube 를 만들어보자

 

 

Three.js 준비

https://threejs.org/ 사이트에서 파일을 다운로드한다.

다운로드한 파일 (three.js-master) > build > three.js 파일을 사용하면 된다.

three.js를 쓰던 three.min.js를 쓰던 상관없다.

 

HTML 준비

three.js 와 같은 위치에 hellocube.html 파일을 만든다.

<!doctype html>
<html>
<head>
	<meta charset="UTF-8">
	<title>hello cube</title>
	<script type="text/javascript" src="./three.js"></script>
</head>
<body>
	<div id="WebGL-output"></div>
    
    
    
</body>
</html>

또는

<body>
    <div id="WebGL-output"></div>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.js"></script>
</body>

 

 

 

Scene 추가

Scene은 렌더링 할 모든 객체와, 광원을 저장하는 컨테이너이다.

THREE.Scene이 없으면 렌더링 할 수 없다!

var scene = new THREE.Scene();

 

 

Camera 추가

Camera는 어떻게 보일지 정의한다.

Camera에는 PerspectiveCamera가 OrthographicCamera 있지만, 나는 PerspectiveCamera를 쓰겠다.

PerspectiveCamera - 일상생활에서 우리가 보는 외관.

OrthographicCamera - 직교 카메라, 시점으로부터의 거리에 상관없이 모든 물체가 동일한 크기이다.

var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
 
camera.position.x = -25;
camera.position.y = 30;
camera.position.z = 25;
 
camera.lookAt(scene.position);

THREE.PerspectiveCamera(fov, aspect, near, far)

45도의 화각(카메라에 비치는 광경 범위를 각도로 나타낸 것), 화면 비율(가로 대 세로의 비율),

0.1(광경이 보이기 시작면까지의 거리), 1000(화면에서 가장 먼 반대편의 거리)

near, far - 오브젝트가 카메라에 얼마나 가까워지고 멀어져서 그려질 수 있는지를 정의한 것이다.

position - x축 -25, y축 30, z축 25 위치에 있는 점을 Camera가 보고 있다.

lookAt - position의 점을 보기 위해 Camera가 위치 이동.

 


Renderer 추가

var renderer = new THREE.WebGLRenderer({antialias:true});
 
renderer.setClearColor(new THREE.Color(0xeeeeee));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true; 

오브젝트의 가장자리를 매끄럽게 하기 위해 antialias를 true로 한다.

왼쪽은 antialias를 false, 오른쪽은 true

색상은 0x로 시작하고 HEX color로 적어준다. (0xeeeeee) 배경의 색이 #eee로 바뀌었다.

Renderer를 윈도우의 가로세로 크기로 설정하였다.

그림자를 만들기 위해서 shadowMapEnabled을 true로 준다. (그림자 효과화)

 


Plane (바닥) 추가.

var planeGeometry = new THREE.PlaneGeometry(180, 180, 1, 1);
var planeMaterial = new THREE.MeshLambertMaterial({color:0xffffff});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.receiveShadow = true;
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 15;
plane.position.y = 0;
plane.position.z = 0;
 
scene.add(plane);

planeGeometry - 가로 180, 세로 180, 가로세로 1씩의 세그먼트를 가진 Plane를 추가한다.

planeMaterial - 색상과 재질을 설정한다.

THREE.Mesh - 형태, 재질을 합쳐주는 역할을 한다.

Plane 위에 생성되는 객체의 그림자를 받을 것이기 때문에 receiveShadow의 값을 true로 설정한다.

Plane은 기본값이 수직으로 서있기 때문에 rotation 시켜서 수평으로 만든다.

THREE.Mesh - 형태, 재질을 합쳐주는 역할을 한다.
지오메트리 - 객체의 수학적 공식
머티리얼 - 오브젝트의 속성과 장면의 광원과의 동작

 

 

 

 

AxisHelper (좌표계) 생성

var axes = new THREE.AxisHelper(20);
scene.add(axes);

카메라가 바라보고 곳을 알려주기 위하여 xyz 좌표계를 만든다. (유용하다)

x축은 Red, y축은 Green, z축은 Blue로 확인할 수 있다.

 

Cube 추가

var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
var cubeMaterial = new THREE.MeshLambertMaterial({color: 0x12db00, wireframe: false});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
cube.position.x = -4;
cube.position.y = 5;
cube.position.z = 0;
scene.add(cube);  

BoxGeometry를 이용하여 x축, y축, z축의 길이가 4인 입방체를 만든다.

MeshBasicMaterial은 광원의 영향을 받지 않기 때문에 그림자를 만들지 못한다.

MeshLambertMaterial, MeshPhongMaterial의 Material를 사용해야 한다.

MeshLambertMaterial - 빛을 받아 반짝이지 않는 객체를 만들 때 사용

MeshPhongMaterial - 빛을 받아 반짝이는 객체를 만들 때 사용

 

질감이 높은 순으로 나열하자면

MeshPhongMaterial > MeshLambertMaterial > MeshBasicMaterial이 된다.

MeshPhongMaterial > MeshLambertMaterial > MeshBasicMaterial

 

 

색상과 wireframe를 어찌할지 설정을 해주고 Scene에 추가!

wireframe : true

 


SpotLight 광원 추가

var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
spotLight.castShadow = true;
spotLight.shadowMapHeight = 5000;
spotLight.shadowMapWidth = 5000;
scene.add(spotLight);

빛이 있어야 물체가 보인다. 광원에는 여러 가지 종류가 있지만, 다음에 알아보기로 하고 일단은 그림자를 만들어주는 SpotLight를 사용한다.

광원의 색과 position을 설정해주고, 그림자를 만들어야 하니 castShadow는 true로 한다.

왼쪽은 기본값 512, 오른쪽은 5000으로 늘림

그림자의 shadowMapWidth, shadowMapHeight 기본값은 512로 설정되어 있어 그림자가 까슬까슬하게 생겼다.

자연스러운 그림자를 주기 위해 shadowMapWidth, shadowMapHeight의 값을 5000으로 주었다.

그리고 Scene에 추가!

 


Rendering 하기

document.getElementById("WebGL-output").appendChild(renderer.domElement);
renderer.render(scene, camera);

만들어둔 div(WebGL-output) 안에 Rendering 한 것을 넣어준다.

render 함수의 인수 scene과 camera를 전달하여 Rendering 완료!

 


완성!!

 

 

전체소스

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

<script>
	// Scene : 컨테이너
	var scene = new THREE.Scene();

	// camera(카메라) : 화면을 보는 시각
	var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
		camera.position.x = -25;
		camera.position.y = 30;
		camera.position.z = 25;
		
		camera.lookAt( scene.position );

	// Plane : 바닥
	var planeGeometry = new THREE.PlaneGeometry(180, 180, 1, 1);
	var planeMaterial = new THREE.MeshLambertMaterial({color:0xffffff});
	var plane = new THREE.Mesh(planeGeometry, planeMaterial);
		plane.receiveShadow = true;
		plane.rotation.x = -0.5 * Math.PI;
		plane.position.x = 15;
		plane.position.y = 0;
		plane.position.z = 0;
 
		scene.add(plane)

	// AxisHelper (좌표계) 생성
	var axes = new THREE.AxisHelper(20);
		scene.add(axes);

	// Cube : 박스 만들기
	var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
	var cubeMaterial = new THREE.MeshLambertMaterial({color: 0x12db00, wireframe: false});
	var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
		cube.castShadow = true;
		cube.position.x = -4;
		cube.position.y = 5;
		cube.position.z = 0;

		scene.add(cube); 

	// SpotLight : 광원을 주어야 객체가 보인다!
	var spotLight = new THREE.SpotLight(0xffffff);
		spotLight.position.set(-40, 60, -10);
		spotLight.castShadow = true;
		spotLight.shadowMapHeight = 5000;
		spotLight.shadowMapWidth = 5000;

		scene.add(spotLight);

	// renderer(랜더러) : 그림자효과, 색상입히기, 부드럽게 바꾸기 등.
	var renderer = new THREE.WebGLRenderer({antialias:true});
		renderer.setClearColor(new THREE.Color(0xeeeeee));
		renderer.setSize(window.innerWidth, window.innerHeight);
		renderer.shadowMapEnabled = true; 

		document.getElementById("WebGL-output").appendChild(renderer.domElement);
		renderer.render( scene, camera );


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

See the Pen Three.js - hello cube by 최충현 (@nenara) on CodePen.

 

 

 

 


출처: https://jj-k-ul.tistory.com/entry/Threejs를-시작해보자 [불꽃놀이보고싶다]

출처: https://medium.com/@necsoft/three-js-101-hello-world-part-1-443207b1ebe1

 

+ Recent posts