html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}
canvas {
  width: 100%;
  height: 100%;
  display; block;
}
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import {OrbitControls} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";
import {GLTFLoader} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/loaders/GLTFLoader";
import {GUI} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/libs/lil-gui.module.min.js";
import {TWEEN} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/libs/tween.module.min.js";

var running = false;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
camera.position.set(0, 13, 21).setLength(15);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setClearColor(0x404040);
var canvas = renderer.domElement;
document.body.appendChild(canvas);

console.log("R " + THREE.REVISION);

var controls = new OrbitControls(camera, canvas);
controls.target.set(0, 4.5, 0);
controls.update();

// lights
var alight = new THREE.AmbientLight(0xffffff);
alight.intensity = 0.9;
scene.add(alight);

var light = new THREE.PointLight(0xffffff, 1, 40);
light.intensity = 0.9;
light.position.set(0, 20, 0);
scene.add(light);

let preWave = 0.1;
let postWave = 2.1;
var uniforms = {
  hWave: { value: -preWave }
};
var func = {
  Start: () => {
    startSequence();
  }
};

var commonMaterial = new THREE.MeshLambertMaterial({
  color: 0xff6464,
  side: THREE.DoubleSide
});

var lineMaterial = new THREE.LineBasicMaterial({
  color: 0xffcccc,
  depthTest: false,
  transparent: true,
  opacity: 0.125,
  onBeforeCompile: shader => {
    shader.uniforms.hWave = uniforms.hWave;
    shader.vertexShader = `
      varying float vPos;
      ${shader.vertexShader}
    `.replace(
      `#include <begin_vertex>`,
      `#include <begin_vertex>
        vPos = (modelMatrix * vec4(transformed, 1.0)).y;
      `
    );
    //console.log(shader.vertexShader)
    shader.fragmentShader = `
      #define ss(a,b,c) smoothstep(a,b,c)
      uniform float hWave;
      varying float vPos;
      ${shader.fragmentShader}
    `.replace(
      `vec4 diffuseColor = vec4( diffuse, opacity );`,
      `
      float f = ss(hWave - ${postWave}, hWave, vPos) - ss(hWave, hWave + ${preWave}, vPos);
      f = clamp(f, 0., 1.);
      f *= (1. - opacity);
      vec4 diffuseColor = vec4( diffuse, opacity + f );`
    );
    //console.log(shader.fragmentShader);
  }
});

var loader = new GLTFLoader();
// st basils
loader.load(
  "https://cywarr.github.io/small-shop/stbasil.glb",
  function(gltf) {
    var stBasil = gltf.scene.children[2];
    stBasil.children[0].material = commonMaterial;
    stBasil.children[1].material = commonMaterial;
    stBasil.rotation.z = -Math.PI * 0.25;
    
    // lines
    let gLines1 = new THREE.WireframeGeometry(stBasil.children[0].geometry);
    let gLines2 = new THREE.WireframeGeometry(stBasil.children[1].geometry);
    
    let lines1 = new THREE.LineSegments(gLines1, lineMaterial);
    let lines2 = new THREE.LineSegments(gLines2, lineMaterial);
    
    stBasil.add(lines1, lines2);

    var box3 = new THREE.Box3().setFromObject(stBasil);
    var size = new THREE.Vector3();
    box3.getSize(size);
    var scale = 10 / size.y;

    gltf.scene.scale.setScalar(scale);
    scene.add(gltf.scene);
    setGUI(10);
    startSequence();
  },
  function(xhr) {},
  function(error) {
    console.log(error);
  }
);

function setGUI(lim) {
  var gui = new GUI();
  gui.add(func, "Start").name("Run-a-wave");
}

function startSequence() {
  if (running) return;
  uniforms.hWave.value = -preWave;

  var plane = new TWEEN.Tween(uniforms.hWave)
    .to({ value: 10 + postWave }, 2000)
    .delay(500)
    .onStart(() => {
      running = true;
    })
    .onComplete(() => {
      running = false;
    });

  plane.start();
}

render();

function render() {
  if (resize(renderer)) {
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }
  TWEEN.update();
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}

function resize(renderer) {
  const canvas = renderer.domElement;
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;
  if (needResize) {
    renderer.setSize(width, height, false);
  }
  return needResize;
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.