JSFiddle - React, Tailwind, and code Playground
JavaScript
import * as THREE from 'https://cdn.skypack.dev/[email protected]/build/three.module.js';
import {
OrbitControls
} from 'https://cdn.skypack.dev/[email protected]/examples/jsm/controls/OrbitControls.js';
import {
GLTFLoader
} from 'https://cdn.skypack.dev/[email protected]/examples/jsm/loaders/GLTFLoader.js';
let camera, scene, renderer, stats;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(27, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.z = 20;
scene = new THREE.Scene();
const loader = new GLTFLoader();
loader.load('https://threejs.org/examples/models/gltf/LeePerrySmith/LeePerrySmith.glb', function(gltf) {
const geometry = gltf.scene.children[0].geometry;
let mesh = new THREE.Mesh(geometry, buildTwistMaterial(2.0));
mesh.position.x = -3.5;
mesh.position.y = -0.5;
scene.add(mesh);
mesh = new THREE.Mesh(geometry, buildTwistMaterial(-2.0));
mesh.position.x = 3.5;
mesh.position.y = -0.5;
scene.add(mesh);
});
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.minDistance = 10;
controls.maxDistance = 50;
// EVENTS
window.addEventListener('resize', onWindowResize);
}
function buildTwistMaterial(amount) {
const material = new THREE.MeshNormalMaterial();
material.onBeforeCompile = function(shader) {
shader.uniforms.time = {
value: 0
};
shader.vertexShader = 'uniform float time;\n' + shader.vertexShader;
shader.vertexShader = shader.vertexShader.replace(
'#include <begin_vertex>',
[
`float theta = sin( time + position.y ) / ${ amount.toFixed( 1 ) };`,
'float c = cos( theta );',
'float s = sin( theta );',
'mat3 m = mat3( c, 0, s, 0, 1, 0, -s,...