feat: rebuild the nightdrive road and terrain
This commit is contained in:
173
src/scene/world/palette.ts
Normal file
173
src/scene/world/palette.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
import * as THREE from 'three';
|
||||
import type { EnvironmentChapter } from '@/journey/types';
|
||||
|
||||
export interface ChapterPaletteDefinition {
|
||||
sky: number;
|
||||
fog: number;
|
||||
terrainLow: number;
|
||||
terrainHigh: number;
|
||||
sun: number;
|
||||
haze: number;
|
||||
warmth: number;
|
||||
terrainEnergy: number;
|
||||
starVisibility: number;
|
||||
streakEnergy: number;
|
||||
}
|
||||
|
||||
export interface MutableChapterPalette {
|
||||
sky: MutableColor;
|
||||
fog: MutableColor;
|
||||
terrainLow: MutableColor;
|
||||
terrainHigh: MutableColor;
|
||||
sun: MutableColor;
|
||||
haze: MutableColor;
|
||||
warmth: number;
|
||||
terrainEnergy: number;
|
||||
starVisibility: number;
|
||||
streakEnergy: number;
|
||||
}
|
||||
|
||||
export interface MutableColor {
|
||||
clone(): MutableColor;
|
||||
getHex(): number;
|
||||
lerpColors(from: MutableColor, to: MutableColor, progress: number): MutableColor;
|
||||
setHex(value: number): MutableColor;
|
||||
}
|
||||
|
||||
export const CHAPTER_PALETTES: Readonly<Record<EnvironmentChapter, ChapterPaletteDefinition>> = {
|
||||
'deep-night': {
|
||||
sky: 0x040713,
|
||||
fog: 0x07101c,
|
||||
terrainLow: 0x126a7c,
|
||||
terrainHigh: 0xa53a74,
|
||||
sun: 0xc7437e,
|
||||
haze: 0x65225f,
|
||||
warmth: 0.12,
|
||||
terrainEnergy: 0.78,
|
||||
starVisibility: 1,
|
||||
streakEnergy: 0.72,
|
||||
},
|
||||
systems: {
|
||||
sky: 0x050918,
|
||||
fog: 0x081622,
|
||||
terrainLow: 0x168aa0,
|
||||
terrainHigh: 0xa83f79,
|
||||
sun: 0xd05282,
|
||||
haze: 0x6d2968,
|
||||
warmth: 0.22,
|
||||
terrainEnergy: 0.9,
|
||||
starVisibility: 0.94,
|
||||
streakEnergy: 0.86,
|
||||
},
|
||||
infrastructure: {
|
||||
sky: 0x060a1b,
|
||||
fog: 0x091a2a,
|
||||
terrainLow: 0x197f98,
|
||||
terrainHigh: 0xa13d7a,
|
||||
sun: 0xd45b82,
|
||||
haze: 0x6f2d70,
|
||||
warmth: 0.3,
|
||||
terrainEnergy: 0.88,
|
||||
starVisibility: 0.86,
|
||||
streakEnergy: 0.82,
|
||||
},
|
||||
builds: {
|
||||
sky: 0x0b0d22,
|
||||
fog: 0x111d2d,
|
||||
terrainLow: 0x1a8ba0,
|
||||
terrainHigh: 0xb04479,
|
||||
sun: 0xe16d7a,
|
||||
haze: 0x7f356c,
|
||||
warmth: 0.46,
|
||||
terrainEnergy: 1,
|
||||
starVisibility: 0.72,
|
||||
streakEnergy: 1,
|
||||
},
|
||||
'pre-dawn': {
|
||||
sky: 0x15142a,
|
||||
fog: 0x1c2433,
|
||||
terrainLow: 0x277f91,
|
||||
terrainHigh: 0x9c4b78,
|
||||
sun: 0xf09667,
|
||||
haze: 0xa45468,
|
||||
warmth: 0.76,
|
||||
terrainEnergy: 0.72,
|
||||
starVisibility: 0.38,
|
||||
streakEnergy: 0.52,
|
||||
},
|
||||
destination: {
|
||||
sky: 0x241b31,
|
||||
fog: 0x2b2b38,
|
||||
terrainLow: 0x386f79,
|
||||
terrainHigh: 0x87506e,
|
||||
sun: 0xf4b06d,
|
||||
haze: 0xbb6b65,
|
||||
warmth: 1,
|
||||
terrainEnergy: 0.54,
|
||||
starVisibility: 0.16,
|
||||
streakEnergy: 0.18,
|
||||
},
|
||||
};
|
||||
|
||||
const paletteColors = Object.fromEntries(
|
||||
Object.entries(CHAPTER_PALETTES).map(([chapter, palette]) => [chapter, {
|
||||
sky: new THREE.Color(palette.sky),
|
||||
fog: new THREE.Color(palette.fog),
|
||||
terrainLow: new THREE.Color(palette.terrainLow),
|
||||
terrainHigh: new THREE.Color(palette.terrainHigh),
|
||||
sun: new THREE.Color(palette.sun),
|
||||
haze: new THREE.Color(palette.haze),
|
||||
}]),
|
||||
) as Readonly<Record<EnvironmentChapter, Pick<MutableChapterPalette,
|
||||
'sky' | 'fog' | 'terrainLow' | 'terrainHigh' | 'sun' | 'haze'>>>;
|
||||
|
||||
export function createMutableChapterPalette(
|
||||
chapter: EnvironmentChapter = 'deep-night',
|
||||
): MutableChapterPalette {
|
||||
const source = CHAPTER_PALETTES[chapter];
|
||||
const colors = paletteColors[chapter];
|
||||
return {
|
||||
sky: colors.sky.clone(),
|
||||
fog: colors.fog.clone(),
|
||||
terrainLow: colors.terrainLow.clone(),
|
||||
terrainHigh: colors.terrainHigh.clone(),
|
||||
sun: colors.sun.clone(),
|
||||
haze: colors.haze.clone(),
|
||||
warmth: source.warmth,
|
||||
terrainEnergy: source.terrainEnergy,
|
||||
starVisibility: source.starVisibility,
|
||||
streakEnergy: source.streakEnergy,
|
||||
};
|
||||
}
|
||||
|
||||
export function writeChapterPalette(
|
||||
target: MutableChapterPalette,
|
||||
from: EnvironmentChapter,
|
||||
to: EnvironmentChapter,
|
||||
progress: number,
|
||||
): MutableChapterPalette {
|
||||
const start = CHAPTER_PALETTES[from];
|
||||
const end = CHAPTER_PALETTES[to];
|
||||
const startColors = paletteColors[from];
|
||||
const endColors = paletteColors[to];
|
||||
const mix = clamp01(progress);
|
||||
target.sky.lerpColors(startColors.sky, endColors.sky, mix);
|
||||
target.fog.lerpColors(startColors.fog, endColors.fog, mix);
|
||||
target.terrainLow.lerpColors(startColors.terrainLow, endColors.terrainLow, mix);
|
||||
target.terrainHigh.lerpColors(startColors.terrainHigh, endColors.terrainHigh, mix);
|
||||
target.sun.lerpColors(startColors.sun, endColors.sun, mix);
|
||||
target.haze.lerpColors(startColors.haze, endColors.haze, mix);
|
||||
target.warmth = lerp(start.warmth, end.warmth, mix);
|
||||
target.terrainEnergy = lerp(start.terrainEnergy, end.terrainEnergy, mix);
|
||||
target.starVisibility = lerp(start.starVisibility, end.starVisibility, mix);
|
||||
target.streakEnergy = lerp(start.streakEnergy, end.streakEnergy, mix);
|
||||
return target;
|
||||
}
|
||||
|
||||
function lerp(from: number, to: number, progress: number): number {
|
||||
return from + (to - from) * progress;
|
||||
}
|
||||
|
||||
function clamp01(value: number): number {
|
||||
return Number.isFinite(value) ? THREE.MathUtils.clamp(value, 0, 1) : 0;
|
||||
}
|
||||
Reference in New Issue
Block a user