Skip to content

Commit 07d8247

Browse files
committed
Experiment with noise
1 parent 978cea9 commit 07d8247

File tree

4 files changed

+82
-66
lines changed

4 files changed

+82
-66
lines changed
Lines changed: 11 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,7 @@
11
/** @format */
22

33
import type { Tile } from "@derivean/chunk";
4-
import { HSLA, hslaToRgba, type Color } from "@derivean/utils";
5-
6-
/**
7-
* Color definitions for different land types
8-
* Using HSLA as it's easier to make color transitions
9-
*/
10-
const COLOR_MAP = {
11-
mountain: HSLA([0, 0, 35, 1]), // Gray mountains
12-
platau: HSLA([30, 60, 70, 1]), // Brownish plateaus
13-
valley: HSLA([115, 50, 32, 1]), // Dark green valleys
14-
hill: HSLA([85, 65, 50, 1]), // Lighter green hills
15-
plain: HSLA([60, 70, 75, 1]), // Yellowish plains
16-
};
4+
import { HSLA, hslaToRgba, mapNoiseToColor, type Color } from "@derivean/utils";
175

186
export namespace withColorMap {
197
export interface Props {
@@ -22,61 +10,18 @@ export namespace withColorMap {
2210
}
2311

2412
/**
25-
* Maps noise values to HSLA/RGBA colors based on the strength of each land type
26-
* Blends colors based on the relative strength of each land type
13+
* Maps a noise value to an RGBA color based on the provided color map
14+
* Currently uses heightmap as the primary source for color mapping
2715
*/
2816
export const withColorMap = ({ tile }: withColorMap.Props): Color.RGBA => {
29-
// Extract land properties
30-
const { mountain, platau, valley, hill, plain } = tile.land;
31-
32-
// Map each noise value to a normalized weight (0 to 1)
33-
// First, convert from -1,1 range to 0,1 range
34-
const mountainWeight = (mountain + 1) / 2;
35-
const platauWeight = (platau + 1) / 2;
36-
const valleyWeight = (valley + 1) / 2;
37-
const hillWeight = (hill + 1) / 2;
38-
const plainWeight = (plain + 1) / 2;
39-
40-
// Calculate total weight to normalize
41-
const totalWeight = mountainWeight + platauWeight + valleyWeight + hillWeight + plainWeight;
42-
43-
// Guard against division by zero
44-
if (totalWeight === 0) {
45-
return hslaToRgba(HSLA([0, 0, 50, 1])); // Default gray if all weights are zero
46-
}
47-
48-
// Initialize color components for weighted average
49-
let h = 0;
50-
let s = 0;
51-
let l = 0;
52-
53-
// Add weighted contribution from each land type
54-
h += COLOR_MAP.mountain.color[0] * mountainWeight;
55-
h += COLOR_MAP.platau.color[0] * platauWeight;
56-
h += COLOR_MAP.valley.color[0] * valleyWeight;
57-
h += COLOR_MAP.hill.color[0] * hillWeight;
58-
h += COLOR_MAP.plain.color[0] * plainWeight;
59-
60-
s += COLOR_MAP.mountain.color[1] * mountainWeight;
61-
s += COLOR_MAP.platau.color[1] * platauWeight;
62-
s += COLOR_MAP.valley.color[1] * valleyWeight;
63-
s += COLOR_MAP.hill.color[1] * hillWeight;
64-
s += COLOR_MAP.plain.color[1] * plainWeight;
65-
66-
l += COLOR_MAP.mountain.color[2] * mountainWeight;
67-
l += COLOR_MAP.platau.color[2] * platauWeight;
68-
l += COLOR_MAP.valley.color[2] * valleyWeight;
69-
l += COLOR_MAP.hill.color[2] * hillWeight;
70-
l += COLOR_MAP.plain.color[2] * plainWeight;
71-
72-
// Normalize by dividing by total weight
73-
h /= totalWeight;
74-
s /= totalWeight;
75-
l /= totalWeight;
17+
const color = HSLA([0, 0, 0, 1]);
7618

77-
// Create the final blended HSLA color
78-
const blendedColor = HSLA([h, s, l, 1]);
19+
return hslaToRgba(
20+
mapNoiseToColor(tile.biome.deep_ocean, {
21+
min: HSLA([220, 100, 30, 1]),
22+
max: HSLA([200, 80, 60, 1]),
23+
}),
24+
);
7925

80-
// Convert to RGBA and return
81-
return hslaToRgba(blendedColor);
26+
// return hslaToRgba(color);
8227
};

packages/@derivean/utils/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export { TagSchema } from "./schema/tag/TagSchema";
4646
export { UserSchema } from "./schema/UserSchema";
4747
export { type UserType } from "./type/UserType";
4848
export { type XZ } from "./type/XZ";
49+
export { mapNoiseToColor } from "./utils/mapNoiseToColor";
50+
export { noiseToGrayscale } from "./utils/noiseToGrayscale";
4951
export { smoothstep } from "./utils/smoothstep";
5052
export { toWebp64 } from "./utils/toWebp64";
5153
export { withUse } from "./utils/withUse";
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/** @format */
2+
3+
import { HSLA, type Color } from "@derivean/utils";
4+
5+
/**
6+
* Maps a noise value (-1 to 1) to an HSLA color within the specified range
7+
*
8+
* @param noise The input noise value, should be between -1 and 1
9+
* @param colorRange An object containing min and max HSLA colors
10+
* @returns An HSLA color interpolated based on the noise value
11+
*/
12+
export interface ColorRange {
13+
min: Color.HSLA;
14+
max: Color.HSLA;
15+
}
16+
17+
export function mapNoiseToColor(noise: number, colorRange: ColorRange): Color.HSLA {
18+
// Ensure the noise value is clamped between -1 and 1
19+
const clampedNoise = Math.max(-1, Math.min(1, noise));
20+
21+
// Convert noise from [-1, 1] to [0, 1] for interpolation
22+
const t = (clampedNoise + 1) / 2;
23+
24+
// Extract color components
25+
const [minH, minS, minL, minA] = colorRange.min.color;
26+
const [maxH, maxS, maxL, maxA] = colorRange.max.color;
27+
28+
// Handle hue interpolation specially (since it's circular)
29+
let hueDiff = maxH - minH;
30+
31+
// Take the shortest path around the color wheel
32+
if (Math.abs(hueDiff) > 180) {
33+
if (hueDiff > 0) {
34+
hueDiff -= 360;
35+
} else {
36+
hueDiff += 360;
37+
}
38+
}
39+
40+
const h = (minH + hueDiff * t + 360) % 360;
41+
const s = minS + (maxS - minS) * t;
42+
const l = minL + (maxL - minL) * t;
43+
const a = minA + (maxA - minA) * t;
44+
45+
return HSLA([h, s, l, a]);
46+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/** @format */
2+
3+
import { RGBA, type Color } from "../color/Color";
4+
5+
/**
6+
* Converts a noise value (-1 to 1) to a grayscale RGBA color
7+
*
8+
* @param noise Noise value from -1 to 1
9+
* @returns RGBA color with full opacity (alpha = 255)
10+
*/
11+
export function noiseToGrayscale(noise: number): Color.RGBA {
12+
// Clamp the noise value to ensure it's within -1 to 1
13+
const clampedNoise = Math.max(-1, Math.min(1, noise));
14+
15+
// Map the noise from [-1, 1] to [0, 1]
16+
const normalizedNoise = (clampedNoise + 1) / 2;
17+
18+
// Map the normalized noise to 0-255 range
19+
const colorValue = Math.round(normalizedNoise * 255);
20+
21+
// Return grayscale RGBA (all RGB channels have the same value)
22+
return RGBA([colorValue, colorValue, colorValue, 255]);
23+
}

0 commit comments

Comments
 (0)