Copy URL or Code
Paste to your AI coding assistant and customize:
Done. Your AI handles the rest.
Fully customizable. Uses dual-canvas CSS blur technique for GPU-accelerated glow. No expensive WebGL post-processing required. Works on most devices.
/*
================================================================================
AI COMPONENT: NeonWireframe
================================================================================
SETUP:
1. Create file: components/NeonWireframe.tsx
2. Install dependencies: npm install three @types/three
3. Copy this entire code block into that file
4. Import: import NeonWireframe from "@/components/NeonWireframe"
================================================================================
TECHNIQUE: CSS-based Glow (Dual Canvas)
================================================================================
This component uses TWO canvases rendering the same scene:
- Lower canvas: Normal render
- Upper canvas: Same render with CSS blur + brightness + screen blend
This achieves a bloom/glow effect WITHOUT expensive WebGL post-processing.
It's GPU-accelerated via CSS and works on most devices.
================================================================================
QUICK CUSTOMIZATION (via props)
================================================================================
| Prop | Type | Default | Description |
|-----------------|---------|---------|-------------------------------------|
| width | number | 320 | Canvas width in pixels |
| height | number | 320 | Canvas height in pixels |
| color | string | "cyan" | Line color (any CSS color) |
| autoRotate | boolean | true | Enable auto-rotation |
| autoRotateSpeed | number | 0.5 | Rotation speed |
| blurAmount | number | 5 | Glow blur radius (px) |
| brightness | number | 200 | Glow brightness (%) |
================================================================================
COMMON MODIFICATIONS
================================================================================
1. DIFFERENT GLOW COLOR:
<NeonWireframe color="hotpink" />
<NeonWireframe color="#00ff00" />
<NeonWireframe color="orange" />
2. STRONGER GLOW:
<NeonWireframe blurAmount={10} brightness={300} />
3. SUBTLE GLOW:
<NeonWireframe blurAmount={3} brightness={150} />
4. STATIC (NO ROTATION):
<NeonWireframe autoRotate={false} />
5. CUSTOM SIZE:
<NeonWireframe width={600} height={400} />
================================================================================
SWAPPING GEOMETRIES (for AI assistants)
================================================================================
Replace the TorusKnotGeometry with other Three.js geometries:
// Icosahedron (sci-fi sphere)
const geometry = new THREE.IcosahedronGeometry(1.5, 1);
// Octahedron (diamond)
const geometry = new THREE.OctahedronGeometry(1.5);
// Dodecahedron (12-sided)
const geometry = new THREE.DodecahedronGeometry(1.5);
// Custom from GLTF model:
// import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
// new GLTFLoader().load("/model.glb", (gltf) => {
// const edges = new THREE.EdgesGeometry(gltf.scene.children[0].geometry);
// const lines = new THREE.LineSegments(edges, lineMaterial);
// scene.add(lines);
// });
================================================================================
SOURCE CODE
================================================================================
*/
"use client";
import React, { useRef, useEffect, useCallback } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
export interface NeonWireframeProps {
width?: number;
height?: number;
className?: string;
color?: string;
autoRotate?: boolean;
autoRotateSpeed?: number;
blurAmount?: number;
brightness?: number;
}
export default function NeonWireframe({
width = 320,
height = 320,
className = "",
color = "cyan",
autoRotate = true,
autoRotateSpeed = 0.5,
blurAmount = 5,
brightness = 200,
}: NeonWireframeProps) {
const containerRef = useRef<HTMLDivElement>(null);
const lowerCanvasRef = useRef<HTMLCanvasElement>(null);
const upperCanvasRef = useRef<HTMLCanvasElement>(null);
const animationRef = useRef<number | null>(null);
const cleanupRef = useRef<(() => void) | null>(null);
const initScene = useCallback(() => {
if (!containerRef.current || !lowerCanvasRef.current || !upperCanvasRef.current) return;
// Normal renderer (lower canvas)
const renderer = new THREE.WebGLRenderer({
canvas: lowerCanvasRef.current,
antialias: true,
alpha: true,
});
renderer.setSize(width, height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
// Blur renderer (upper canvas) - blur applied via CSS
const blurRenderer = new THREE.WebGLRenderer({
canvas: upperCanvasRef.current,
antialias: true,
alpha: true,
});
blurRenderer.setSize(width, height);
blurRenderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
// Scene
const scene = new THREE.Scene();
// Camera
const camera = new THREE.PerspectiveCamera(30, width / height, 0.1, 1000);
camera.position.set(0, 2, 8);
// Controls - attach to upper canvas (the one on top)
const controls = new OrbitControls(camera, upperCanvasRef.current);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.autoRotate = autoRotate;
controls.autoRotateSpeed = autoRotateSpeed;
controls.enableZoom = false;
// Create torus knot with edge geometry for wireframe lines
const torusKnotGeometry = new THREE.TorusKnotGeometry(1.2, 0.4, 128, 32);
const edgesGeometry = new THREE.EdgesGeometry(torusKnotGeometry, 15);
const lineMaterial = new THREE.LineBasicMaterial({
color: color,
transparent: true,
opacity: 1,
});
const torusKnot = new THREE.LineSegments(edgesGeometry, lineMaterial);
torusKnot.position.set(0, 0, 0);
scene.add(torusKnot);
// Animation loop
let time = 0;
const animate = () => {
time++;
controls.update();
// Subtle floating motion
torusKnot.position.y = Math.sin(time * 0.01) * 0.1;
// Render normal scene
renderer.render(scene, camera);
// Render blurred scene (CSS handles the blur)
blurRenderer.render(scene, camera);
animationRef.current = requestAnimationFrame(animate);
};
animate();
// Cleanup function
cleanupRef.current = () => {
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
}
controls.dispose();
torusKnotGeometry.dispose();
edgesGeometry.dispose();
lineMaterial.dispose();
renderer.dispose();
blurRenderer.dispose();
};
}, [width, height, color, autoRotate, autoRotateSpeed]);
useEffect(() => {
initScene();
return () => {
if (cleanupRef.current) {
cleanupRef.current();
}
};
}, [initScene]);
return (
<div
ref={containerRef}
className={`relative ${className}`}
style={{
width,
height,
backgroundColor: "#000",
borderRadius: 8,
overflow: "hidden",
}}
>
{/* Lower canvas - normal scene */}
<canvas
ref={lowerCanvasRef}
style={{
position: "absolute",
left: 0,
top: 0,
width,
height,
}}
/>
{/* Upper canvas - blurred for glow effect */}
<canvas
ref={upperCanvasRef}
style={{
position: "absolute",
left: 0,
top: 0,
width,
height,
zIndex: 1,
filter: `blur(${blurAmount}px) brightness(${brightness}%)`,
mixBlendMode: "screen",
pointerEvents: "auto",
}}
/>
</div>
);
}
export { NeonWireframe };import NeonWireframe from "@/components/NeonWireframe";
// Basic usage - cyan glowing torus knot
export default function GlowDemo() {
return (
<div className="bg-black min-h-screen flex items-center justify-center">
<NeonWireframe />
</div>
);
}
// Custom color and stronger glow
export function PinkGlow() {
return (
<NeonWireframe
color="hotpink"
blurAmount={8}
brightness={250}
/>
);
}
// Large static display
export function HeroSection() {
return (
<div className="relative">
<NeonWireframe
width={800}
height={600}
color="#00ff88"
autoRotate={false}
/>
<h1 className="absolute inset-0 flex items-center justify-center text-white text-4xl">
Your Text Here
</h1>
</div>
);
}
// Multiple colors side by side
export function ColorShowcase() {
const colors = ["cyan", "hotpink", "lime", "orange"];
return (
<div className="flex gap-4">
{colors.map((c) => (
<NeonWireframe key={c} color={c} width={200} height={200} />
))}
</div>
);
}