// inspiration from Etienne Jacob // https://www.thisiscolossal.com/wp-content/uploads/2018/12/agifcolossaltd2opt.gif import "./styles.css"; import * as THREE from "three"; // import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; import vertex from "./shaders/vertex.glsl"; import fragment from "./shaders/fragment.glsl"; import txt from "./123.png"; let timer = 0; let mouseIsDown = false; export default class Sketch { constructor(options) { this.clock = new THREE.Clock(); this.time = 0; this.container = options.domElement; this.height = this.container.offsetHeight; this.width = this.container.offsetWidth; this.camera = new THREE.PerspectiveCamera( 75, this.width / this.height, 0.1, 1000 ); this.camera.position.set(0, 0, 10); this.scene = new THREE.Scene(); this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); this.renderer.setPixelRatio(window.devicePixelRatio * 2); this.container.appendChild(this.renderer.domElement); // this.controls = new OrbitControls(this.camera, this.renderer.domElement); this.normal = new THREE.Vector3(); this.binormal = new THREE.Vector3(); this.resize(); this.addObjects(); this.render(); this.setUpResize(); } addObjects() { const texture = new THREE.TextureLoader().load(txt, (texture) => { texture.minFilter = THREE.NearestFilter; texture.magFilter = THREE.NearestFilter; }); this.material = new THREE.ShaderMaterial({ side: THREE.DoubleSide, // transparent:true, // wireframe: true, uniforms: { time: { type: "f", value: 0 }, uResolution: { type: "v4", value: new THREE.Vector4() }, u_texture: { type: "t", value: texture } }, vertexShader: vertex, fragmentShader: fragment }); class CustomSinCurve extends THREE.Curve { constructor(scale = 1) { super(); this.scale = scale; } getPoint(t, optionalTarget = new THREE.Vector3()) { const tx = Math.cos(2 * Math.PI * t); const ty = Math.sin(2 * Math.PI * t); const tz = 0.1 * Math.sin(8 * Math.PI * t); return optionalTarget.set(tx, ty, tz).multiplyScalar(this.scale); } } const path = new CustomSinCurve(10); this.geometry = new THREE.TubeGeometry(path, 200, 0.5, 20, false); this.mesh = new THREE.Mesh(this.geometry, this.material); this.scene.add(this.mesh); } render() { this.time = timer; // https://threejs.org/examples/webgl_geometry_extrude_splines.html let looptime = 10 * 1000; let t = (this.time % looptime) / looptime; let pos = this.geometry.parameters.path.getPointAt(t); let segments = this.geometry.tangents.length; let pickt = t * segments; let pick = Math.floor(pickt); let pickNext = (pick + 1) % segments; this.binormal.subVectors( this.geometry.binormals[pickNext], this.geometry.binormals[pick] ); this.binormal .multiplyScalar(pickt - pick) .add(this.geometry.binormals[pick]); let dir = this.geometry.parameters.path.getTangentAt(t); let offset = 0; this.normal.copy(this.binormal).cross(dir); pos.add(this.normal.clone().multiplyScalar(offset)); this.camera.position.copy(pos); let lookAt = this.geometry.parameters.path.getPointAt( (t + 1 / this.geometry.parameters.path.getLength()) % 1 ); this.camera.matrix.lookAt(this.camera.position, lookAt, this.normal); this.camera.rotation.setFromRotationMatrix( this.camera.matrix, this.camera.rotation.order ); this.material.uniforms.time.value = this.clock.getElapsedTime(); requestAnimationFrame(this.render.bind(this)); this.renderer.render(this.scene, this.camera); } resize() { this.width = this.container.offsetWidth; this.height = this.container.offsetHeight; this.renderer.setSize(this.width, this.height); this.camera.aspect = this.width / this.height; this.camera.updateProjectionMatrix(); } setUpResize() { window.addEventListener("resize", this.resize.bind(this)); } } new Sketch({ domElement: document.getElementById("container") }); window.addEventListener("mousedown", function (e) { mouseIsDown = true; }); window.addEventListener("mouseup", function (e) { mouseIsDown = false; }); window.addEventListener("mousemove", function (e) { if (mouseIsDown) { timer += ((e.clientY / window.innerHeight) * 2 - 1) * 10; } if (timer <= 0) { timer = 0; } }); setInterval(() => { timer += 1 }, 10)