{
const w = width
const h = 640
const scene = new THREE.Scene()
scene.fog = new THREE.FogExp2(0x1f1f1f, 0.01)
scene.background = new THREE.Color(0x1f1f1f)
const SIDES = 20
const SEGMENTS = 200
const geometry = new THREE.BufferGeometry()
const indices = []
const vertices = new Float32Array(SIDES * SEGMENTS * 3)
let ptr = 0
for (let segment = 0; segment < SEGMENTS; segment++) {
for (let side = 0; side < SIDES; side++) {
vertices[ptr] = segment
vertices[ptr + 1] = side
vertices[ptr + 2] = 0
ptr += 3
}
}
const MAX = SEGMENTS * SIDES
for (let segment = 0; segment < SEGMENTS + 1; segment++) {
for (let f = 0; f < SIDES; f++) {
const a = (segment * SIDES + ((f + 1) % SIDES)) % MAX
const b = (segment * SIDES + f) % MAX
const c = (segment * SIDES + f + SIDES) % MAX
const d = (segment * SIDES + ((f + 1) % SIDES) + SIDES) % MAX
indices.push(a, b, d)
indices.push(b, c, d)
}
}
geometry.setIndex(indices)
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3))
const loader = new THREE.TextureLoader()
const matcap1 = loader.load(matcapUrl)
const matcap2 = loader.load('https://makio135.com/matcaps/512/736655_D9D8D5_2F281F_B1AEAB-512px.png')
const matcap3 = loader.load('https://makio135.com/matcaps/512/181F1F_475057_616566_525C62-512px.png')
const g = new THREE.Group()
scene.add(g)
const TAU = 2 * Math.PI
const meshes = []
const N = 9
for (let i = 0; i < N; i++) {
const geoMat = new THREE.RawShaderMaterial({
uniforms: {
SEGMENTS: { value: SEGMENTS },
SIDES: { value: SIDES },
matCapMap: {
value: i % 3 === 0 ? matcap1 : i % 3 === 1 ? matcap2 : matcap3,
},
time: { value: 0 },
index: { value: i },
},
vertexShader: vertexShader(),
fragmentShader: fragmentShader(),
})
const angle = (i * TAU) / N
const t = new THREE.Mesh(geometry, geoMat)
g.add(t)
meshes.push(t)
}
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(w, h)
renderer.setPixelRatio(devicePixelRatio)
const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 150)
camera.position.set(0, 5, 40).multiplyScalar(1.05)
camera.lookAt(new THREE.Vector3(0, 0, 10))
const controls = new THREE.OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
controls.maxDistance = 50
invalidation.then(() => (controls.dispose(), renderer.dispose()))
controls.addEventListener("change", () => renderer.render(scene, camera))
while (true) {
meshes.forEach(m => m.material.uniforms.time.value = 0.0005 * performance.now())
controls.update()
renderer.render(scene, camera)
renderer.domElement.style.cursor = 'pointer'
yield renderer.domElement
}
}