<div id="container"></div>

	<script type="x-shader/x-vertex" id="vertexshader">

			uniform float amplitude;

			attribute vec3 customColor;
			attribute vec3 displacement;

			varying vec3 vNormal;
			varying vec3 vColor;

			void main() {

				vNormal = normal;
				vColor = customColor;

				vec3 newPosition = position + normal * amplitude * displacement;
				gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );

			}

		</script>

	<script type="x-shader/x-fragment" id="fragmentshader">

			varying vec3 vNormal;
			varying vec3 vColor;

			void main() {

				const float ambient = 0.4;

				vec3 light = vec3( 1.0 );
				light = normalize( light );

				float directional = max( dot( vNormal, light ), 0.0 );

				gl_FragColor = vec4( ( directional + ambient ) * vColor, 1.0 );

			}

		</script>
		import * as THREE from 'https://threejs.org/build/three.module.js';

		import Stats from 'https://threejs.org/examples/jsm/libs/stats.module.js';

		import { TrackballControls } from 'https://threejs.org/examples/jsm/controls/TrackballControls.js';
		import { TessellateModifier } from 'https://threejs.org/examples/jsm/modifiers/TessellateModifier.js';
		import { GLTFLoader } from 'https://threejs.org/examples/jsm/loaders/GLTFLoader.js';
		import { SimplifyModifier } from 'https://threejs.org/examples/jsm/modifiers/SimplifyModifier.js';
		import { OBJLoader } from 'https://threejs.org/examples/jsm/loaders/OBJLoader.js';
		import { TWEEN } from 'https://threejs.org/examples/jsm/libs/tween.module.min.js';
		import { Geometry } from "https://threejs.org/build/three.module.js";

		var renderer, scene, camera, stats;

		var controls;

		var mesh, uniforms;

		var WIDTH = window.innerWidth,
			HEIGHT = window.innerHeight;

		var loader = new THREE.FontLoader();
		new GLTFLoader().load("https://threejs.org/examples/models/gltf/LeePerrySmith/LeePerrySmith.glb", function (gltf) {
			var mesh = gltf.scene.children[0];
			var modifier = new SimplifyModifier();

			var simplified = mesh.clone();
			simplified.material = simplified.material.clone();
			simplified.material.flatShading = true;
			var count = Math.floor(simplified.geometry.attributes.position.count * 0.5); // number of vertices to remove
			simplified.geometry = modifier.modify(simplified.geometry, count);

			var geometry = new Geometry().fromBufferGeometry(simplified.geometry);

			init(geometry)
			render()
			animate()
		})

		function init(geometry) {

			camera = new THREE.PerspectiveCamera(3, WIDTH / HEIGHT, 1, 10000);
			camera.position.set(10, 100, 200);

			scene = new THREE.Scene();
			scene.background = new THREE.Color(0x050505);

			geometry.center();

			geometry = new THREE.BufferGeometry().fromGeometry(geometry);

			var numFaces = geometry.attributes.position.count / 3;

			var colors = new Float32Array(numFaces * 3 * 3);
			var displacement = new Float32Array(numFaces * 3 * 3);

			var color = new THREE.Color();

			for (var f = 0; f < numFaces; f++) {

				var index = 9 * f;

				var h = 0.2 * Math.random();
				var s = 0.5 + 0.5 * Math.random();
				var l = 0.5 + 0.5 * Math.random();

				color.setHSL(h, s, l);

				var d = 1000 * (0.5 - Math.random());

				for (var i = 0; i < 3; i++) {

					colors[index + (3 * i)] = color.r;
					colors[index + (3 * i) + 1] = color.g;
					colors[index + (3 * i) + 2] = color.b;

					displacement[index + (3 * i)] = d;
					displacement[index + (3 * i) + 1] = d;
					displacement[index + (3 * i) + 2] = d;

				}

			}

			geometry.setAttribute('customColor', new THREE.BufferAttribute(colors, 3));
			geometry.setAttribute('displacement', new THREE.BufferAttribute(displacement, 3));

			//

			uniforms = {

				amplitude: { value: 0.01 }

			};

			var shaderMaterial = new THREE.ShaderMaterial({

				uniforms: uniforms,
				vertexShader: document.getElementById('vertexshader').textContent,
				fragmentShader: document.getElementById('fragmentshader').textContent

			});

			//

			mesh = new THREE.Mesh(geometry, shaderMaterial);

			scene.add(mesh);

			renderer = new THREE.WebGLRenderer({ antialias: true });
			renderer.setPixelRatio(window.devicePixelRatio);
			renderer.setSize(WIDTH, HEIGHT);

			var container = document.getElementById('container');
			container.appendChild(renderer.domElement);

			controls = new TrackballControls(camera, renderer.domElement);

			stats = new Stats();
			container.appendChild(stats.dom);

			//

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

		}

		function onWindowResize() {

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

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

		}

		var isReverse = true
		function tween(amplitude, to) {

			new TWEEN.Tween(amplitude).to({ value: to, }, 2000)
				.onComplete(() => isReverse = !isReverse)
				.easing(TWEEN.Easing.Quadratic.Out).start();

		}

		function animate() {
			const to = isReverse ? 0 : 0.5
			tween(uniforms.amplitude, to)
			setTimeout(animate, 5000);
		}

		function render() {
			controls.update();
			TWEEN.update();
			renderer.render(scene, camera);

			stats.update();

			requestAnimationFrame(render);

		}

Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.