优化雷
This commit is contained in:
@@ -337,7 +337,7 @@
|
||||
</div>
|
||||
<div class="control-toggle" style="margin-top: 8px;">
|
||||
<label for="rain-audio-enabled">启用雨声</label>
|
||||
<input type="checkbox" id="rain-audio-enabled">
|
||||
<input type="checkbox" id="rain-audio-enabled" checked>
|
||||
</div>
|
||||
<div class="control-grid">
|
||||
<div class="control-group full-width">
|
||||
@@ -352,7 +352,7 @@
|
||||
<div class="control-section-title">雷闪</div>
|
||||
<div class="control-toggle">
|
||||
<label for="lightning-enabled">启用雷闪</label>
|
||||
<input type="checkbox" id="lightning-enabled">
|
||||
<input type="checkbox" id="lightning-enabled" checked>
|
||||
</div>
|
||||
<div class="control-grid">
|
||||
<div class="control-group full-width">
|
||||
|
||||
@@ -41,7 +41,11 @@ export class OceanScene {
|
||||
this.fogLayers = [];
|
||||
this.horizonFog = null;
|
||||
this.skyHazeBand = null;
|
||||
this.rainAudio = null;
|
||||
this.rainAudioPool = [];
|
||||
this.rainAudioActiveIndex = 0;
|
||||
this.rainAudioIsPlaying = false;
|
||||
this.rainAudioCrossfading = false;
|
||||
this.rainAudioCrossfadeDuration = 1.6;
|
||||
this.thunderAudioPool = [];
|
||||
this.thunderAudioIndex = 0;
|
||||
this.scheduledThunder = [];
|
||||
@@ -66,9 +70,9 @@ export class OceanScene {
|
||||
rainVeilIntensity: 1.15,
|
||||
rainDropSize: 1.0,
|
||||
rainSpeed: 1.0,
|
||||
rainAudioEnabled: false,
|
||||
rainAudioEnabled: true,
|
||||
rainAudioVolume: 0.35,
|
||||
lightningEnabled: false,
|
||||
lightningEnabled: true,
|
||||
lightningIntensity: 0.75,
|
||||
mieCoefficient: 0.005,
|
||||
mieDirectionalG: 0.8
|
||||
@@ -191,11 +195,14 @@ export class OceanScene {
|
||||
}
|
||||
|
||||
initAudio() {
|
||||
this.rainAudio = new Audio(RAIN_AUDIO_URL);
|
||||
this.rainAudio.loop = true;
|
||||
this.rainAudio.preload = 'auto';
|
||||
this.rainAudio.volume = this.params.rainAudioVolume;
|
||||
this.rainAudio.crossOrigin = 'anonymous';
|
||||
this.rainAudioPool = Array.from({ length: 2 }, () => {
|
||||
const audio = new Audio(RAIN_AUDIO_URL);
|
||||
audio.loop = false;
|
||||
audio.preload = 'auto';
|
||||
audio.volume = 0;
|
||||
audio.crossOrigin = 'anonymous';
|
||||
return audio;
|
||||
});
|
||||
|
||||
this.thunderAudioPool = Array.from({ length: 3 }, () => {
|
||||
const audio = new Audio(THUNDER_AUDIO_URL);
|
||||
@@ -1054,6 +1061,16 @@ export class OceanScene {
|
||||
this.rainPass.enabled = value;
|
||||
}
|
||||
this.updateRainAudioState();
|
||||
if (!value) {
|
||||
this.lightningFlash = 0;
|
||||
this.lightningLocalFlash = 0;
|
||||
this.lightningBurstEnd = 0;
|
||||
this.nextLightningAt = 0;
|
||||
this.lightningPulseSchedule = [];
|
||||
this.scheduledThunder = [];
|
||||
this.applyLightningState(0);
|
||||
this.stopThunderAudio();
|
||||
}
|
||||
}
|
||||
|
||||
setRainScreenIntensity(value) {
|
||||
@@ -1091,25 +1108,72 @@ export class OceanScene {
|
||||
|
||||
setRainAudioVolume(value) {
|
||||
this.params.rainAudioVolume = value;
|
||||
if (this.rainAudio) {
|
||||
this.rainAudio.volume = value;
|
||||
}
|
||||
this.updateRainAudioState();
|
||||
}
|
||||
|
||||
updateRainAudioState() {
|
||||
if (!this.rainAudio) return;
|
||||
if (this.rainAudioPool.length === 0) return;
|
||||
|
||||
const shouldPlay = this.params.rainEnabled && this.params.rainAudioEnabled && this.params.rainAudioVolume > 0.001;
|
||||
if (shouldPlay) {
|
||||
this.rainAudio.volume = this.params.rainAudioVolume;
|
||||
const playPromise = this.rainAudio.play();
|
||||
if (!this.rainAudioIsPlaying) {
|
||||
const active = this.rainAudioPool[this.rainAudioActiveIndex];
|
||||
active.currentTime = 0;
|
||||
active.volume = this.params.rainAudioVolume;
|
||||
const playPromise = active.play();
|
||||
if (playPromise?.catch) {
|
||||
playPromise.catch(() => {});
|
||||
}
|
||||
this.rainAudioIsPlaying = true;
|
||||
this.rainAudioCrossfading = false;
|
||||
}
|
||||
} else {
|
||||
for (const audio of this.rainAudioPool) {
|
||||
audio.pause();
|
||||
audio.currentTime = 0;
|
||||
audio.volume = 0;
|
||||
}
|
||||
this.rainAudioIsPlaying = false;
|
||||
this.rainAudioCrossfading = false;
|
||||
}
|
||||
}
|
||||
|
||||
updateRainAudioLoop() {
|
||||
if (!this.rainAudioIsPlaying || this.rainAudioPool.length < 2) return;
|
||||
|
||||
const active = this.rainAudioPool[this.rainAudioActiveIndex];
|
||||
const next = this.rainAudioPool[(this.rainAudioActiveIndex + 1) % this.rainAudioPool.length];
|
||||
const duration = Number.isFinite(active.duration) ? active.duration : 0;
|
||||
if (duration <= 0) {
|
||||
active.volume = this.params.rainAudioVolume;
|
||||
return;
|
||||
}
|
||||
|
||||
const timeLeft = duration - active.currentTime;
|
||||
if (!this.rainAudioCrossfading && timeLeft <= this.rainAudioCrossfadeDuration) {
|
||||
next.currentTime = 0;
|
||||
next.volume = 0;
|
||||
const playPromise = next.play();
|
||||
if (playPromise?.catch) {
|
||||
playPromise.catch(() => {});
|
||||
}
|
||||
this.rainAudioCrossfading = true;
|
||||
}
|
||||
|
||||
if (this.rainAudioCrossfading) {
|
||||
const progress = THREE.MathUtils.clamp(1.0 - timeLeft / this.rainAudioCrossfadeDuration, 0, 1);
|
||||
active.volume = this.params.rainAudioVolume * (1.0 - progress);
|
||||
next.volume = this.params.rainAudioVolume * progress;
|
||||
|
||||
if (progress >= 0.999 || active.ended) {
|
||||
active.pause();
|
||||
active.currentTime = 0;
|
||||
active.volume = 0;
|
||||
this.rainAudioActiveIndex = (this.rainAudioActiveIndex + 1) % this.rainAudioPool.length;
|
||||
this.rainAudioCrossfading = false;
|
||||
}
|
||||
} else {
|
||||
this.rainAudio.pause();
|
||||
this.rainAudio.currentTime = 0;
|
||||
active.volume = this.params.rainAudioVolume;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1193,7 +1257,7 @@ export class OceanScene {
|
||||
}
|
||||
|
||||
playThunder(volume, playbackRate) {
|
||||
if (!this.params.lightningEnabled || this.thunderAudioPool.length === 0) return;
|
||||
if (!this.params.rainEnabled || !this.params.lightningEnabled || this.thunderAudioPool.length === 0) return;
|
||||
|
||||
const audio = this.thunderAudioPool[this.thunderAudioIndex % this.thunderAudioPool.length];
|
||||
this.thunderAudioIndex += 1;
|
||||
@@ -1208,7 +1272,7 @@ export class OceanScene {
|
||||
}
|
||||
|
||||
updateThunder(time) {
|
||||
if (!this.params.lightningEnabled || this.scheduledThunder.length === 0) return;
|
||||
if (!this.params.rainEnabled || !this.params.lightningEnabled || this.scheduledThunder.length === 0) return;
|
||||
|
||||
const pending = [];
|
||||
for (const thunder of this.scheduledThunder) {
|
||||
@@ -1222,7 +1286,7 @@ export class OceanScene {
|
||||
}
|
||||
|
||||
updateLightning(time) {
|
||||
if (!this.params.lightningEnabled) return;
|
||||
if (!this.params.rainEnabled || !this.params.lightningEnabled) return;
|
||||
|
||||
if (this.nextLightningAt === 0) {
|
||||
this.scheduleNextLightning(time);
|
||||
@@ -1361,6 +1425,7 @@ export class OceanScene {
|
||||
const time = this.clock.getElapsedTime();
|
||||
this.updateLightning(time);
|
||||
this.updateThunder(time);
|
||||
this.updateRainAudioLoop();
|
||||
|
||||
if (this.water) {
|
||||
this.water.material.uniforms['time'].value += 1.0 / 60.0;
|
||||
|
||||
Reference in New Issue
Block a user