tunnel demo
This commit is contained in:
161
src/index.js
Normal file
161
src/index.js
Normal file
@@ -0,0 +1,161 @@
|
||||
// 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)
|
||||
Reference in New Issue
Block a user