Skip to content

Étoiles

Le pipeline étoile est structurellement distinct du pipeline planète. Une étoile n'a pas de relief jouable, pas de surface liquide, pas d'atmosphère cliquable, pas de basculement de vue ; en contrepartie, elle porte une granulation animée, une corona, une pulsation, et son look est entièrement dérivé de son spectralType — sans caller-side palette à fournir.

Ce guide consolide tout ce qui touche aux étoiles : configuration, handle, helpers spectraux, conversions Kelvin et calibration des effets post-process. Pour les concepts généraux (déterminisme, séparation sim/core/vue, pipeline planète), voir Concepts fondamentaux.

Hello, étoile

ts
import { useBody, DEFAULT_TILE_SIZE } from '@cedric-pouilleux/stellexjs/core'

const sun = useBody({
  type:          'star',
  spectralType:  'G',
  name:          'Sol',
  radius:         3,
  rotationSpeed:  0.01,
  axialTilt:      0,
}, DEFAULT_TILE_SIZE)

scene.add(sun.group)

renderer.setAnimationLoop((dt) => {
  sun.tick(dt)        // avance granulation + pulsation + corona
  renderer.render(scene, camera)
})

spectralType est obligatoire sur une StarConfig — c'est lui qui pilote palette, granulation, corona, godrays et tile-ref radius.

Classification spectrale

Sept classes Morgan–Keenan supportées. La table interne SPECTRAL_TABLE (exportée depuis /sim) fournit les valeurs canoniques :

spectralTypeCouleur visuelletempKradius (réf.)Description
'O'Bleu-blanc40 000 K15Géante massive, rare, durée de vie courte
'B'Bleu-blanc20 000 K7Géante chaude
'A'Blanc9 000 K4Étoile blanche
'F'Blanc-jaune7 000 K3.5Plus chaude que le Soleil
'G'Jaune (Soleil)5 778 K3Référence — REF_STAR_TEMP, REF_STAR_RADIUS
'K'Orange4 500 K2.5Plus froide que le Soleil
'M'Rouge3 000 K1.5Naine rouge

Le radius du tableau est une valeur visuelle (unités monde), pas une grandeur astrophysique. La luminosité relative est dérivée de Stefan-Boltzmann par resolveStarData — pas hardcodée.

Le handle StarBody

ts
const sun = useBody(starConfig, DEFAULT_TILE_SIZE)
if (sun.kind === 'star') {
  // ...
}

StarBody est la branche étoile de l'union Body. Vs PlanetBody, elle :

TraitPlanetBodyStarBody
kind'planet''star'
liquidprésentabsent
viewprésent ('surface' | 'atmosphere' | 'shader')absent (toujours en mode shader)
atmoShellAtmoShellHandle | nullabsent
tiles.atmoBoardTiles | nullabsent (pas de board atmo)
tiles.solSolBoardTiles (avec updateTileSolHeight)absenttiles est plat (StarTiles)
tiles.tileBaseVisualsous tiles.sol.tileBaseVisualdirectement sur tiles.tileBaseVisual
tiles.writeTileColorsous tiles.sol.writeTileColordirectement sur tiles.writeTileColor
flatSurface (strategy)falsetrue (granulation = shader effect)
canHaveRings (strategy)truefalse
tick(dt)rotation + uniforms atmogranulation + corona + pulsation

Les primitives communes (présentes sur les deux branches) restent disponibles : group, sim, palette, variation, planetMaterial, graphicsUniforms, hoverChannel, interactive, hover, tick, dispose, getCoreRadius, getSurfaceRadius.

Tile count et STAR_TILE_REF

Sur une planète, le tile count dérive de radius. Sur une étoile, ça produirait des tuiles minuscules sur les O et démesurées sur les M (le ratio de rayon est 15:1.5 = 10x entre les extrêmes). Pour stabiliser les tile counts, le pipeline étoile utilise STAR_TILE_REF :

ts
import { STAR_TILE_REF } from '@cedric-pouilleux/stellexjs/core'
// { M: 2.0, K: 2.5, G: 3.0, F: 3.5 }
SpectralTile-ref radiusEffet
M2.0Naines rouges — tile count bumped malgré le petit radius
K2.5
G3.0Identité (réf Soleil)
F3.5
A/B/Ofallback 3.0Pas listés — utilisent la valeur G par défaut

Le tile count concret est tileSizeToSubdivisions(STAR_TILE_REF[spectralType], tileSize).

Dérivations physiques

Trois helpers exportés depuis /sim (donc utilisables côté serveur / worker / CLI sans WebGL) :

resolveStarData

ts
import { resolveStarData } from '@cedric-pouilleux/stellexjs/sim'

const data = resolveStarData({ spectralType: 'M' })
// { tempK: 3000, radius: 1.5, luminosity: 0.067, color: '#ffcc6f' }

luminosity est calculée via Stefan-Boltzmann relative au G (L_G = 1). color est la teinte CSS canonique de la classe spectrale (utile pour les UI / minimap).

tempK et radius peuvent être overridés :

ts
resolveStarData({ spectralType: 'G', tempK: 5500, radius: 2.8 })
// → tempK et radius surchargés ; luminosity recalculée depuis ces overrides

toStarParams

ts
import { toStarParams } from '@cedric-pouilleux/stellexjs/sim'

const params = toStarParams({ spectralType: 'O' })
// { radius: 15, tempK: 40000 }

Forme minimaliste — utile quand seuls radius + tempK sont consommés (mécanique orbitale, FX de chaleur, etc.).

SPECTRAL_TABLE

Lecture directe quand vous voulez la valeur sans traverser un resolver :

ts
import { SPECTRAL_TABLE } from '@cedric-pouilleux/stellexjs/sim'

console.log(SPECTRAL_TABLE.G.tempK)   // 5778
console.log(SPECTRAL_TABLE.M.color)   // '#ffcc6f'

Helpers Kelvin

Trois utilitaires de conversion couleur exportés depuis /core. Utilisent l'approximation de Tanner Helland, valide entre ~1 000 K et ~40 000 K.

ts
import { kelvinToRGB, kelvinToThreeColor, kelvinLabel } from '@cedric-pouilleux/stellexjs/core'

kelvinToRGB(5778)
// { r: 1.0, g: 0.97, b: 0.92, hex: '#fff7eb' } — Soleil

kelvinToThreeColor(3500)
// { r: 1.0, g: 0.65, b: 0.31 } — naine M, prêt pour new THREE.Color(r, g, b)

kelvinLabel(5778)
// 'Étoile G comme notre Soleil (~5778K)'

Quand utiliser quoi

  • Vous avez un spectralType connuSPECTRAL_TABLE[type].color (CSS hex pré-calculé, pas de calcul).
  • Vous avez une température arbitraire (e.g. kelvinToRGB(4200) pour une étoile sub-K simulée) → helpers Kelvin.
  • Vous voulez l'étiquette UIkelvinLabel (déjà en français).

Helpers visuels

buildStarPalette

ts
import { buildStarPalette } from '@cedric-pouilleux/stellexjs/core'

const palette = buildStarPalette('M')
// TerrainLevel[] : surface → corona en gradient pour la classe M

Palette terrain pour le shader étoile — surface → bord/corona. Consommée automatiquement par useBody ; vous l'invoquez directement uniquement pour des previews ou des shaders custom.

godRaysFromStar

Calibre les paramètres god rays (exposure, decay, density, weight) à partir d'un StarPhysicsInput — voir le détail dans le guide API avancée. Couplé à GodRaysShader (post-processing pass), ça produit un effet calibré par classe spectrale sans tuning manuel.

ts
import { godRaysFromStar } from '@cedric-pouilleux/stellexjs/core'

const params = godRaysFromStar({ spectralType: 'O' })
// exposure / decay / density / weight calibrés pour une géante O

Override radius / tempK

StarConfig expose les mêmes leviers que BodyPhysicsCore (radius, rotationSpeed, axialTilt, mass?, coreRadiusRatio?). Les seuls champs étoile-spécifiques sont spectralType (requis) et l'override implicite tempK qui passe par resolveStarData quand vous voulez une valeur non-canonique :

ts
// Étoile G "personnalisée" — un peu plus froide et plus grosse que le Soleil
useBody({
  type:         'star',
  spectralType: 'G',
  name:         'Helios-Beta',
  radius:        4.2,        // override visuel (par défaut 3 pour G)
  rotationSpeed: 0.005,
  axialTilt:     0,
}, DEFAULT_TILE_SIZE)

Pour overrider tempK (qui vit hors de BodyConfig puisque c'est une dérivation), passez par resolveStarData directement quand vous calculez un état de jeu :

ts
const data = resolveStarData({ spectralType: 'G', tempK: 5500 })
// luminosity recalculée pour 5500 K (≠ valeur canonique G de 5778 K)

Pas de view, pas de liquid, pas d'atmoShell

C'est le plus gros piège — TS rejette directement ces accès sur StarBody :

ts
const star = useBody(starConfig, DEFAULT_TILE_SIZE)

star.view.set('surface')        // ❌ TS error : 'view' does not exist on StarBody
star.liquid.setSeaLevel(1.0)    // ❌
star.atmoShell?.tick(dt)        // ❌
star.tiles.sol.tileGeometry(0)  // ❌ : pas de namespace .sol sur StarTiles

// ✅ Avec narrowing
if (star.kind === 'star') {
  // tiles plat sur StarBody
  star.tiles.tileGeometry(0)
  star.tiles.tileBaseVisual(0)
  star.tiles.writeTileColor(0, { r: 1, g: 0, b: 0 })
}

Si tu veux factoriser du code agnostique, type-le contre BodyBase et reste sur les primitives communes (group, tick, dispose, interactive, hover, getCoreRadius, getSurfaceRadius, …).

Voir aussi

Distribué sous la licence indiquée dans le dépôt.