.knu-cap{position:absolute;left:0;right:0;bottom:6%;text-align:center;font-size:clamp(9px,2.4vmin,13px);color:#f1f0eccc}
import * as THREE from 'three';
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0d0d12);
const camera = new THREE.PerspectiveCamera(38, 1, 0.1, 100);
camera.position.set(0, 0.3, 6.4);
const canvas = document.createElement('canvas');
canvas.width = 256; canvas.height = 256;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#b9bec4'; ctx.fillRect(0, 0, 256, 256);
ctx.strokeStyle = '#6b6b76'; ctx.lineWidth = 3;
for (let i = -256; i < 512; i += 22) {
ctx.beginPath(); ctx.moveTo(i, 0); ctx.lineTo(i + 256, 256); ctx.stroke();
ctx.beginPath(); ctx.moveTo(i, 256); ctx.lineTo(i + 256, 0); ctx.stroke();
}
const tex = new THREE.CanvasTexture(canvas);
tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
tex.repeat.set(3, 1.4);
const geo = new THREE.CylinderGeometry(1.05, 1.05, 2.3, 48);
const mat = new THREE.MeshStandardMaterial({ map: tex, roughness: 0.55, metalness: 0.5 });
const knob = new THREE.Mesh(geo, mat);
scene.add(knob);
const key = new THREE.DirectionalLight(0xffffff, 2.2); key.position.set(3, 4, 5); scene.add(key);
const rim = new THREE.DirectionalLight(0x8fb0ff, 0.7); rim.position.set(-4, -1, -3); scene.add(rim);
scene.add(new THREE.AmbientLight(0xffffff, 0.4));
function resize() { renderer.setSize(innerWidth, innerHeight); camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); }
addEventListener('resize', resize); resize();
renderer.setAnimationLoop((t) => {
knob.rotation.y = t * 0.00045;
camera.lookAt(0, 0, 0);
renderer.render(scene, camera);
});