tower / files / src / views / stars.ts
stars.ts
| 1 | /** |
| 2 | * The real star catalogue as a texture, shared by every shader that draws the sky |
| 3 | * (STAR_GLSL). See celestial.ts for the bake and D-075 for why. |
| 4 | * |
| 5 | * The catalogue is a separate chunk, fetched the first time a 3D view asks: the map |
| 6 | * never needs it. The texture exists from the start at its full size and empty, so |
| 7 | * shaders compile against it at once and the stars simply appear when it is filled. |
| 8 | */ |
| 9 | import { DataTexture, FloatType, Matrix3, NearestFilter, RGBAFormat } from 'three' |
| 10 | import { STAR_FACE_SIZE, bakeStars, skyFrame } from '../world/celestial.js' |
| 11 | |
| 12 | let texture: DataTexture | null = null |
| 13 | |
| 14 | export function starTexture(): DataTexture { |
| 15 | if (texture) return texture |
| 16 | const S = STAR_FACE_SIZE |
| 17 | const t = texture = new DataTexture(new Float32Array(S * S * 6 * 4), S, S * 6, RGBAFormat, FloatType) |
| 18 | // Read with texelFetch, one cell at a time: nothing is ever filtered or mipmapped. |
| 19 | t.minFilter = t.magFilter = NearestFilter |
| 20 | t.generateMipmaps = false |
| 21 | t.needsUpdate = true |
| 22 | void import('../data/bright-stars.json').then(({ default: catalog }) => { |
| 23 | ;(t.image.data as Float32Array).set(bakeStars(catalog.stars)) |
| 24 | t.needsUpdate = true |
| 25 | }) |
| 26 | return t |
| 27 | } |
| 28 | |
| 29 | /** `skyFrame` as the Matrix3 the shaders take, written into `into`. */ |
| 30 | export function skyMatrix(at: number, into: Matrix3): Matrix3 { |
| 31 | const m = skyFrame(new Date(at)) |
| 32 | return into.set(m[0]!, m[1]!, m[2]!, m[3]!, m[4]!, m[5]!, m[6]!, m[7]!, m[8]!) |
| 33 | } |