<!DOCTYPE html>
<html lang="en">
<head>
	<title>three.js webgl - lights - projectorlight</title>
	<meta charset="utf-8">
	<meta name="viewport"
				content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<style>
		body {
			background-color: #000;
			margin: 0px;
			overflow: hidden;
		}

		#info {
			position: absolute;
			top: 0px;
			width: 100%;
			color: #ffffff;
			padding: 5px;
			font-family: Monospace;
			font-size: 13px;
			text-align: center;
		}

		a {
			color: #ff0080;
			text-decoration: none;
		}

		a:hover {
			color: #0080ff;
		}
	</style>
</head>
<body>

<div id="info">
	<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webgl
	- projectorlight by <a href="http://github.com/usefulthink" target="_blank"
												 rel="noopener">Martin Schuhfuss</a><br/>
</div>

<video id="video" autoplay loop webkit-playsinline muted style="display: none;">
	<source src="textures/sintel.mp4"
					type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
	<source src="textures/sintel.ogv" type='video/ogg; codecs="theora, vorbis"'>
</video>

<script src="../build/three.js"></script>
<script src="js/controls/OrbitControls.js"></script>

<script src="js/libs/dat.gui.min.js"></script>

<script src="js/Detector.js"></script>

<script>

	if ( !Detector.webgl ) Detector.addGetWebGLMessage();

	var renderer, scene, camera;
	var controls;
	var projectorLight;
	var shadowCameraHelper;
	var helpers = [];

	var gui;

	var textures = {};

	function initTextures() {

		var textureLoader = new THREE.TextureLoader();
		var texture;

		textures.uvGrid = textureLoader.load( 'textures/UV_Grid_Sm.jpg' );

		var video = document.getElementById( 'video' );
		texture = new THREE.VideoTexture( video );
		texture.minFilter = THREE.LinearFilter;
		texture.magFilter = THREE.LinearFilter;
		texture.format = THREE.RGBFormat;

		textures.video = texture;

	}

	function init() {

		renderer = new THREE.WebGLRenderer();
		renderer.setPixelRatio( window.devicePixelRatio );
		renderer.setSize( window.innerWidth, window.innerHeight );
		document.body.appendChild( renderer.domElement );
		renderer.shadowMap.enabled = true;
		renderer.shadowMap.type = THREE.PCFSoftShadowMap;

		renderer.gammaInput = true;
		renderer.gammaOutput = true;

		scene = new THREE.Scene();

		camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 1000 );
		camera.position.set( 65, 8, -10 );

		controls = new THREE.OrbitControls( camera, renderer.domElement );
		controls.minDistance = 20;
		controls.maxDistance = 500;
		controls.enablePan = false;

		var ambient = new THREE.AmbientLight( 0xffffff, 0.1 );
		scene.add( ambient );

		projectorLight = new THREE.ProjectorLight( 0xffffff, 1 );

		projectorLight.map = textures.uvGrid;
		projectorLight.position.set( 15, 40, 35 );
		projectorLight.angle = Math.PI / 3;
		projectorLight.fov = 60;
		projectorLight.aspect = 1;
		projectorLight.decay = 2;
		projectorLight.distance = 200;

		projectorLight.castShadow = true;
		projectorLight.shadow.mapSize.width = 1024;
		projectorLight.shadow.mapSize.height = 1024;
		projectorLight.shadow.camera.near = 10;
		projectorLight.shadow.camera.far = 200;

		scene.add( projectorLight );

		shadowCameraHelper = new THREE.CameraHelper( projectorLight.shadow.camera );

		helpers.push( shadowCameraHelper );
		helpers.push( new THREE.AxesHelper( 10 ) );
		helpers.push( new THREE.GridHelper( 100, 10 ) );

		scene.add.apply( scene, helpers );

		var floor = new THREE.Mesh(
				new THREE.BoxGeometry( 2000, 1, 2000 ),
				new THREE.MeshPhongMaterial( { color: 0x808080, dithering: true } )
		);
		floor.position.set( 0, -1, 0 );
		floor.receiveShadow = true;
		scene.add( floor );

		var box1 = new THREE.Mesh(
				new THREE.BoxGeometry( 3, 1, 2 ),
				new THREE.MeshPhongMaterial( { color: 0xffffff, dithering: true } )
		);
		box1.position.set( -10, 2, 0 );
		box1.castShadow = true;
		scene.add( box1 );

		var box2 = new THREE.Mesh(
				new THREE.BoxGeometry( 3, 10, 2 ),
				new THREE.MeshPhongMaterial( { color: 0xffffff, dithering: true } )
		);
		box2.position.set( 20, 4, 0 );
		box2.castShadow = true;
		scene.add( box2 );

		projectorLight.target = box2;

		controls.target.copy( box2.position );
		controls.update();

		window.addEventListener( 'resize', onResize, false );

	}

	function onResize() {

		camera.aspect = window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();

		renderer.setSize( window.innerWidth, window.innerHeight );

	}

	function buildGui() {

		gui = new dat.GUI();

		var params = {
			'light color': projectorLight.color.getHex(),
			intensity: projectorLight.intensity,
			distance: projectorLight.distance,
			fov: projectorLight.fov,
			aspect: projectorLight.aspect,
			decay: projectorLight.decay,
			rotation: projectorLight.rotation.z,
			texture: 'uvGrid',
			showHelpers: true
		};

		gui.addColor( params, 'light color' ).onChange( function ( val ) {
			projectorLight.color.setHex( val );
		} );
		gui.add( params, 'intensity', 0, 2 ).onChange( function ( val ) {
			projectorLight.intensity = val;
		} );
		gui.add( params, 'distance', 50, 200 ).onChange( function ( val ) {
			projectorLight.distance = val;
		} );
		gui.add( params, 'decay', 1, 2 ).onChange( function ( val ) {
			projectorLight.decay = val;
		} );
		gui.add( params, 'fov', 10, 120 ).onChange( function ( val ) {
			projectorLight.fov = val;
		} );
		gui.add( params, 'aspect', 0.5, 2 ).onChange( function ( val ) {
			projectorLight.aspect = val;
		} );
		gui.add( params, 'texture', Object.keys( textures ) ).onChange( function ( val ) {
			projectorLight.map = textures[ val ];
		} );
		gui.add( params, 'rotation', -Math.PI, Math.PI ).onChange( function ( val ) {
			projectorLight.rotation.z = val;
		} );
		gui.add( params, 'showHelpers' ).onChange( function ( val ) {
			helpers.forEach( function ( helper ) { helper.visible = val; } );
		} );
		gui.open();

	}

	initTextures();
	init();

	buildGui();

	requestAnimationFrame( function __loop() {
		controls.update();
		renderer.render( scene, camera );
		shadowCameraHelper.update();
		requestAnimationFrame( __loop );
	} );

</script>

</body>

</html>