扩大陆地面积

This commit is contained in:
2026-03-26 10:17:20 +08:00
parent d751437fca
commit dc417a1f1a
2 changed files with 57 additions and 10 deletions

View File

@@ -280,11 +280,20 @@ export class OceanScene {
async initTerrain() { async initTerrain() {
const terrainGen = new TerrainGenerator({ const terrainGen = new TerrainGenerator({
size: 1200, size: 1200, // 地形平面尺寸
segments: 200, segments: 200, // 网格细分数,越高细节越多
maxHeight: 30, maxHeight: 34, // 海面以上地形的最大起伏高度
waterLevel: 0, waterLevel: 0, // 海平面基准高度
seed: 42 underwaterDepthBias: 4.5, // 整体压低海面以下地形,避免浅滩露出
landBias: 0.2, // 整体抬升陆地倾向,增大陆地露出面积
falloffStartRatio: 0.22, // 从中心向外开始下沉的起始比例
maxLandRatio: 0.46, // 大陆海岸线的大致外缘比例
edgeDepth: 12, // 海岸外侧向海底下沉的强度
coreRadiusRatio: 0.24, // 大陆核心高地区域半径比例
continentLift: 0.55, // 核心大陆的额外抬升强度
coastVariance: 0.05, // 海岸线形状起伏幅度,越大越不规则
outerShelfDepth: 4, // 大陆外侧陆架的额外下沉深度
seed: 42 // 固定随机种子,保证地形稳定复现
}); });
this.terrain = terrainGen.generate(); this.terrain = terrainGen.generate();

View File

@@ -10,6 +10,15 @@ export class TerrainGenerator {
this.beachWidth = options.beachWidth || 20; this.beachWidth = options.beachWidth || 20;
this.shoreWidth = options.shoreWidth || 3.5; this.shoreWidth = options.shoreWidth || 3.5;
this.shoreDepth = options.shoreDepth || 1.5; this.shoreDepth = options.shoreDepth || 1.5;
this.underwaterDepthBias = options.underwaterDepthBias || 3.5;
this.landBias = options.landBias ?? 0.18;
this.falloffStartRatio = options.falloffStartRatio || 0.24;
this.maxLandRatio = options.maxLandRatio || 0.48;
this.edgeDepth = options.edgeDepth || 10;
this.coreRadiusRatio = options.coreRadiusRatio || 0.2;
this.continentLift = options.continentLift || 0.35;
this.coastVariance = options.coastVariance || 0.08;
this.outerShelfDepth = options.outerShelfDepth || 2.5;
this.noise = new SimplexNoise(options.seed || 42); this.noise = new SimplexNoise(options.seed || 42);
this.terrain = null; this.terrain = null;
@@ -65,20 +74,45 @@ export class TerrainGenerator {
height += detail; height += detail;
const distFromCenter = Math.sqrt(x * x + y * y); const distFromCenter = Math.sqrt(x * x + y * y);
const maxLandDist = this.size * 0.45; const angle = Math.atan2(y, x);
const falloffStart = this.size * 0.2; const coastNoise = this.noise.fbm(
Math.cos(angle) * 1.7 + 11.3,
Math.sin(angle) * 1.7 - 4.8,
3,
2.0,
0.5
);
const coastlineRadius = this.size * this.maxLandRatio * (1 + coastNoise * this.coastVariance);
const falloffStart = coastlineRadius * (this.falloffStartRatio / this.maxLandRatio);
const coreRadius = this.size * this.coreRadiusRatio;
let continentLift = 1.0;
if (distFromCenter < coreRadius) {
const t = distFromCenter / coreRadius;
continentLift += (1 - t * t) * this.continentLift;
}
let continentMask = 1.0; let continentMask = 1.0;
let edgeDepth = 0; let edgeDepth = 0;
if (distFromCenter > falloffStart) { if (distFromCenter > falloffStart) {
const t = (distFromCenter - falloffStart) / (maxLandDist - falloffStart); const t = (distFromCenter - falloffStart) / Math.max(0.0001, coastlineRadius - falloffStart);
continentMask = Math.max(0, 1 - Math.pow(t, 1.2)); continentMask = Math.max(0, 1 - Math.pow(t, 1.2));
edgeDepth = -15 * Math.pow(Math.max(0, t), 2); edgeDepth = -this.edgeDepth * Math.pow(Math.max(0, t), 2);
} }
height = height * continentMask + edgeDepth; height = ((height * continentLift) + this.landBias) * continentMask + edgeDepth;
height = height * this.maxHeight * 0.5; height = height * this.maxHeight * 0.5;
if (distFromCenter > coastlineRadius) {
const t = THREE.MathUtils.clamp(
(distFromCenter - coastlineRadius) / (this.size * 0.08),
0,
1
);
const forcedSeaFloor = this.waterLevel - this.outerShelfDepth * Math.pow(t, 1.1);
height = Math.min(height, forcedSeaFloor);
}
const shoreMin = this.waterLevel - this.shoreWidth; const shoreMin = this.waterLevel - this.shoreWidth;
const shoreMax = this.waterLevel + this.shoreWidth; const shoreMax = this.waterLevel + this.shoreWidth;
if (height > shoreMin && height < shoreMax) { if (height > shoreMin && height < shoreMax) {
@@ -91,6 +125,10 @@ export class TerrainGenerator {
} }
} }
if (height < this.waterLevel) {
height -= this.underwaterDepthBias;
}
if (Math.abs(height - this.waterLevel) < 0.06) { if (Math.abs(height - this.waterLevel) < 0.06) {
height = this.waterLevel - 0.06; height = this.waterLevel - 0.06;
} }