packages/core/src/features/textures/lib/palette.ts
This is the source snapshot used to build these API details. View this revision on GitHub.
1 import type { ProceduralTextureProps } from './procedural-texture.js';
2 import type { ReactionDiffusionProps } from './reaction-diffusion.js';
3 /**
4 * Ordered colors forming a texture's presentation ramp.
5 *
6 * @see {@link texturePalettes}
7 * @see {@link ProceduralTextureProps}
8 * @see {@link ReactionDiffusionProps}
9 */
10 export type TexturePalette = readonly string[];
11 /**
12 * Built-in immutable color ramps for procedural texture presentation.
13 *
14 * @see {@link TexturePalette}
15 */
16 export const texturePalettes = Object.freeze({
17 /** Dark blue through teal to pale yellow. See {@link texturePalettes}. */
18 lagoon: Object.freeze(["#081e2c", "#125568", "#50b8ad", "#e5efb3"]),
19 /** Warm ivory through lavender to deep blue. See {@link texturePalettes}. */
20 porcelain: Object.freeze(["#f2e7d4", "#b7a9c0", "#536194", "#172955"]),
21 /** Dark violet through coral to pale yellow. See {@link texturePalettes}. */
22 ember: Object.freeze(["#241526", "#893955", "#e88470", "#ffe3aa"]),
23 });
24
25 export function paletteLut(palette: TexturePalette): Uint8ClampedArray {
26 if (palette.length < 2 || palette.length > 16)
27 throw new RangeError("Texture palette requires 2–16 #RRGGBB colors.");
28 const colors = palette.map((color) => {
29 if (!/^#[0-9a-f]{6}$/i.test(color))
30 throw new TypeError("Texture palette colors must use #RRGGBB.");
31 return [
32 parseInt(color.slice(1, 3), 16),
33 parseInt(color.slice(3, 5), 16),
34 parseInt(color.slice(5, 7), 16),
35 ];
36 });
37 const lut = new Uint8ClampedArray(256 * 4);
38 for (let i = 0; i < 256; i++) {
39 const position = (i / 255) * (colors.length - 1);
40 const lo = Math.min(colors.length - 2, Math.floor(position)),
41 mix = position - lo;
42 for (let c = 0; c < 3; c++)
43 lut[i * 4 + c] = colors[lo][c] * (1 - mix) + colors[lo + 1][c] * mix;
44 lut[i * 4 + 3] = 255;
45 }
46 return lut;
47 }
48
49 /**
50 * The width and height of a texture's raster grid.
51 *
52 * @see {@link TexturePalette}
53 * @see {@link ReactionDiffusionProps}
54 * @see {@link ProceduralTextureProps}
55 */
56 export interface TextureResolution {
57 /**
58 * Horizontal extent in the units of the containing geometry or surface. See
59 * {@link TextureResolution}.
60 */
61 readonly width: number;
62 /**
63 * Vertical extent in the units of the containing geometry or surface. See
64 * {@link TextureResolution}.
65 */
66 readonly height: number;
67 }
68 export function validateResolution(
69 value: TextureResolution = { width: 256, height: 160 },
70 ): TextureResolution {
71 if (
72 ![value.width, value.height].every(
73 (n) => Number.isInteger(n) && n >= 8 && n <= 1024,
74 ) ||
75 value.width * value.height > 262144
76 ) {
77 throw new RangeError(
78 "Texture resolution must contain integer dimensions from 8 to 1024 and at most 262144 cells.",
79 );
80 }
81 return { width: value.width, height: value.height };
82 }
83 export function validateSeed(seed = 42): number {
84 if (!Number.isInteger(seed) || seed < 0 || seed > 0xffffffff)
85 throw new RangeError("Texture seed must be an unsigned 32-bit integer.");
86 return seed;
87 }
88
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.