not bad
This commit is contained in:
parent
27ceb6568a
commit
4a8aff90b2
7 changed files with 3806 additions and 83 deletions
55
renderer.js
55
renderer.js
|
|
@ -1,4 +1,4 @@
|
|||
import { CELL_SIZE, MAP_H, MAP_W, clamp } from "./mapUtils.js";
|
||||
import { CELL_SIZE, MAP_H, MAP_W, clamp, valueNoise } from "./mapUtils.js";
|
||||
|
||||
|
||||
const segmentVectorCache = new WeakMap();
|
||||
|
|
@ -296,6 +296,38 @@ function isWaterSample(map, fx, fy) {
|
|||
return seaCoverageSample(map, fx, fy) >= 0.50;
|
||||
}
|
||||
|
||||
function terrainWorldPoint(map, fx, fy) {
|
||||
return {
|
||||
x: fx + (map?.worldCamera?.x || 0),
|
||||
y: fy + (map?.worldCamera?.y || 0),
|
||||
};
|
||||
}
|
||||
|
||||
function waterVisualTone(map, fx, fy) {
|
||||
const p = terrainWorldPoint(map, fx, fy);
|
||||
const seed = (map?.seed || 0) >>> 0;
|
||||
const broad = valueNoise(p.x, p.y, seed ^ 0x5d2a9b31, 74);
|
||||
const mid = valueNoise(p.x, p.y, seed ^ 0x8f4c2d19, 29);
|
||||
return clamp(broad * 0.72 + mid * 0.28);
|
||||
}
|
||||
|
||||
function waterVisualColor(map, fx, fy, waterCoverage = null) {
|
||||
const coverage = waterCoverage ?? seaCoverageSample(map, fx, fy);
|
||||
const tone = waterVisualTone(map, fx, fy) - 0.5;
|
||||
const offshore = clamp((coverage - 0.42) / 0.58);
|
||||
const depth = clamp(0.48 + offshore * 0.22 + tone * 0.10);
|
||||
return [
|
||||
Math.round(174 - depth * 6),
|
||||
Math.round(203 + depth * 2),
|
||||
Math.round(224 + depth * 4),
|
||||
];
|
||||
}
|
||||
|
||||
function waterVisualShade(map, fx, fy) {
|
||||
const tone = waterVisualTone(map, fx * 0.85 + 11.7, fy * 0.85 - 3.1) - 0.5;
|
||||
return clamp(0.992 + tone * 0.018, 0.976, 1.012);
|
||||
}
|
||||
|
||||
function mixRgb(a, b, t) {
|
||||
return [
|
||||
Math.round(a[0] + (b[0] - a[0]) * t),
|
||||
|
|
@ -363,8 +395,10 @@ function terrainColorContinuous(map, fx, fy, mode) {
|
|||
let color;
|
||||
|
||||
const waterCoverage = seaCoverageSample(map, fx, fy);
|
||||
const depth = clamp(((map.seaLevel ?? 0.285) + 0.065 - fieldSample(map, map.elevation, fx, fy)) * 2.4);
|
||||
const waterColor = [Math.round(174 - depth * 7), Math.round(203 + depth * 2), Math.round(224 + depth * 5)];
|
||||
// Water must not inherit terrain DEM hill bands. Use a stable world-coordinate
|
||||
// visual water tone instead of elevation-derived depth; otherwise patched sea
|
||||
// areas expose rectangular/horizontal generation artefacts.
|
||||
const waterColor = waterVisualColor(map, fx, fy, waterCoverage);
|
||||
|
||||
let landColor;
|
||||
if (mode === "development") {
|
||||
|
|
@ -405,6 +439,9 @@ function terrainColorContinuous(map, fx, fy, mode) {
|
|||
}
|
||||
|
||||
function terrainShadeContinuous(map, fx, fy) {
|
||||
const waterCoverage = seaCoverageSample(map, fx, fy);
|
||||
if (waterCoverage >= 0.50) return waterVisualShade(map, fx, fy);
|
||||
|
||||
const step = 0.50;
|
||||
const eC = fieldSample(map, map.elevation, fx, fy);
|
||||
const eL = fieldSample(map, map.elevation, fx - step, fy);
|
||||
|
|
@ -589,6 +626,14 @@ function getRasterBorderSegments(map, fieldName) {
|
|||
return segments;
|
||||
}
|
||||
|
||||
function getDisplayBorderSegments(map, fieldName, precomputedSegments, mode) {
|
||||
// Raw raster borders expose every one-cell ID fragment and also reveal patch
|
||||
// ownership seams as long rectangular prefecture/municipality lines. Keep
|
||||
// that extractor debug-only; normal modes must use prepared vector layers.
|
||||
if (mode === "borders-debug") return getRasterBorderSegments(map, fieldName);
|
||||
return Array.isArray(precomputedSegments) ? precomputedSegments : [];
|
||||
}
|
||||
|
||||
function drawRiverPath(ctx, map, path, color, widthFn, alpha = 1) {
|
||||
if (!path || path.length < 2) return;
|
||||
ctx.save();
|
||||
|
|
@ -1067,8 +1112,8 @@ export function drawMap(canvas, map, options) {
|
|||
const showPrefectureRegions = ["all", "admin", "borders-debug"].includes(mode);
|
||||
if (showPrefectureRegions) drawPrefectureRegionFill(ctx, map, mode);
|
||||
|
||||
const adminBorderSegments = map.adminId ? getRasterBorderSegments(map, "adminId") : map.adminBorders;
|
||||
const prefectureBorderSegments = map.prefectureRegionId ? getRasterBorderSegments(map, "prefectureRegionId") : map.regionalPrefectureBorders;
|
||||
const adminBorderSegments = getDisplayBorderSegments(map, "adminId", map.adminBorders, mode);
|
||||
const prefectureBorderSegments = getDisplayBorderSegments(map, "prefectureRegionId", map.regionalPrefectureBorders, mode);
|
||||
if (showAdmin && adminBorderSegments?.length) {
|
||||
drawVectorSegments(ctx, adminBorderSegments, "rgba(255, 255, 255, 0.8)", 2.8, false, { iterations: 1, tolerance: 0.05, offsetX: -0.5, offsetY: -0.5 });
|
||||
drawVectorSegments(ctx, adminBorderSegments, "rgba(150, 140, 150, 0.9)", 1.2, true, { iterations: 1, tolerance: 0.05, offsetX: -0.5, offsetY: -0.5 });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue