沙沙的雨声
This commit is contained in:
11
index.html
11
index.html
@@ -335,6 +335,17 @@
|
|||||||
<div class="control-value" id="rain-speed-value">1.00</div>
|
<div class="control-value" id="rain-speed-value">1.00</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="control-toggle" style="margin-top: 8px;">
|
||||||
|
<label for="rain-audio-enabled">启用雨声</label>
|
||||||
|
<input type="checkbox" id="rain-audio-enabled">
|
||||||
|
</div>
|
||||||
|
<div class="control-grid">
|
||||||
|
<div class="control-group full-width">
|
||||||
|
<label>雨声音量</label>
|
||||||
|
<input type="range" id="rain-audio-volume" min="0" max="1" value="0.35" step="0.01">
|
||||||
|
<div class="control-value" id="rain-audio-volume-value">0.35</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-section">
|
<div class="control-section">
|
||||||
|
|||||||
BIN
public/audio/rain-calming.mp3
Normal file
BIN
public/audio/rain-calming.mp3
Normal file
Binary file not shown.
@@ -9,6 +9,8 @@ import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
|
|||||||
import { TerrainGenerator } from './TerrainGenerator.js';
|
import { TerrainGenerator } from './TerrainGenerator.js';
|
||||||
import { VegetationSystem } from './VegetationSystem.js';
|
import { VegetationSystem } from './VegetationSystem.js';
|
||||||
|
|
||||||
|
const RAIN_AUDIO_URL = '/audio/rain-calming.mp3';
|
||||||
|
|
||||||
export class OceanScene {
|
export class OceanScene {
|
||||||
constructor(container) {
|
constructor(container) {
|
||||||
this.container = container;
|
this.container = container;
|
||||||
@@ -38,6 +40,7 @@ export class OceanScene {
|
|||||||
this.fogLayers = [];
|
this.fogLayers = [];
|
||||||
this.horizonFog = null;
|
this.horizonFog = null;
|
||||||
this.skyHazeBand = null;
|
this.skyHazeBand = null;
|
||||||
|
this.rainAudio = null;
|
||||||
|
|
||||||
this.params = {
|
this.params = {
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
@@ -59,6 +62,8 @@ export class OceanScene {
|
|||||||
rainVeilIntensity: 1.15,
|
rainVeilIntensity: 1.15,
|
||||||
rainDropSize: 1.0,
|
rainDropSize: 1.0,
|
||||||
rainSpeed: 1.0,
|
rainSpeed: 1.0,
|
||||||
|
rainAudioEnabled: false,
|
||||||
|
rainAudioVolume: 0.35,
|
||||||
lightningEnabled: false,
|
lightningEnabled: false,
|
||||||
lightningIntensity: 0.75,
|
lightningIntensity: 0.75,
|
||||||
mieCoefficient: 0.005,
|
mieCoefficient: 0.005,
|
||||||
@@ -82,6 +87,7 @@ export class OceanScene {
|
|||||||
this.initControls();
|
this.initControls();
|
||||||
this.initLighting();
|
this.initLighting();
|
||||||
this.initPostProcessing();
|
this.initPostProcessing();
|
||||||
|
this.initAudio();
|
||||||
await this.initSky();
|
await this.initSky();
|
||||||
this.initClouds();
|
this.initClouds();
|
||||||
this.initFog();
|
this.initFog();
|
||||||
@@ -180,6 +186,14 @@ export class OceanScene {
|
|||||||
this.composer.addPass(this.rainPass);
|
this.composer.addPass(this.rainPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
|
||||||
createRainShader() {
|
createRainShader() {
|
||||||
return {
|
return {
|
||||||
uniforms: {
|
uniforms: {
|
||||||
@@ -1028,6 +1042,7 @@ export class OceanScene {
|
|||||||
if (this.rainPass) {
|
if (this.rainPass) {
|
||||||
this.rainPass.enabled = value;
|
this.rainPass.enabled = value;
|
||||||
}
|
}
|
||||||
|
this.updateRainAudioState();
|
||||||
}
|
}
|
||||||
|
|
||||||
setRainScreenIntensity(value) {
|
setRainScreenIntensity(value) {
|
||||||
@@ -1058,6 +1073,35 @@ export class OceanScene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setRainAudioEnabled(value) {
|
||||||
|
this.params.rainAudioEnabled = value;
|
||||||
|
this.updateRainAudioState();
|
||||||
|
}
|
||||||
|
|
||||||
|
setRainAudioVolume(value) {
|
||||||
|
this.params.rainAudioVolume = value;
|
||||||
|
if (this.rainAudio) {
|
||||||
|
this.rainAudio.volume = value;
|
||||||
|
}
|
||||||
|
this.updateRainAudioState();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRainAudioState() {
|
||||||
|
if (!this.rainAudio) 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 (playPromise?.catch) {
|
||||||
|
playPromise.catch(() => {});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.rainAudio.pause();
|
||||||
|
this.rainAudio.currentTime = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setLightningEnabled(value) {
|
setLightningEnabled(value) {
|
||||||
this.params.lightningEnabled = value;
|
this.params.lightningEnabled = value;
|
||||||
if (!value) {
|
if (!value) {
|
||||||
|
|||||||
@@ -68,8 +68,10 @@ function setupControls(oceanScene) {
|
|||||||
bindSlider('rain-veil-intensity', (value) => value.toFixed(2), (value) => oceanScene.setRainVeilIntensity(value));
|
bindSlider('rain-veil-intensity', (value) => value.toFixed(2), (value) => oceanScene.setRainVeilIntensity(value));
|
||||||
bindSlider('rain-drop-size', (value) => value.toFixed(2), (value) => oceanScene.setRainDropSize(value));
|
bindSlider('rain-drop-size', (value) => value.toFixed(2), (value) => oceanScene.setRainDropSize(value));
|
||||||
bindSlider('rain-speed', (value) => value.toFixed(2), (value) => oceanScene.setRainSpeed(value));
|
bindSlider('rain-speed', (value) => value.toFixed(2), (value) => oceanScene.setRainSpeed(value));
|
||||||
|
bindSlider('rain-audio-volume', (value) => value.toFixed(2), (value) => oceanScene.setRainAudioVolume(value));
|
||||||
bindSlider('lightning-intensity', (value) => value.toFixed(2), (value) => oceanScene.setLightningIntensity(value));
|
bindSlider('lightning-intensity', (value) => value.toFixed(2), (value) => oceanScene.setLightningIntensity(value));
|
||||||
bindCheckbox('rain-enabled', (value) => oceanScene.setRainEnabled(value));
|
bindCheckbox('rain-enabled', (value) => oceanScene.setRainEnabled(value));
|
||||||
|
bindCheckbox('rain-audio-enabled', (value) => oceanScene.setRainAudioEnabled(value));
|
||||||
bindCheckbox('lightning-enabled', (value) => oceanScene.setLightningEnabled(value));
|
bindCheckbox('lightning-enabled', (value) => oceanScene.setLightningEnabled(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user