ck42bb/procedural-stars-threejs/procedural-stars-threejs

Claude Code and agent skill by ck42bb/procedural-stars-threejs

Trust tier 3
  • community
  • ext:[{"type":"plugin","description":"Custom plugin integration"}]
Source check pending

Checking that the SKILL.md file is still in the repository.

Generate stunning procedural night skies, starfields, nebulae, and celestial phenomena in Three.js using WebGPU compute with WebGL2 fallback. Covers scientifically-grounded starfields with spectral color temperature, magnitude-based brightness, and twinkling; volumetric nebulae with emission/absorption/reflection types; the Milky Way band; constellations with optional line overlays; planets and moons with phase lighting; shooting stars and meteor showers; aurora integration; eclipses (solar and lunar); comets with ion/dust tails; galaxies as deep-sky backdrop objects; and a full sky dome controller with time-of-night progression, moon phases, and horizon glow. Triggers: "procedural starfield", "night sky", "star rendering", "nebula", "deep space", "milky way", "constellation", "shooting star", "meteor shower", "celestial", "space background", "starbox", "skybox stars", "galaxy background", "moon phases", "comet", "eclipse", "space scene", "star shader".

Install

npx vskill@latest install ck42bb/procedural-stars-threejs/procedural-stars-threejs

Semi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard

SKILL.md

Procedural Starfield & Celestial Phenomena

Generate breathtaking night skies in Three.js — from photorealistic starfields to dreamy nebulae to dramatic celestial events.

Architecture Overview

┌──────────────────────────────────────────────────────┐
│ Night Sky Pipeline │
│ │
│ SkyController (master orchestrator) │
│ ├── time progression (sunset → night → dawn) │
│ ├── moon phase + position │
│ └── drives all layers: │
│ │
│ ┌─ Layer 1: Sky Dome ──────────────────────────┐ │
│ │ Gradient background, horizon glow, zodiacal │ │
│ └──────────────────────────────────────────────┘ │
│ ┌─ Layer 2: Stars ─────────────────────────────┐ │
│ │ Points with spectral color + magnitude │ │
│ │ Twinkle, proper motion (optional) │ │
│ └──────────────────────────────────────────────┘ │
│ ┌─ Layer 3: Milky Way ─────────────────────────┐ │
│ │ Textured band or procedural FBM glow │ │
│ └──────────────────────────────────────────────┘ │
│ ┌─ Layer 4: Nebulae ───────────────────────────┐ │
│ │ Volumetric raymarched or billboard sprites │ │
│ └──────────────────────────────────────────────┘ │
│ ┌─ Layer 5: Celestial Bodies ──────────────────┐ │
│ │ Moon (phase lit), planets, sun glow │ │
│ └──────────────────────────────────────────────┘ │
│ ┌─ Layer 6: Transients ────────────────────────┐ │
│ │ Shooting stars, comets, eclipses, satellites│ │
│ └──────────────────────────────────────────────┘ │
│ ┌─ Layer 7: Deep Space (optional) ─────────────┐ │
│ │ Distant galaxies, star clusters, dust lanes │ │
│ └──────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘

Renderer Setup

javascript
import * as THREE from 'three';
async function createRenderer(canvas) {
let renderer, gpuAvailable = false;
try {
const WebGPU = (await import('three/addons/capabilities/WebGPU.js')).default;
if (WebGPU.isAvailable()) {
const { default: WebGPURenderer } = await import(
'three/addons/renderers/webgpu/WebGPURenderer.js'
);
renderer = new WebGPURenderer({ canvas, antialias: true });
await renderer.init();
gpuAvailable = true;
}
} catch (e) {}
if (!renderer) {
renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;
}
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
return { renderer, gpuAvailable };
}

Layer 1: Sky Dome

Gradient hemisphere that transitions from deep zenith to warm horizon glow, with optional light pollution and twilight blending.

javascript
function createSkyDome(radius = 500) {
const geo = new THREE.SphereGeometry(radius, 32, 16);
const material = new THREE.ShaderMaterial({
uniforms: {
zenithColor: { value: new THREE.Color(0x020010) },
midColor: { value: new THREE.Color(0x0a0a2a) },
horizonColor: { value: new THREE.Color(0x15102a) },
horizonGlow: { value: new THREE.Color(0x1a1530) },
glowStrength: { value: 0.3 },
lightPollution: { value: 0.0 }, // 0=pristine, 1=urban
moonPos: { value: new THREE.Vector3(0, 0.5, -1).normalize() },
moonGlowStr: { value: 0.15 },
},
vertexShader: `
varying vec3 vWorldDir;
void main() {
vec4 worldPos = modelMatrix * vec4(position, 1.0);
vWorldDir = normalize(worldPos.xyz);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: SKY_DOME_FRAG, // See references/celestial-shaders.md
side: THREE.BackSide,
depthWrite: false,
});
return new THREE.Mesh(geo, material);
}

Layer 2: Starfield

The heart of the night sky. Each star is a Points particle with scientifically- grounded color (spectral class → blackbody temperature), magnitude-based size/brightness, and animated twinkle.

Star Generation
javascript
class Starfield {
constructor(scene, options = {}) {
this.scene = scene;
this.count = options.count ?? 8000;
this.radius = options.radius ?? 400;
this.minMagnitude = options.minMagnitude ?? -1.5; // Brightest (Sirius)
this.maxMagnitude = options.maxMagnitude ?? 6.5; // Faintest visible
this.twinkleSpeed = options.twinkleSpeed ?? 1.0;
this.seed = options.seed ?? 42;
this._build();
}
_build() {
const positions = new Float32Array(this.count * 3);
const starData = new Float32Array(this.count * 4); // r, g, b, magnitude
let rng = this.seed;
const random = () => { rng = (rng * 16807) % 2147483647; return rng / 2147483647; };
for (let i = 0; i < this.count; i++) {
// Uniform distribution on sphere
const theta = random() * Math.PI * 2;
const phi = Math.acos(2 * random() - 1);
positions[i * 3] = Math.sin(phi) * Math.cos(theta) * this.radius;
positions[i * 3 + 1] = Math.sin(phi) * Math.sin(theta) * this.radius;
positions[i * 3 + 2] = Math.cos(phi) * this.radius;
// Magnitude: exponential distribution (many faint, few bright)
const mag = this.minMagnitude + Math.pow(random(), 0.4) * (this.maxMagnitude - this.minMagnitude);
// Spectral color from temperature
const temp = this._randomStarTemp(random());
const col = blackbodyColor(temp);
starData[i * 4] = col.r;
starData[i * 4 + 1] = col.g;
starData[i * 4 + 2] = col.b;
starData[i * 4 + 3] = mag;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('aStarData', new THREE.BufferAttribute(starData, 4));
this.material = new THREE.ShaderMaterial({
uniforms: {
time: { value: 0 },
twinkleSpeed: { value: this.twinkleSpeed },
brightnessExp: { value: 2.5 }, // Magnitude → size exponent
baseSizePx: { value: 2.5 },
glowFalloff: { value: 0.4 },
exposure: { value: 1.0 },
},
vertexShader: STAR_VERT, // See references/celestial-shaders.md
fragmentShader: STAR_FRAG, // See references/celestial-shaders.md
transparent: true,
depthWrite: false,
blending: THREE.AdditiveBlending,
});
this.mesh = new THREE.Points(geometry, this.material);
this.mesh.frustumCulled = false;
this.scene.add(this.mesh);
}
// Realistic star temperature distribution
_randomStarTemp(r) {
// Weighted toward cooler stars (M/K/G), fewer hot O/B
if (r < 0.003) return 30000 + r * 5000000; // O: blue-white
if (r < 0.01) return 10000 + r * 1000000; // B: blue
if (r < 0.04) return 7500 + r * 60000; // A: white
if (r < 0.11) return 6000 + r * 15000; // F: yellow-white
if (r < 0.23) return 5200 + r * 5000; // G: yellow (Sun-like)
if (r < 0.50) return 3700 + r * 3000; // K: orange
return 2400 + r * 2600; // M: red
}
update(time) {
this.material.uniforms.time.value = time;
}
dispose() {
this.scene.remove(this.mesh);
this.mesh.geometry.dispose();
this.material.dispose();
}
}
Blackbody Color Function

Convert Kelvin temperature to RGB for accurate star colors:

javascript
function blackbodyColor(tempK) {
// Attempt a physically-grounded approximation (Tanner Helland algorithm)
const t = tempK / 100;
let r, g, b;
if (t <= 66) {
r = 255;
g = 99.4708025861 * Math.log(t) - 161.1195681661;
b = t <= 19 ? 0 : 138.5177312231 * Math.log(t - 10) - 305.0447927307;
} else {
r = 329.698727446 * Math.pow(t - 60, -0.1332047592);
g = 288.1221695283 * Math.pow(t - 60, -0.0755148492);
b = 255;
}
return new THREE.Color(
Math.min(Math.max(r, 0), 255) / 255,
Math.min(Math.max(g, 0), 255) / 255,
Math.min(Math.max(b, 0), 255) / 255
);
}

Star spectral classes and their temperatures/colors:

ClassTemp (K)ColorFractionExamples
O30,000+Blue-violet0.003%Mintaka
B10,000–30,000Blue-white0.1%Rigel, Spica
A7,500–10,000White0.6%Sirius, Vega
F6,000–7,500Yellow-white3%Procyon
G5,200–6,000Yellow8%Sun, Alpha Centauri
K3,700–5,200Orange12%Arcturus
M2,400–3,700Red-orange76%Betelgeuse, Proxima

Layer 3: Milky Way

A luminous band across the sky, rendered as a textured strip or procedural FBM glow on the sky dome.

javascript
function createMilkyWay(scene, radius = 450) {
const geo = new THREE.SphereGeometry(radius, 64, 32);
const material = new THREE.ShaderMaterial({
uniforms: {
time: { value: 0 },
brightness: { value: 0.25 },
bandWidth: { value: 0.18 }, // Angular width of the band
bandTilt: { value: 0.4 }, // Tilt angle in radians
coreGlow: { value: 0.6 }, // Sagittarius core brightness
dustLanes: { value: 0.4 }, // Dark lane intensity
warmTint: { value: new THREE.Color(0xffe8cc) },
coolTint: { value: new THREE.Color(0xccddff) },
},
vertexShader: `
varying vec3 vWorldDir;
void main() {
vWorldDir = normalize((modelMatrix * vec4(position, 1.0)).xyz);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: MILKY_WAY_FRAG, // See references/celestial-shaders.md
side: THREE.BackSide,
transparent: true,
depthWrite: false,
blending: THREE.AdditiveBlending,
});
const mesh = new THREE.Mesh(geo, material);
scene.add(mesh);
return { mesh, material };
}

Layer 4: Nebulae

Volumetric Nebula (WebGPU — Raymarched)

Full 3D nebula rendered by marching through an emission/absorption density field.

javascript
function createVolumetricNebula(scene, options = {}) {
const {
position = new THREE.Vector3(100, 80, -200),
scale = 80,
type = 'emission', // emission | reflection | dark | planetary
color1 = new THREE.Color(0xff2266),
color2 = new THREE.Color(0x4466ff),
color3 = new THREE.Color(0x22ffaa),
} = options;
const geo = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.ShaderMaterial({
uniforms: {
cameraPos: { value: new THREE.Vector3() },
nebulaScale: { value: scale },
color1: { value: color1 },
color2: { value: color2 },
color3: { value: color3 },
density: { value: 0.5 },
brightness: { value: 1.2 },
noiseOctaves: { value: 5 },
time: { value: 0 },
nebulaType: { value: NEBULA_TYPE_MAP[type] },
},
vertexShader: NEBULA_VERT,
fragmentShader: NEBULA_FRAG, // See references/celestial-shaders.md
transparent: true,
depthWrite: false,
side: THREE.BackSide,
blending: THREE.AdditiveBlending,
});
const mesh = new THREE.Mesh(geo, material);
mesh.position.copy(position);
mesh.scale.setScalar(scale);
scene.add(mesh);
return { mesh, material };
}
const NEBULA_TYPE_MAP = { emission: 0, reflection: 1, dark: 2, planetary: 3 };
Billboard Nebula (WebGL Fallback)

Canvas-generated nebula sprite for cheaper rendering.

javascript
function createBillboardNebula(scene, options = {}) {
const size = options.size ?? 512;
const canvas = document.createElement('canvas');
canvas.width = canvas.height = size;
const ctx = canvas.getContext('2d');

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 98 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

  • SKILL.md in the repositoryCheckingSKILL.md

Popularity

Repository stars
1
Repository forks
1
7-day trend score
3

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 19 Mar 2026, 7 months ago.

Extension points

  • pluginCustom plugin integration

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/ck42bb/procedural-stars-threejs/procedural-stars-threejs/badge)](https://verified-skill.com/skills/ck42bb/procedural-stars-threejs/procedural-stars-threejs)

Something wrong with this skill or its page? Tell us.