From adb098e2eb1be3cf8c9ea6972fbd06cab89e0611 Mon Sep 17 00:00:00 2001 From: como Date: Wed, 25 Mar 2026 17:46:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=B0=B4=E9=9D=A2=E4=B8=8B?= =?UTF-8?q?=E5=B2=B8=E4=B8=8D=E6=AD=A3=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/OceanScene.js | 2 +- src/TerrainGenerator.js | 48 ++++++++++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/OceanScene.js b/src/OceanScene.js index 54b3fcb..8382aca 100644 --- a/src/OceanScene.js +++ b/src/OceanScene.js @@ -146,7 +146,7 @@ export class OceanScene { }); this.water.rotation.x = -Math.PI / 2; - this.water.position.y = 0; + this.water.position.y = -0.15; this.scene.add(this.water); } diff --git a/src/TerrainGenerator.js b/src/TerrainGenerator.js index e59bc2f..b77288c 100644 --- a/src/TerrainGenerator.js +++ b/src/TerrainGenerator.js @@ -8,6 +8,8 @@ export class TerrainGenerator { this.maxHeight = options.maxHeight || 50; this.waterLevel = options.waterLevel || 0; this.beachWidth = options.beachWidth || 20; + this.shoreWidth = options.shoreWidth || 3.5; + this.shoreDepth = options.shoreDepth || 1.5; this.noise = new SimplexNoise(options.seed || 42); this.terrain = null; @@ -64,21 +66,33 @@ export class TerrainGenerator { const distFromCenter = Math.sqrt(x * x + y * y); const maxLandDist = this.size * 0.45; - const falloffStart = this.size * 0.25; + const falloffStart = this.size * 0.2; let continentMask = 1.0; + let edgeDepth = 0; if (distFromCenter > falloffStart) { const t = (distFromCenter - falloffStart) / (maxLandDist - falloffStart); - continentMask = Math.max(0, 1 - Math.pow(t, 1.5)); + continentMask = Math.max(0, 1 - Math.pow(t, 1.2)); + edgeDepth = -15 * Math.pow(Math.max(0, t), 2); } - height = height * continentMask; - height = height * this.maxHeight * 0.4; + height = height * continentMask + edgeDepth; + height = height * this.maxHeight * 0.5; - const beachZone = 2; - if (height > this.waterLevel && height < this.waterLevel + beachZone) { - const blend = Math.max(0, Math.min(1, (height - this.waterLevel) / beachZone)); - height = this.waterLevel + Math.pow(blend, 0.5) * beachZone; + const shoreMin = this.waterLevel - this.shoreWidth; + const shoreMax = this.waterLevel + this.shoreWidth; + if (height > shoreMin && height < shoreMax) { + if (height < this.waterLevel) { + const t = (height - shoreMin) / (this.waterLevel - shoreMin); + height = this.waterLevel - this.shoreDepth * Math.pow(1 - t, 1.35); + } else { + const t = (height - this.waterLevel) / (shoreMax - this.waterLevel); + height = this.waterLevel + Math.pow(t, 0.75) * this.shoreWidth; + } + } + + if (Math.abs(height - this.waterLevel) < 0.06) { + height = this.waterLevel - 0.06; } return height; @@ -97,18 +111,18 @@ export class TerrainGenerator { let color = new THREE.Color(); - if (normalizedHeight < -0.1) { + if (height < this.waterLevel - 1.5) { color.copy(deepWater); - } else if (normalizedHeight < 0) { - color.lerpColors(deepWater, shallowWater, (normalizedHeight + 0.1) / 0.1); - } else if (normalizedHeight < 0.05) { - const beachBlend = Math.min(1, normalizedHeight / 0.05); - color.lerpColors(shallowWater, beach, beachBlend); - } else if (normalizedHeight < 0.15) { - const sandToGrass = (normalizedHeight - 0.05) / 0.1; + } else if (height < this.waterLevel) { + const shallowBlend = (height - (this.waterLevel - 1.5)) / 1.5; + color.lerpColors(deepWater, shallowWater, THREE.MathUtils.clamp(shallowBlend, 0, 1)); + } else if (normalizedHeight < 0.08) { + color.copy(beach); + } else if (normalizedHeight < 0.18) { + const sandToGrass = (normalizedHeight - 0.08) / 0.1; color.lerpColors(beach, grass, sandToGrass); } else if (normalizedHeight < 0.4) { - const grassBlend = (normalizedHeight - 0.15) / 0.25; + const grassBlend = (normalizedHeight - 0.18) / 0.22; color.lerpColors(grass, darkGrass, grassBlend); } else if (normalizedHeight < 0.6) { const rockBlend = (normalizedHeight - 0.4) / 0.2;