加入海天线柔和,不明显
This commit is contained in:
165
index.html
165
index.html
@@ -89,36 +89,60 @@
|
|||||||
top: 20px;
|
top: 20px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
background: rgba(0, 0, 0, 0.7);
|
background: rgba(0, 0, 0, 0.7);
|
||||||
padding: 20px;
|
padding: 15px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
color: white;
|
color: white;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
min-width: 250px;
|
min-width: 280px;
|
||||||
|
max-height: calc(100vh - 40px);
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sun-controls h3 {
|
#sun-controls h3 {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 12px;
|
||||||
font-size: 16px;
|
font-size: 14px;
|
||||||
border-bottom: 1px solid rgba(255,255,255,0.2);
|
border-bottom: 1px solid rgba(255,255,255,0.2);
|
||||||
padding-bottom: 10px;
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-section {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-section-title {
|
||||||
|
font-size: 11px;
|
||||||
|
opacity: 0.6;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 8px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-group {
|
.control-group {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group.full-width {
|
||||||
|
grid-column: 1 / -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-group label {
|
.control-group label {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 3px;
|
||||||
font-size: 13px;
|
font-size: 11px;
|
||||||
opacity: 0.9;
|
opacity: 0.85;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-group input[type="range"] {
|
.control-group input[type="range"] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 6px;
|
height: 4px;
|
||||||
border-radius: 3px;
|
border-radius: 2px;
|
||||||
background: rgba(255,255,255,0.2);
|
background: rgba(255,255,255,0.2);
|
||||||
outline: none;
|
outline: none;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
@@ -126,8 +150,8 @@
|
|||||||
|
|
||||||
.control-group input[type="range"]::-webkit-slider-thumb {
|
.control-group input[type="range"]::-webkit-slider-thumb {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
width: 16px;
|
width: 12px;
|
||||||
height: 16px;
|
height: 12px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: #4a9eff;
|
background: #4a9eff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -135,9 +159,9 @@
|
|||||||
|
|
||||||
.control-value {
|
.control-value {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font-size: 12px;
|
font-size: 10px;
|
||||||
opacity: 0.7;
|
opacity: 0.6;
|
||||||
margin-top: 3px;
|
margin-top: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#stats {
|
#stats {
|
||||||
@@ -172,11 +196,112 @@
|
|||||||
|
|
||||||
<div id="sun-controls">
|
<div id="sun-controls">
|
||||||
<h3>☀️ 场景控制</h3>
|
<h3>☀️ 场景控制</h3>
|
||||||
<div class="control-group">
|
|
||||||
<label>太阳高度角 (Elevation)</label>
|
<div class="control-section">
|
||||||
<input type="range" id="sun-elevation" min="0" max="90" value="2" step="0.1">
|
<div class="control-section-title">太阳 & 光照</div>
|
||||||
<div class="control-value" id="sun-elevation-value">2.0°</div>
|
<div class="control-grid">
|
||||||
|
<div class="control-group">
|
||||||
|
<label>太阳高度</label>
|
||||||
|
<input type="range" id="sun-elevation" min="0" max="90" value="2" step="0.1">
|
||||||
|
<div class="control-value" id="sun-elevation-value">2.0°</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>太阳方位</label>
|
||||||
|
<input type="range" id="sun-azimuth" min="-180" max="180" value="180" step="0.1">
|
||||||
|
<div class="control-value" id="sun-azimuth-value">180.0°</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>曝光度</label>
|
||||||
|
<input type="range" id="exposure" min="0" max="1" value="0.1" step="0.01">
|
||||||
|
<div class="control-value" id="exposure-value">0.10</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>浑浊度</label>
|
||||||
|
<input type="range" id="turbidity" min="1" max="20" value="10" step="0.1">
|
||||||
|
<div class="control-value" id="turbidity-value">10.0</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>瑞利散射</label>
|
||||||
|
<input type="range" id="rayleigh" min="0" max="4" value="2" step="0.01">
|
||||||
|
<div class="control-value" id="rayleigh-value">2.00</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="control-section">
|
||||||
|
<div class="control-section-title">Bloom 效果</div>
|
||||||
|
<div class="control-grid">
|
||||||
|
<div class="control-group">
|
||||||
|
<label>强度</label>
|
||||||
|
<input type="range" id="bloom-strength" min="0" max="3" value="0.1" step="0.01">
|
||||||
|
<div class="control-value" id="bloom-strength-value">0.10</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>扩散</label>
|
||||||
|
<input type="range" id="bloom-radius" min="0" max="1" value="0" step="0.01">
|
||||||
|
<div class="control-value" id="bloom-radius-value">0.00</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-section">
|
||||||
|
<div class="control-section-title">云层</div>
|
||||||
|
<div class="control-grid">
|
||||||
|
<div class="control-group">
|
||||||
|
<label>覆盖度</label>
|
||||||
|
<input type="range" id="cloud-coverage" min="0" max="1" value="0.4" step="0.01">
|
||||||
|
<div class="control-value" id="cloud-coverage-value">0.40</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>密度</label>
|
||||||
|
<input type="range" id="cloud-density" min="0" max="1" value="0.5" step="0.01">
|
||||||
|
<div class="control-value" id="cloud-density-value">0.50</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>高度</label>
|
||||||
|
<input type="range" id="cloud-elevation" min="0" max="1" value="0.5" step="0.01">
|
||||||
|
<div class="control-value" id="cloud-elevation-value">0.50</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-section">
|
||||||
|
<div class="control-section-title">雾气</div>
|
||||||
|
<div class="control-grid">
|
||||||
|
<div class="control-group">
|
||||||
|
<label>浓度</label>
|
||||||
|
<input type="range" id="fog-density" min="0" max="1" value="0.42" step="0.01">
|
||||||
|
<div class="control-value" id="fog-density-value">0.42</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>高度</label>
|
||||||
|
<input type="range" id="fog-height" min="0" max="1" value="0.32" step="0.01">
|
||||||
|
<div class="control-value" id="fog-height-value">0.32</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>范围</label>
|
||||||
|
<input type="range" id="fog-range" min="0" max="1" value="0.55" step="0.01">
|
||||||
|
<div class="control-value" id="fog-range-value">0.55</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-section">
|
||||||
|
<div class="control-section-title">海天线柔和</div>
|
||||||
|
<div class="control-grid">
|
||||||
|
<div class="control-group">
|
||||||
|
<label>模糊强度</label>
|
||||||
|
<input type="range" id="horizon-blend" min="0" max="1" value="0.45" step="0.01">
|
||||||
|
<div class="control-value" id="horizon-blend-value">0.45</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>发光强度</label>
|
||||||
|
<input type="range" id="horizon-glow" min="0" max="1" value="0.28" step="0.01">
|
||||||
|
<div class="control-value" id="horizon-glow-value">0.28</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>太阳方位角 (Azimuth)</label>
|
<label>太阳方位角 (Azimuth)</label>
|
||||||
<input type="range" id="sun-azimuth" min="-180" max="180" value="180" step="0.1">
|
<input type="range" id="sun-azimuth" min="-180" max="180" value="180" step="0.1">
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ export class OceanScene {
|
|||||||
this.fogLayers = [];
|
this.fogLayers = [];
|
||||||
this.horizonFog = null;
|
this.horizonFog = null;
|
||||||
this.skyHazeBand = null;
|
this.skyHazeBand = null;
|
||||||
|
this.horizonSoftBlend = null;
|
||||||
|
this.horizonGlow = null;
|
||||||
|
|
||||||
this.params = {
|
this.params = {
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
@@ -51,7 +53,9 @@ export class OceanScene {
|
|||||||
fogHeight: 0.32,
|
fogHeight: 0.32,
|
||||||
fogRange: 0.55,
|
fogRange: 0.55,
|
||||||
mieCoefficient: 0.005,
|
mieCoefficient: 0.005,
|
||||||
mieDirectionalG: 0.8
|
mieDirectionalG: 0.8,
|
||||||
|
horizonBlend: 0.45,
|
||||||
|
horizonGlow: 0.28
|
||||||
};
|
};
|
||||||
|
|
||||||
this.clock = new THREE.Clock();
|
this.clock = new THREE.Clock();
|
||||||
@@ -285,6 +289,10 @@ export class OceanScene {
|
|||||||
this.fogGroup.add(this.horizonFog);
|
this.fogGroup.add(this.horizonFog);
|
||||||
this.skyHazeBand = this.createSkyHazeBand();
|
this.skyHazeBand = this.createSkyHazeBand();
|
||||||
this.fogGroup.add(this.skyHazeBand);
|
this.fogGroup.add(this.skyHazeBand);
|
||||||
|
this.horizonSoftBlend = this.createHorizonSoftBlend();
|
||||||
|
this.fogGroup.add(this.horizonSoftBlend);
|
||||||
|
this.horizonGlow = this.createHorizonGlow();
|
||||||
|
this.fogGroup.add(this.horizonGlow);
|
||||||
this.scene.add(this.fogGroup);
|
this.scene.add(this.fogGroup);
|
||||||
this.updateFog();
|
this.updateFog();
|
||||||
}
|
}
|
||||||
@@ -357,10 +365,13 @@ export class OceanScene {
|
|||||||
const context = canvas.getContext('2d');
|
const context = canvas.getContext('2d');
|
||||||
const gradient = context.createLinearGradient(0, 0, 0, canvas.height);
|
const gradient = context.createLinearGradient(0, 0, 0, canvas.height);
|
||||||
gradient.addColorStop(0, 'rgba(255,255,255,0)');
|
gradient.addColorStop(0, 'rgba(255,255,255,0)');
|
||||||
gradient.addColorStop(0.16, 'rgba(255,255,255,0.08)');
|
gradient.addColorStop(0.08, 'rgba(255,255,255,0.02)');
|
||||||
gradient.addColorStop(0.38, 'rgba(255,255,255,0.62)');
|
gradient.addColorStop(0.2, 'rgba(255,255,255,0.12)');
|
||||||
gradient.addColorStop(0.6, 'rgba(255,255,255,0.42)');
|
gradient.addColorStop(0.35, 'rgba(255,255,255,0.38)');
|
||||||
gradient.addColorStop(0.82, 'rgba(255,255,255,0.06)');
|
gradient.addColorStop(0.5, 'rgba(255,255,255,0.55)');
|
||||||
|
gradient.addColorStop(0.65, 'rgba(255,255,255,0.38)');
|
||||||
|
gradient.addColorStop(0.8, 'rgba(255,255,255,0.12)');
|
||||||
|
gradient.addColorStop(0.92, 'rgba(255,255,255,0.02)');
|
||||||
gradient.addColorStop(1, 'rgba(255,255,255,0)');
|
gradient.addColorStop(1, 'rgba(255,255,255,0)');
|
||||||
context.fillStyle = gradient;
|
context.fillStyle = gradient;
|
||||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
@@ -382,10 +393,14 @@ export class OceanScene {
|
|||||||
const context = canvas.getContext('2d');
|
const context = canvas.getContext('2d');
|
||||||
const gradient = context.createLinearGradient(0, 0, 0, canvas.height);
|
const gradient = context.createLinearGradient(0, 0, 0, canvas.height);
|
||||||
gradient.addColorStop(0, 'rgba(255,255,255,0)');
|
gradient.addColorStop(0, 'rgba(255,255,255,0)');
|
||||||
gradient.addColorStop(0.12, 'rgba(255,255,255,0.04)');
|
gradient.addColorStop(0.06, 'rgba(255,255,255,0.01)');
|
||||||
gradient.addColorStop(0.34, 'rgba(255,255,255,0.32)');
|
gradient.addColorStop(0.15, 'rgba(255,255,255,0.06)');
|
||||||
gradient.addColorStop(0.56, 'rgba(255,255,255,0.78)');
|
gradient.addColorStop(0.28, 'rgba(255,255,255,0.18)');
|
||||||
gradient.addColorStop(0.82, 'rgba(255,255,255,0.18)');
|
gradient.addColorStop(0.42, 'rgba(255,255,255,0.45)');
|
||||||
|
gradient.addColorStop(0.55, 'rgba(255,255,255,0.62)');
|
||||||
|
gradient.addColorStop(0.7, 'rgba(255,255,255,0.45)');
|
||||||
|
gradient.addColorStop(0.85, 'rgba(255,255,255,0.12)');
|
||||||
|
gradient.addColorStop(0.94, 'rgba(255,255,255,0.02)');
|
||||||
gradient.addColorStop(1, 'rgba(255,255,255,0)');
|
gradient.addColorStop(1, 'rgba(255,255,255,0)');
|
||||||
context.fillStyle = gradient;
|
context.fillStyle = gradient;
|
||||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
@@ -442,6 +457,105 @@ export class OceanScene {
|
|||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createHorizonSoftBlendTexture() {
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = 64;
|
||||||
|
canvas.height = 512;
|
||||||
|
|
||||||
|
const context = canvas.getContext('2d');
|
||||||
|
const gradient = context.createLinearGradient(0, 0, 0, canvas.height);
|
||||||
|
gradient.addColorStop(0, 'rgba(255,255,255,0)');
|
||||||
|
gradient.addColorStop(0.15, 'rgba(255,255,255,0.01)');
|
||||||
|
gradient.addColorStop(0.3, 'rgba(255,255,255,0.08)');
|
||||||
|
gradient.addColorStop(0.45, 'rgba(255,255,255,0.25)');
|
||||||
|
gradient.addColorStop(0.5, 'rgba(255,255,255,0.32)');
|
||||||
|
gradient.addColorStop(0.55, 'rgba(255,255,255,0.25)');
|
||||||
|
gradient.addColorStop(0.7, 'rgba(255,255,255,0.08)');
|
||||||
|
gradient.addColorStop(0.85, 'rgba(255,255,255,0.01)');
|
||||||
|
gradient.addColorStop(1, 'rgba(255,255,255,0)');
|
||||||
|
context.fillStyle = gradient;
|
||||||
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
const texture = new THREE.CanvasTexture(canvas);
|
||||||
|
texture.colorSpace = THREE.SRGBColorSpace;
|
||||||
|
texture.wrapS = THREE.RepeatWrapping;
|
||||||
|
texture.wrapT = THREE.ClampToEdgeWrapping;
|
||||||
|
texture.repeat.set(5, 1);
|
||||||
|
texture.needsUpdate = true;
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
createHorizonSoftBlend() {
|
||||||
|
const texture = this.createHorizonSoftBlendTexture();
|
||||||
|
const material = new THREE.MeshBasicMaterial({
|
||||||
|
map: texture,
|
||||||
|
alphaMap: texture,
|
||||||
|
color: 0xe8f0f5,
|
||||||
|
transparent: true,
|
||||||
|
opacity: 0.45,
|
||||||
|
fog: false,
|
||||||
|
depthWrite: false,
|
||||||
|
side: THREE.BackSide,
|
||||||
|
blending: THREE.NormalBlending
|
||||||
|
});
|
||||||
|
|
||||||
|
const geometry = new THREE.CylinderGeometry(4850, 4850, 1200, 72, 1, true);
|
||||||
|
const mesh = new THREE.Mesh(geometry, material);
|
||||||
|
mesh.position.y = 180;
|
||||||
|
mesh.renderOrder = -3;
|
||||||
|
mesh.userData.texture = texture;
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
createHorizonGlowTexture() {
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = 64;
|
||||||
|
canvas.height = 512;
|
||||||
|
|
||||||
|
const context = canvas.getContext('2d');
|
||||||
|
const gradient = context.createLinearGradient(0, 0, 0, canvas.height);
|
||||||
|
gradient.addColorStop(0, 'rgba(255,255,255,0)');
|
||||||
|
gradient.addColorStop(0.25, 'rgba(255,255,255,0.02)');
|
||||||
|
gradient.addColorStop(0.4, 'rgba(255,255,255,0.12)');
|
||||||
|
gradient.addColorStop(0.48, 'rgba(255,255,255,0.22)');
|
||||||
|
gradient.addColorStop(0.52, 'rgba(255,255,255,0.22)');
|
||||||
|
gradient.addColorStop(0.6, 'rgba(255,255,255,0.12)');
|
||||||
|
gradient.addColorStop(0.75, 'rgba(255,255,255,0.02)');
|
||||||
|
gradient.addColorStop(1, 'rgba(255,255,255,0)');
|
||||||
|
context.fillStyle = gradient;
|
||||||
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
const texture = new THREE.CanvasTexture(canvas);
|
||||||
|
texture.colorSpace = THREE.SRGBColorSpace;
|
||||||
|
texture.wrapS = THREE.RepeatWrapping;
|
||||||
|
texture.wrapT = THREE.ClampToEdgeWrapping;
|
||||||
|
texture.repeat.set(6, 1);
|
||||||
|
texture.needsUpdate = true;
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
createHorizonGlow() {
|
||||||
|
const texture = this.createHorizonGlowTexture();
|
||||||
|
const material = new THREE.MeshBasicMaterial({
|
||||||
|
map: texture,
|
||||||
|
alphaMap: texture,
|
||||||
|
color: 0xfff5e8,
|
||||||
|
transparent: true,
|
||||||
|
opacity: 0.28,
|
||||||
|
fog: false,
|
||||||
|
depthWrite: false,
|
||||||
|
side: THREE.BackSide,
|
||||||
|
blending: THREE.AdditiveBlending
|
||||||
|
});
|
||||||
|
|
||||||
|
const geometry = new THREE.CylinderGeometry(4600, 4600, 600, 72, 1, true);
|
||||||
|
const mesh = new THREE.Mesh(geometry, material);
|
||||||
|
mesh.position.y = 120;
|
||||||
|
mesh.renderOrder = -4;
|
||||||
|
mesh.userData.texture = texture;
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
async initWater() {
|
async initWater() {
|
||||||
const waterGeometry = new THREE.PlaneGeometry(10000, 10000, 128, 128);
|
const waterGeometry = new THREE.PlaneGeometry(10000, 10000, 128, 128);
|
||||||
|
|
||||||
@@ -711,6 +825,16 @@ export class OceanScene {
|
|||||||
this.updateFog();
|
this.updateFog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setHorizonBlend(value) {
|
||||||
|
this.params.horizonBlend = value;
|
||||||
|
this.updateFog();
|
||||||
|
}
|
||||||
|
|
||||||
|
setHorizonGlow(value) {
|
||||||
|
this.params.horizonGlow = value;
|
||||||
|
this.updateFog();
|
||||||
|
}
|
||||||
|
|
||||||
updateClouds() {
|
updateClouds() {
|
||||||
if (!this.cloudGroup) return;
|
if (!this.cloudGroup) return;
|
||||||
|
|
||||||
@@ -780,6 +904,41 @@ export class OceanScene {
|
|||||||
);
|
);
|
||||||
this.skyHazeBand.visible = this.skyHazeBand.material.opacity > 0.01;
|
this.skyHazeBand.visible = this.skyHazeBand.material.opacity > 0.01;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.horizonSoftBlend) {
|
||||||
|
const softBlendColor = horizonColor.clone().lerp(skyBlendColor, 0.35);
|
||||||
|
this.horizonSoftBlend.material.color.copy(softBlendColor);
|
||||||
|
this.horizonSoftBlend.material.opacity =
|
||||||
|
this.params.horizonBlend *
|
||||||
|
THREE.MathUtils.lerp(0.8, 1.2, this.params.fogDensity) *
|
||||||
|
THREE.MathUtils.lerp(0.85, 1.1, this.params.fogRange);
|
||||||
|
this.horizonSoftBlend.position.y = THREE.MathUtils.lerp(120, 220, this.params.fogHeight);
|
||||||
|
this.horizonSoftBlend.scale.set(
|
||||||
|
THREE.MathUtils.lerp(0.9, 1.18, this.params.fogRange),
|
||||||
|
THREE.MathUtils.lerp(0.85, 1.12, this.params.fogHeight),
|
||||||
|
THREE.MathUtils.lerp(0.9, 1.18, this.params.fogRange)
|
||||||
|
);
|
||||||
|
this.horizonSoftBlend.visible = this.horizonSoftBlend.material.opacity > 0.01;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.horizonGlow) {
|
||||||
|
const warmGlow = new THREE.Color(0xfff5e8);
|
||||||
|
const coolGlow = new THREE.Color(0xe8f4ff);
|
||||||
|
const glowColor = warmGlow.clone().lerp(coolGlow, sunMix);
|
||||||
|
this.horizonGlow.material.color.copy(glowColor);
|
||||||
|
this.horizonGlow.material.opacity =
|
||||||
|
this.params.horizonGlow *
|
||||||
|
THREE.MathUtils.lerp(0.7, 1.1, this.params.fogDensity) *
|
||||||
|
THREE.MathUtils.lerp(0.8, 1.05, this.params.fogRange) *
|
||||||
|
THREE.MathUtils.clamp((this.params.elevation + 5) / 50, 0.1, 1);
|
||||||
|
this.horizonGlow.position.y = THREE.MathUtils.lerp(80, 160, this.params.fogHeight);
|
||||||
|
this.horizonGlow.scale.set(
|
||||||
|
THREE.MathUtils.lerp(0.92, 1.15, this.params.fogRange),
|
||||||
|
THREE.MathUtils.lerp(0.88, 1.1, this.params.fogHeight),
|
||||||
|
THREE.MathUtils.lerp(0.92, 1.15, this.params.fogRange)
|
||||||
|
);
|
||||||
|
this.horizonGlow.visible = this.horizonGlow.material.opacity > 0.01;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
animate() {
|
animate() {
|
||||||
@@ -811,6 +970,12 @@ export class OceanScene {
|
|||||||
if (this.skyHazeBand?.userData.texture) {
|
if (this.skyHazeBand?.userData.texture) {
|
||||||
this.skyHazeBand.userData.texture.offset.x = -time * 0.00018;
|
this.skyHazeBand.userData.texture.offset.x = -time * 0.00018;
|
||||||
}
|
}
|
||||||
|
if (this.horizonSoftBlend?.userData.texture) {
|
||||||
|
this.horizonSoftBlend.userData.texture.offset.x = time * 0.00012;
|
||||||
|
}
|
||||||
|
if (this.horizonGlow?.userData.texture) {
|
||||||
|
this.horizonGlow.userData.texture.offset.x = -time * 0.00008;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.vegetationSystem) {
|
if (this.vegetationSystem) {
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ function setupControls(oceanScene) {
|
|||||||
bindSlider('fog-density', (value) => value.toFixed(2), (value) => oceanScene.setFogDensity(value));
|
bindSlider('fog-density', (value) => value.toFixed(2), (value) => oceanScene.setFogDensity(value));
|
||||||
bindSlider('fog-height', (value) => value.toFixed(2), (value) => oceanScene.setFogHeight(value));
|
bindSlider('fog-height', (value) => value.toFixed(2), (value) => oceanScene.setFogHeight(value));
|
||||||
bindSlider('fog-range', (value) => value.toFixed(2), (value) => oceanScene.setFogRange(value));
|
bindSlider('fog-range', (value) => value.toFixed(2), (value) => oceanScene.setFogRange(value));
|
||||||
|
bindSlider('horizon-blend', (value) => value.toFixed(2), (value) => oceanScene.setHorizonBlend(value));
|
||||||
|
bindSlider('horizon-glow', (value) => value.toFixed(2), (value) => oceanScene.setHorizonGlow(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch(console.error);
|
main().catch(console.error);
|
||||||
|
|||||||
Reference in New Issue
Block a user