Globe Particles
Meng ToCommunityCreated by Meng To
- Skill
- Tool integration
- Software development
- MIT
- Medium risk
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured approach to creating a 3D globe visualization using WebGL and Three.js. It defines a specific particle system consisting of a dense spherical core and a surrounding orbital ring. The implementation includes custom vertex and fragment shaders to manage particle appearance, depth, and color blending, alongside a JavaScript recipe for initializing the scene, handling user interaction, and managing the animation loop.
What it does
- Generates a 3D globe structure using two distinct particle populations.
- Applies custom shaders for crisp, luminous particle rendering.
- Supports dynamic color mapping for core and accent elements.
- Includes mouse-responsive rotation and tilt controls.
- Provides a cleanup function for scene disposal and event listener removal.
- Respects user preferences for reduced motion.
When to use it
- When a design requires a planetary or synthesized data-globe effect.
- When integrating 3D WebGL visualizations into a dark-themed UI.
- When a project needs a cinematic, orbital-style motion graphic.
- When you need to represent infrastructure or data connectivity through a spherical particle model.
Advantages
- Separates core and ring particle populations for distinct visual control.
- Uses additive blending to create a luminous, depth-aware effect.
- Includes built-in support for responsive resizing and device pixel ratios.
- Provides granular tuning knobs for density, scale, and motion speed.
Usage examples
- “Initialize a globe particle visualization with a custom blue accent color.”
- The agent provides the configuration object with the accentColor property set to a blue hex code, passing it to the initGlobeParticles function.
- “How do I adjust the density of the globe's core?”
- The agent explains how to modify the sphereCount parameter within the options object passed to the particle geometry builder.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/mengto/globe-particles/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip globe-particles.zip -d .agents/skills
Documentation by Meng To
Globe Particles
Scope
Apply only to a globe-like 3D particle visualization.
Do not change full page layout, copy, or unrelated motion systems.
Use for planetary, orbital, infrastructure, or synthesized data-globe effects.
Keep the core neutral or white-hot and derive ring/glow accents from the design's primary color.
Visual Target
Dense spherical core of luminous points.
Thinner outer orbital ring or flattened disc around the sphere.
Clear globe silhouette with tilt, depth, and layered particle density.
Dark atmospheric background, restrained glow, clean structure, and subtle sci-fi depth.
Premium and cinematic, not playful or noisy.
HTML And CSS
<div class="globe-particles-shell">
<canvas class="globe-particles-canvas" data-globe-particles></canvas>
</div>.globe-particles-shell {
position: relative;
width: min(100%, 760px);
aspect-ratio: 1 / 1;
}
.globe-particles-canvas {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
display: block;
pointer-events: none;
}Particle Shader
Use circular shader points so particles stay crisp and luminous.
const globeParticleVertex = `
attribute float a_size;
attribute float a_layer;
uniform float u_time;
uniform float u_pointSize;
varying float v_layer;
varying float v_depth;
varying float v_falloff;
void main() {
vec3 pos = position;
float breathe = 1.0 + sin(u_time * 0.65 + a_layer * 4.0) * 0.012;
pos *= breathe;
vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
gl_PointSize = u_pointSize * a_size * (1.0 / max(0.18, -mvPosition.z));
gl_Position = projectionMatrix * mvPosition;
v_layer = a_layer;
v_depth = smoothstep(-1.8, 1.8, pos.z);
v_falloff = smoothstep(2.45, 0.25, length(pos));
}
`;
const globeParticleFragment = `
precision highp float;
uniform vec3 u_coreColor;
uniform vec3 u_accentColor;
varying float v_layer;
varying float v_depth;
varying float v_falloff;
void main() {
vec2 uv = gl_PointCoord - 0.5;
float d = length(uv);
float alpha = smoothstep(0.5, 0.0, d);
alpha *= alpha;
vec3 color = mix(u_coreColor, u_accentColor, smoothstep(0.35, 1.0, v_layer));
color += vec3(1.0) * v_depth * 0.08;
color = mix(color * 0.42, color, clamp(v_falloff + v_layer * 0.28, 0.0, 1.0));
alpha *= mix(0.52, 1.0, clamp(v_falloff + v_layer * 0.24, 0.0, 1.0));
gl_FragColor = vec4(color, alpha);
}
`;Three.js Recipe
import * as THREE from "three";
function hexToRgb01(hex) {
const clean = hex.replace("#", "").trim();
const value = clean.length === 3
? clean.split("").map((char) => char + char).join("")
: clean;
return new THREE.Color(
parseInt(value.slice(0, 2), 16) / 255,
parseInt(value.slice(2, 4), 16) / 255,
parseInt(value.slice(4, 6), 16) / 255
);
}
function buildGlobeParticleGeometry(options = {}) {
const sphereCount = options.sphereCount || 2600;
const ringCount = options.ringCount || 1300;
const radius = options.radius || 1.35;
const ringRadius = options.ringRadius || 2.05;
const ringThickness = options.ringThickness || 0.12;
const total = sphereCount + ringCount;
const positions = new Float32Array(total * 3);
const sizes = new Float32Array(total);
const layers = new Float32Array(total);
for (let i = 0; i < sphereCount; i++) {
const z = Math.random() * 2 - 1;
const theta = Math.random() * Math.PI * 2;
const r = radius * (0.58 + Math.pow(Math.random(), 0.42) * 0.42);
const root = Math.sqrt(1 - z * z);
const index = i * 3;
positions[index] = Math.cos(theta) * root * r;
positions[index + 1] = Math.sin(theta) * root * r;
positions[index + 2] = z * r;
sizes[i] = 0.72 + Math.random() * 0.72;
layers[i] = Math.random() * 0.28;
}
for (let i = 0; i < ringCount; i++) {
const pointIndex = sphereCount + i;
const angle = Math.random() * Math.PI * 2;
const r = ringRadius + (Math.random() - 0.5) * ringThickness;
const y = (Math.random() - 0.5) * ringThickness * 0.58;
const index = pointIndex * 3;
positions[index] = Math.cos(angle) * r;
positions[index + 1] = y;
positions[index + 2] = Math.sin(angle) * r;
sizes[pointIndex] = 0.62 + Math.random() * 0.58;
layers[pointIndex] = 0.72 + Math.random() * 0.28;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
geometry.setAttribute("a_size", new THREE.BufferAttribute(sizes, 1));
geometry.setAttribute("a_layer", new THREE.BufferAttribute(layers, 1));
return geometry;
}
function initGlobeParticles(canvas, options = {}) {
if (!canvas) return () => {};
const renderer = new THREE.WebGLRenderer({
canvas,
antialias: true,
alpha: true,
});
renderer.setClearColor(0x000000, 0);
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, options.maxDpr || 1.6));
renderer.outputColorSpace = THREE.SRGBColorSpace;
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(38, 1, 0.1, 100);
camera.position.set(0, 0, options.cameraDistance || 5.6);
const accent = options.accentColor
? new THREE.Color(options.accentColor)
: hexToRgb01(getComputedStyle(document.documentElement).getPropertyValue("--brand-accent").trim() || "#8b5cf6");
const geometry = buildGlobeParticleGeometry(options);
const material = new THREE.ShaderMaterial({
vertexShader: globeParticleVertex,
fragmentShader: globeParticleFragment,
transparent: true,
depthWrite: false,
blending: THREE.AdditiveBlending,
uniforms: {
u_time: { value: 0 },
u_pointSize: { value: options.pointSize || 18 },
u_coreColor: { value: new THREE.Color(options.coreColor || 0xf8fafc) },
u_accentColor: { value: accent },
},
});
const particles = new THREE.Points(geometry, material);
particles.rotation.x = options.tiltX ?? -0.42;
particles.rotation.z = options.tiltZ ?? 0.22;
scene.add(particles);
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const pointer = new THREE.Vector2(0, 0);
let rafId = 0;
function resize() {
const width = Math.max(1, canvas.clientWidth);
const height = Math.max(1, canvas.clientHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, options.maxDpr || 1.6));
renderer.setSize(width, height, false);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
function handlePointerMove(event) {
const rect = canvas.getBoundingClientRect();
pointer.x = ((event.clientX - rect.left) / rect.width - 0.5) * 2;
pointer.y = ((event.clientY - rect.top) / rect.height - 0.5) * 2;
}
function render(time = 0) {
const t = time * 0.001;
material.uniforms.u_time.value = t;
const mouseStrength = options.mouseStrength ?? 0.08;
const breath = reduceMotion ? 0 : Math.sin(t * 0.55) * 0.045;
particles.rotation.y = t * (options.rotationSpeed || 0.12);
particles.rotation.x = (options.tiltX ?? -0.42) + pointer.y * mouseStrength;
particles.rotation.z = (options.tiltZ ?? 0.22) + pointer.x * mouseStrength;
particles.scale.setScalar(1 + breath);
renderer.render(scene, camera);
if (!reduceMotion) rafId = requestAnimationFrame(render);
}
function handleResize() {
cancelAnimationFrame(rafId);
resize();
render();
}
resize();
render();
window.addEventListener("resize", handleResize);
window.addEventListener("pointermove", handlePointerMove);
return () => {
cancelAnimationFrame(rafId);
window.removeEventListener("resize", handleResize);
window.removeEventListener("pointermove", handlePointerMove);
geometry.dispose();
material.dispose();
renderer.dispose();
};
}
const cleanupGlobe = initGlobeParticles(document.querySelector("[data-globe-particles]"), {
sphereCount: 2600,
ringCount: 1300,
accentColor: "#8b5cf6",
radius: 1.35,
ringRadius: 2.05,
rotationSpeed: 0.12,
mouseStrength: 0.08,
});Tuning Knobs
Density: tune
sphereCountandringCountseparately.Scale: tune
radius,ringRadius,ringThickness, andcameraDistance.Color: keep
coreColorneutral; deriveaccentColorfrom the brand primary.Motion: tune
rotationSpeed,tiltX,tiltZ,mouseStrength, and breathing amplitude.Glow: tune
pointSize, additive blending, and particle count so the shape stays crisp.Performance: lower particle counts or cap
maxDprbefore changing the visual structure.
Taste Rules
The silhouette must read as a globe, not a loose starfield.
The ring should feel orbital and tilted, not like a flat decorative underline.
Use restrained glow; let density and depth create the premium feel.
Keep mouse response gentle so the object drifts rather than swings.
Put the globe over a dark background or inside a dark atmospheric shell.
Avoid
Generic starfield noise with no spherical structure.
Oversized particles or bloom that destroys the globe silhouette.
Hardcoded accent colors when the design has a clear primary color.
Wild cursor interaction or fast spinning.
Dense fog that turns the object into a blurry blob.
Quick Checks
Sphere and ring are distinct particle populations.
Core reads mostly neutral or white-hot.
Accent color appears on ring, highlights, or glow.
Tilt reveals the ring and globe depth.
Reduced motion renders a still or near-still object.
Geometry, material, renderer, listeners, and RAF are cleaned up.
Files
- ATTRIBUTION.mdAdded by AutoGineer852 B
- LICENSELicence file added by AutoGineer1.0 KiB
- SKILL.md9.7 KiB
- demo/PROMPT.md3.2 KiB
- demo/assets/page-01-fa51902b-c2a4-4c33-a96e-a8f1ef67edc6-1600w.jpg46.4 KiB
- demo/assets/page-02-4f5668c5-fc4a-44e0-bc5e-a664189d3c31-1600w.jpg212.3 KiB
- demo/assets/page-03-2f563338-39fa-47ea-9761-658d4f3f84db-1600w.jpg292.0 KiB
- demo/assets/source-preview.jpg108.9 KiB
- demo/index.html45.9 KiB
- demo/preview.jpg56.6 KiB
- demo/source.json3.9 KiB
demo/PROMPT.md
Globe Particles Demo Prompts
Minimal prompt
Use $globe-particles to create a responsive standalone HTML design with the same visual confidence, hierarchy, and interaction finish as the included Neuform reference.
Recreate the demo
Use $globe-particles to recreate the design quality and behavior of NEUS | Enterprise Brand Architecture as a complete responsive HTML document. Treat the included demo/index.html as the visual and interaction reference, not as a loose mood board.
Product brief
Page concept: NEUS | Enterprise Brand Architecture.
Purpose: Neus Enterprise Sidebar Component is designed for building reusable UI components in modern web projects. Key features include reusable structure, responsive behavior, and production-ready presentation. It is suitable for component libraries and responsive product interfaces.
Content anchors: System Architecture · Cinematic Topologies.
Useful subject tags: sidebar, animated, webgl, threejs, cta, dither, charts, navigation.
Skill direction
Create a 3D globe made from luminous particles, with a dense spherical core, orbital ring, additive glow, and subtle motion.
Globe Particles Skill
Scope:
Apply this to a globe-like 3D particle visualization only, not to the full page layout, copy, or unrelated motion systems.
Use it when the design needs a planetary, orbital, or synthesized data-globe effect rendered as particles.
Visual target:
Create a luminous particle globe with a dense spherical core of points and a thinner outer orbital ring or flattened disc surrounding it.
Keep the center mostly neutral or white-hot, then use the design's primary color or strongest accent color for the outer ring, highlights, or glow instead of hardcoding a specific lime or neon hue.
The silhouette should read clearly as a globe or planetary object with visible tilt, depth, and layered particle density.
Fidelity target
Match the reference's composition, information density, type scale, spacing rhythm, surface treatment, color relationships, and motion restraint.
Preserve the strongest interaction and animated background behavior instead of replacing it with generic fades or decorative movement.
Keep the first screen art-directed, then carry the same design logic through every supporting section.
Make the result responsive from mobile to desktop, keyboard accessible, and stable when reduced motion is enabled.
Deliver a full index.html. Put page-owned images, video, models, and textures in demo/assets/. External runtime libraries may stay as pinned CDN dependencies when the source relies on them.
Reference snapshot
Source: https://neuform.ai/pages/neus-enterprise-brand-architecture/index.html
Neuform rank: #1 for globe-particles when synced.
Popularity: 607 views · 21 favorites · 6 remixes.
Ranking rule: views descending, then favorites descending.
Remix prompt
Use $globe-particles and the included Neuform demo as the quality bar, but replace the brand, subject, copy, palette, and content. Preserve the underlying layout logic, signature visual treatment, interaction choreography, responsive behavior, and performance constraints so the remix still clearly demonstrates the skill.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
What our scanner noticed· Medium risk
- Large base64-encoded blobs
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Meng To
- Publisher
- Meng To (Community)
- Source
- MengTo/Skills · agent-skills/web-design/globe-particles · commit 5ea1661
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Meng To.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download globe-particles.zip