--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title>three.js webgl - post processing - Outline Pass</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: #000000;
+ margin: 0px;
+ overflow: hidden;
+ font-family:Monospace;
+ font-size:13px;
+ text-align:center;
+ font-weight: bold;
+ }
+
+ a {
+ color:#00ff78;
+ }
+
+ #info {
+ color: #fff;
+ position: absolute;
+ top: 10px;
+ width: 100%;
+ text-align: center;
+ display:block;
+ }
+ .dg.ac {
+ z-index: 1 !important; /* FIX DAT.GUI */
+ }
+ </style>
+ </head>
+ <body>
+ <script src="../build/three.js"></script>
+ <script src="js/controls/OrbitControls.js"></script>
+ <script src="js/loaders/OBJLoader.js"></script>
+
+ <script src="js/Detector.js"></script>
+
+ <script src="js/shaders/CopyShader.js"></script>
+ <script src="js/shaders/FXAAShader.js"></script>
+ <script src="js/postprocessing/EffectComposer.js"></script>
+ <script src="js/postprocessing/RenderPass.js"></script>
+ <script src="js/postprocessing/ShaderPass.js"></script>
+ <script src="js/postprocessing/OutlinePass.js"></script>
+ <script src="js/libs/stats.min.js"></script>
+ <script src='js/libs/dat.gui.min.js'></script>
+
+ <div id="info">
+ <a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - Outline Pass by <a href="http://eduperiment.com" target="_blank" rel="noopener">Prashant Sharma</a> and <a href="https://clara.io" target="_blank" rel="noopener">Ben Houston</a><br/><br/>
+ </div>
+
+ <script>
+
+ if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+ var container, stats;
+ var camera, scene, renderer, controls;
+ var mesh, decal;
+ var raycaster = new THREE.Raycaster();
+
+ var mouse = new THREE.Vector2();
+ var selectedObjects = [];
+
+ var composer, effectFXAA, outlinePass;
+ var obj3d = new THREE.Object3D();
+
+ var group = new THREE.Object3D();
+
+ var params = {
+ edgeStrength: 3.0,
+ edgeGlow: 0.0,
+ edgeThickness: 1.0,
+ pulsePeriod: 0,
+ rotate: false,
+ usePatternTexture: false
+ };
+
+ // Init gui
+ var gui = new dat.GUI();
+ gui.add(params, "edgeStrength", 0.01, 10).onChange(function( value ) {
+ outlinePass.edgeStrength = Number(value);
+ });
+ gui.add(params, "edgeGlow", 0.0, 1).onChange(function( value ) {
+ outlinePass.edgeGlow = Number(value);
+ });
+ gui.add(params, "edgeThickness", 1, 4).onChange(function( value ) {
+ outlinePass.edgeThickness = Number(value);
+ });
+ gui.add(params, "pulsePeriod", 0.0, 5).onChange(function( value ) {
+ outlinePass.pulsePeriod = Number(value);
+ });
+ gui.add(params, "rotate");
+ gui.add(params, "usePatternTexture").onChange(function( value ) {
+ outlinePass.usePatternTexture = value;
+ });
+ var Configuration = function() {
+ this.visibleEdgeColor = "#ffffff";
+ this.hiddenEdgeColor = "#190a05";
+ };
+ var conf = new Configuration();
+
+ var controladorVisible = gui.addColor( conf, 'visibleEdgeColor');
+ var controladorHidden = gui.addColor( conf, 'hiddenEdgeColor');
+ controladorVisible.onChange(function( colorValue ) {
+ //the return value by the chooser is like as: #ffff
+ colorValue = colorValue.replace('#', '');
+ function hexToRgb( hex ) {
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? {
+ r: parseInt(result[ 1 ], 16),
+ g: parseInt(result[ 2 ], 16),
+ b: parseInt(result[ 3 ], 16)
+ } : null;
+ }
+
+ var rgba = hexToRgb(colorValue);
+ var color = outlinePass.visibleEdgeColor;
+ color.r = rgba.r / 255;
+ color.g = rgba.g / 255;
+ color.b = rgba.b / 255;
+ });
+
+ controladorHidden.onChange(function( colorValue ) {
+ //the return value by the chooser is like as: #ffff
+ colorValue = colorValue.replace('#', '');
+ function hexToRgb( hex ) {
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? {
+ r: parseInt(result[ 1 ], 16),
+ g: parseInt(result[ 2 ], 16),
+ b: parseInt(result[ 3 ], 16)
+ } : null;
+ }
+
+ var rgba = hexToRgb(colorValue);
+ var color = outlinePass.hiddenEdgeColor;
+ color.r = rgba.r / 255;
+ color.g = rgba.g / 255;
+ color.b = rgba.b / 255;
+ });
+
+ init();
+ animate();
+
+ function init() {
+
+ container = document.createElement( 'div' );
+ document.body.appendChild( container );
+
+ var width = window.innerWidth || 1;
+ var height = window.innerHeight || 1;
+ var devicePixelRatio = window.devicePixelRatio || 1;
+
+ renderer = new THREE.WebGLRenderer( { antialias: false } );
+ renderer.shadowMap.enabled = true;
+ renderer.setClearColor( 0xa0a0a0 );
+ renderer.setPixelRatio( 1 );
+ renderer.setSize( width, height );
+ document.body.appendChild( renderer.domElement );
+
+ camera = new THREE.PerspectiveCamera( 45, width / height, 0.1, 100 );
+ camera.position.z = 8;
+ camera.position.x = 0;
+
+ scene = new THREE.Scene();
+
+ var manager = new THREE.LoadingManager();
+ manager.onProgress = function ( item, loaded, total ) {
+ console.log( item, loaded, total );
+ };
+ // model
+ var loader = new THREE.OBJLoader( manager );
+ loader.load( 'models/obj/tree.obj', function ( object ) {
+ var scale = 1.0;
+ object.traverse( function ( child ) {
+ if ( child instanceof THREE.Mesh ) {
+ child.geometry.center();
+ child.geometry.computeBoundingSphere();
+ scale = 0.2*child.geometry.boundingSphere.radius;
+ var phongMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0xffffff, shininess: 5 } );
+ child.material = phongMaterial;
+ child.material.side = THREE.DoubleSide;
+ child.receiveShadow = true;
+ child.castShadow = true;
+ }
+ } );
+ object.position.y = 1;
+ object.scale.x /= scale;
+ object.scale.y /= scale;
+ object.scale.z /= scale;
+ obj3d.add( object );
+ } );
+ group.add(obj3d);
+
+ controls = new THREE.OrbitControls( camera, renderer.domElement );
+ controls.enableDamping = true;
+ controls.dampingFactor = 0.25;
+
+ scene.add( group );
+
+ var light = new THREE.DirectionalLight( 0xddffdd, 0.4);
+ light.position.z = 1;
+ light.position.y = 1;
+ light.position.x = 1;
+ scene.add( light );
+ light.castShadow = true;
+
+ light.shadow.mapSize.width = 1024;
+ light.shadow.mapSize.height = 1024;
+
+ var d = 20;
+
+ light.shadow.camera.left = - d;
+ light.shadow.camera.right = d;
+ light.shadow.camera.top = d;
+ light.shadow.camera.bottom = - d;
+
+ light.shadow.camera.far = 1000;
+
+ var light2 = new THREE.DirectionalLight( 0xaadddd, 0.15 );
+ light2.position.z = 1;
+ light2.position.x = -1;
+ light2.position.y = -1;
+ scene.add( light2 );
+
+ var light3 = new THREE.DirectionalLight( 0xddddaa, 0.1 );
+ light3.position.z = 1;
+ light3.position.x = -1;
+ light3.position.y = 1;
+ scene.add( light3 );
+
+ var light3 = new THREE.AmbientLight( 0xaaaaaa, 0.2 );
+ scene.add( light3 );
+
+ var geometry = new THREE.SphereBufferGeometry( 3, 48, 24 );
+ for ( var i = 0; i < 20; i ++ ) {
+
+ var material = new THREE.MeshLambertMaterial();
+ material.roughness = 1;//0.5 * Math.random() + 0.25;
+ material.metalness = 0;
+ material.color.setHSL( Math.random(), 1.0, 0.3 );
+
+ var mesh = new THREE.Mesh( geometry, material );
+ mesh.position.x = Math.random() * 4 - 2;
+ mesh.position.y = Math.random() * 4 - 2;
+ mesh.position.z = Math.random() * 4 - 2;
+ mesh.rotation.x = Math.random();
+ mesh.rotation.y = Math.random();
+ mesh.rotation.z = Math.random();
+ mesh.receiveShadow = true;
+ mesh.castShadow = true;
+ mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * 0.3 + 0.1;
+ group.add( mesh );
+ }
+
+ var floorMaterial = new THREE.MeshLambertMaterial();
+ floorMaterial.side = THREE.DoubleSide;
+ material.roughness = 0.5 * Math.random() + 0.25;
+ material.metalness = 0;
+
+ var floorGeometry = new THREE.PlaneBufferGeometry( 12, 12 );
+ var floorMesh = new THREE.Mesh( floorGeometry, floorMaterial );
+ floorMesh.rotation.x -= Math.PI * 0.5;
+ floorMesh.position.y -= 1.5;
+ group.add( floorMesh );
+ floorMesh.receiveShadow = true;
+
+ var geometry = new THREE.TorusGeometry( 1, 0.3, 16, 100 );
+ var material = new THREE.MeshPhongMaterial( { color: 0xffaaff } );
+ var torus = new THREE.Mesh( geometry, material );
+ torus.position.z = -4;
+ group.add( torus );
+ torus.receiveShadow = true;
+ torus.castShadow = true;
+
+ stats = new Stats();
+ container.appendChild( stats.dom );
+
+ // postprocessing
+ composer = new THREE.EffectComposer( renderer );
+
+ var renderPass = new THREE.RenderPass( scene, camera );
+ composer.addPass( renderPass );
+
+ outlinePass = new THREE.OutlinePass( new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
+ composer.addPass( outlinePass );
+ var onLoad = function ( texture ) {
+ outlinePass.patternTexture = texture;
+ texture.wrapS = THREE.RepeatWrapping;
+ texture.wrapT = THREE.RepeatWrapping;
+ };
+
+ var loader = new THREE.TextureLoader();
+
+ // load a resource
+ loader.load(
+ // resource URL
+ 'textures/tri_pattern.jpg',
+ // Function when resource is loaded
+ onLoad
+ );
+
+ effectFXAA = new THREE.ShaderPass(THREE.FXAAShader);
+ effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight );
+ effectFXAA.renderToScreen = true;
+ composer.addPass( effectFXAA );
+
+ window.addEventListener( 'resize', onWindowResize, false );
+
+ window.addEventListener( 'mousemove', onTouchMove );
+ window.addEventListener( 'touchmove', onTouchMove );
+
+ function onTouchMove( event ) {
+
+ var x, y;
+
+ if ( event.changedTouches ) {
+
+ x = event.changedTouches[ 0 ].pageX;
+ y = event.changedTouches[ 0 ].pageY;
+
+ } else {
+
+ x = event.clientX;
+ y = event.clientY;
+
+ }
+
+ mouse.x = ( x / window.innerWidth ) * 2 - 1;
+ mouse.y = - ( y / window.innerHeight ) * 2 + 1;
+
+ checkIntersection();
+
+ }
+
+ function addSelectedObject(object) {
+ selectedObjects = [];
+ selectedObjects.push(object);
+ }
+
+ function checkIntersection() {
+
+ raycaster.setFromCamera( mouse, camera );
+
+ var intersects = raycaster.intersectObjects( [ scene ], true );
+
+ if ( intersects.length > 0 ) {
+ var selectedObject = intersects[ 0 ].object;
+ addSelectedObject(selectedObject);
+ outlinePass.selectedObjects = selectedObjects;
+ }
+ else {
+ // outlinePass.selectedObjects = [];
+ }
+ }
+
+ }
+
+ function onWindowResize() {
+
+ var width = window.innerWidth || 1;
+ var height = window.innerHeight || 1;
+ var devicePixelRatio = window.devicePixelRatio || 1;
+
+ camera.aspect = width / height;
+ camera.updateProjectionMatrix();
+
+ renderer.setSize( width, height );
+ composer.setSize( width, height );
+ effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight );
+ }
+
+ function animate() {
+
+ requestAnimationFrame( animate );
+
+ stats.begin();
+
+ var timer = performance.now();
+ if(params.rotate)
+ group.rotation.y = timer * 0.0001;
+ renderer.autoClear = true;
+ renderer.setClearColor( 0xfff0f0 );
+ renderer.setClearAlpha( 0.0 );
+
+ composer.render();
+ stats.end();
+ }
+
+
+ </script>
+ </body>
+</html>