Evil thing

by Scott Kaye

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>
<script src="https://threejs.org/examples/js/postprocessing/EffectComposer.js"></script>
<script src="https://threejs.org/examples/js/postprocessing/RenderPass.js"></script>
<script src="https://threejs.org/examples/js/postprocessing/MaskPass.js"></script>
<script src="https://threejs.org/examples/js/postprocessing/ShaderPass.js"></script>
<script src="https://threejs.org/examples/js/shaders/CopyShader.js"></script>
<script src="https://threejs.org/examples/js/shaders/FXAAShader.js"></script>
<script src="https://threejs.org/examples/js/shaders/ConvolutionShader.js"></script>
<script src="https://threejs.org/examples/js/shaders/LuminosityHighPassShader.js"></script>
<script src="https://threejs.org/examples/js/postprocessing/UnrealBloomPass.js"></script>
<div class="overlay"></div>

CSS

body {
    margin: 0;
    overflow: hidden;
    background: #000;
	display: flex;
	justify-content: center;
	align-items: center;
	height: 100vh;
}

canvas {
    background: #000;
	border-radius: 50%;
	box-shadow: 0 0 100px rgba(255,40,125, 0.25);
	border: 1px solid #f37;
	animation: r 30s linear infinite;
	position: relative;
}

.overlay {
	position: absolute;
	width: 600px;
	height: 600px;
	border-radius: 50%;
	z-index: 1;
	box-shadow: inset 0 0 80px 40px #000;
}

@keyframes r {
	to {
		transform: rotateZ(360deg);
	}
}

JavaScript

const numPoints = 200;
const maxDistance = 70;
const primaryColor = 0xff3377;
const speed = 2.25;
const starRadius = 20;

var params = {
    bloomStrength: 2,
    bloomThreshold: 0.1,
    bloomRadius: 1.1
};


const scene = new THREE.Scene();
let width = 600;
let height = 600;
const camera = new THREE.OrthographicCamera(width / -2, width / 2, height / 2, height / -2, -10, 1000);

var renderer = new THREE.WebGLRenderer({
    alpha: false,
    antialias: true
});
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);

let points = [];
let lineGeometry = new THREE.BufferGeometry();
let lineMaterial = new THREE.LineBasicMaterial({
    vertexColors: THREE.VertexColors,
    color: primaryColor,
    blending: THREE.AdditiveBlending,
    transparent: true
});

let theLine = new THREE.LineSegments(lineGeometry, lineMaterial);
scene.add(theLine);

for (let i = 0; i < numPoints; ++i) {
    var geometry = new THREE.SphereGeometry(starRadius, 8, 8);
    var material = new THREE.PointsMaterial({
        color: 0x000000
    });

    var cube = new THREE.Mesh(geometry, material);
    cube.position.x = Math.random() * width - width / 2;
    cube.position.y = Math.random() * height - height / 2;

    scene.add(cube);

    let point = {
        mesh: cube,
        vx: (Math.random() - 0.5) * speed,
        vy: (Math.random() - 0.5) * speed
    };

    points.push(point);
}

let vertices = new Float32Array(numPoints * numPoints * 3);
let colors = new Float32Array(numPoints * numPoints * 3);

lineGeometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3).setDynamic(true));
lineGeometry.setAttribute("color", new THREE.BufferAttribute(colors, 3).setDynamic(true));

const renderScene = new THREE.RenderPass(scene, camera);
const bloomPass = new THREE.UnrealBloomPass(new THREE.Vector2(width, height), 1.5, 0.4, 0.85);
bloomPass.threshold = params.bloomThreshold;
bloomPass.strength = params.bloomStrength;
bloomPass.radius = params.bloomRadius;

const...