Files
Portfolio/tests/unit/expressway-lamps.test.ts

36 lines
1.7 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { SceneResourceBag } from '@/scene/resources';
import { renderQualityFor } from '@/scene/render-quality';
import { createExpressway, PYLON_CORE_GAIN, PYLON_HALO_GAIN } from '@/scene/world/expressway';
interface Node {
name: string;
count?: number;
material?: { blending: number; fragmentShader?: string };
}
const children = (group: unknown) => (group as { children: Node[] }).children;
const luminance = ([r, g, b]: readonly number[]) => 0.2126 * r! + 0.7152 * g! + 0.0722 * b!;
const CYAN = [0.02, 0.78, 0.93] as const;
const MAGENTA = [1.0, 0.025, 0.34] as const;
describe('expressway pylon lamps', () => {
it('draws a two-layer lamp: a core and a soft additive halo for every pylon strip', () => {
const world = createExpressway(new SceneResourceBag(), renderQualityFor('high', 1, false));
const core = children(world.group).find((child) => child.name === 'recessed-pylon-lights')!;
const halo = children(world.group).find((child) => child.name === 'pylon-light-halos')!;
expect(halo.count).toBe(core.count);
expect(halo.material!.blending).toBe(core.material!.blending);
expect(halo.material!.fragmentShader).toContain('across');
});
it('keeps the core under the bloom threshold at full drive energy, so the hue survives the tone curve', () => {
// Core: hue * (1.3 + energy 0.5) * gain; core + halo peak stays under 0.85 luminance too.
for (const hue of [CYAN, MAGENTA]) {
const peak = 1.8 * PYLON_CORE_GAIN;
expect(luminance(hue.map((v) => v * peak))).toBeLessThan(0.85);
expect(luminance(hue.map((v) => v * 1.8 * (PYLON_CORE_GAIN + PYLON_HALO_GAIN)))).toBeLessThan(1.2);
}
expect(PYLON_HALO_GAIN).toBeLessThan(PYLON_CORE_GAIN);
});
});