Three.js

Kurz počítačové grafiky

Autor: Jiří Hnídek / jiri.hnidek@tul.cz

Three.js

https://threejs.org/
  • Javascriptová knihovna zjednodušující implementaci 3D grafiky na webu
  • Pro zobrazení 3D obsahu není ani nezbytně nutná podpora WebGL
    • Lze renderovat do canvasu čistě softwarově pomocí SVG.
  • Autor: Mr. Doob
  • Není nutné psát Vertex ani Fragment shadery. Kód aplikace je psán čistě v Javascriptu.

Three.js - důležité vlastnosti

  • Hierarchická scéna
  • Kamera s perspektivním i rovinným promítáním
  • Světla bodová, směrová, kuželová a ambientní
  • Objekty včetně základních primitiv
  • Materiály pomocí předefinovaných i vlastních shaderů
  • Textury a mnohé další

Minimální Three.js kód

<!DOCTYPE html>
<html>
	<head>
		<meta charset=utf-8>
		<title>My first Three.js app</title>
	</head>
	<body>
		<script src="js/three.js"></script>
		<script>
			// Naše Three.js aplikace
		</script>
	</body>
</html>

Scéna s kamerou

// set the scene size
var width = 400, height = 300;
// Set some camera attributes
var view_angle = 35, aspect = width / height, near = 0.1, far = 10000;
// create a WebGL renderer, camera and a scene
var renderer = new THREE.WebGLRenderer({antialias: true}); // WebGL only
renderer.setSize(width, height);
var camera = new THREE.PerspectiveCamera(view_angle, aspect, near, far);
var scene = new THREE.Scene();
scene.add(camera);
camera.position.z = 5.0;
// Attach the render to element <div id="container"><div>
document.getElementById("container").appendChild(renderer.domElement);
// Start the renderer
renderer.render(scene, camera);

Renderer

  • Je vhodné detekovat podporu WebGL:
  • <script src="Detector.js"></script>
    Detector.webgl
    
  • Podle výsledku je možné nastavit buď WebGL renderer:
  • renderer = new THREE.WebGLRenderer();
  • Případně softwarový renderer (SVG na canvas):
  • <script src="CanvasRenderer.js"></script>
    renderer = new THREE.CanvasRenderer();
  • V rendereru nastavujeme i velikost canvasu:
  • renderer.setSize(width, height);

Kamera perspektivní

  • Nastavení kamery je obligátní. Je nutné nastavit:
    • Úhel pohledu alias ohniskovou vzdálenost (dalekohled až rybí oko).
    • Poměr stran.
    • Vzdálená a blízká plocha ořezávají pohledový objem.
var camera = new THREE.PerspectiveCamera(view_angle, aspect, near, far);

Kamera ortogonální

  • V případě, že potřebujeme rovinné promítání, tak kameru vytvoříme pomocí:
  • var camera = new THREE.OrthographicCamera(left, right,
    	top, bottom,
    	near, far);

Scéna

“Dejte mi pevný bod a pohnu zemí.”
var scene = new THREE.Scene();
  • Objekty ve scéně jsou organizovány do stromové struktury.
  • Pokud cheme, aby byl Three.js objekt ve scéně nějak patrný a platný, tak ho do scény musíme přidat:
  • scene.add(camera);

"Scena! Kamera! Renderujem!"

  • Renderer je nakonec potřeba přidat jako "potomka" nějakému DOM elementu z HTML stránky:
  • document.getElementById("container").appendChild(renderer.domElement);
  • A spustit ho>
  • renderer.render(scene, camera);

Přidáváme objekty

  • Vytvoříme geometrii pomocí základního primitiva:
  • var cube_geom = new THREE.BoxGeometry(1.0, 1.0, 1.0);
  • Vytvoříme barvu:
  • var material = new THREE.MeshBasicMaterial({color: 0x00aa00});
  • Vytvoříme z nich objekt:
  • var cube_obj = new THREE.Mesh(cube_geom, material);
  • A přidáme ho do scény, aby byl vidět:
  • scene.add(cube_obj);

Obecná Geometrie

  • Geometrii vytvoříme pomocí:
  • var geometry = new THREE.Geometry();
  • Tu potom můžeme naplnit vertexy:
  • geometry.vertices.push(new THREE.Vector3(0.0, 0.0, 0.0));
    geometry.vertices.push(new THREE.Vector3(1.0, 0.0, 0.0));
    geometry.vertices.push(new THREE.Vector3(0.5, 1.0, 0.0));
  • A vertexy spojit třeba do plošek (v tomto případě trojúhelník):
  • geometry.faces.push(new THREE.Face3(0, 1, 2);

JSON Loader geometrie

Objekt vytvořený v nějakém 3D apliakci můžeme načíst pomocí mnoha loaderů. Jedním z nich je JSON loader:

var loader = new THREE.JSONLoader();
loader.load( "model_example.json", function(geometry){
	var material = new THREE.MeshLambertMaterial({color: 0x00aa00});
	mesh = new THREE.Mesh(geometry, material);
	scene.add(mesh);
});

Animujeme

Následující kód se pokusí vykreslit scénu s obnovovací frekvencí 60 FPS. Pokud canvas nebude vidět, tak se vykreslování zastaví a šetří se baterky.

var render = function () {
	requestAnimationFrame( render );
	cube.rotation.x += 0.1;
	cube.rotation.y += 0.1;
	renderer.render(scene, camera);
};
render();

Pozadí a světla

Nejprve nastavíme barvu pozadí:

renderer.setClearColorHex(0x333F47, 1);

Vytvoříme bodový zdroj světla. Nastavíme mu pozici a přidáme ho do scény:

var light = new THREE.PointLight(0xffffff);
light.position.set(-100,200,100);
scene.add(light);

Elegantnější materiály

Materiál používající Phongův osvětlovací model:

var phong_mat = MeshPhongMaterial({color: 0x00aa00});

Materiál používající Lambertův osvětlovací model:

var material = new THREE.MeshLambertMaterial({color: 0x00aa00});

Ovládání pohledu kamery

Pro ovládání pohledu kamery je potřeba v html souboru vložit:

<script type="text/javascript" src="js/TrackballControls.js"></script>

Ovladač kamery vytvoříme a nastavíme následovně:

controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [65, 83, 68];
controls.addEventListener('change', render);
function render() {renderer.render(scene, camera);};

Textury

Nejprve si vytvoříme loader textur:

var loader = new THREE.TextureLoader();

V loaderu nastavíme cestu k textuře přiřadíme mu callback funkce pro vytvoření materiálu:

loader.load('textura.png',
	function ( texture ) {
		var tex_material = new THREE.MeshBasicMaterial( {
			map: texture
		} );
		// Následně materiál můžeme přiřadit nějakému objektu
	},
	function ( xhr ) {
		console.log( (xhr.loaded/xhr.total*100) + '% loaded' );
	},
	function ( xhr ) {console.log( 'An error happened' );}
}

Statistika vykreslování

V případě, že aplikaci vyvíjíte, tak je šikovné mít přehled, jak rychle se scéna vykresluje. K tomu může posloužit:


stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
document.body.appendChild( stats.domElement );

One more thing.

https://threejs.org/editor/

Děkuji za pozornost.