添加风机

This commit is contained in:
2026-03-27 18:11:27 +08:00
parent 4a9410802d
commit c0ca5b51c4
6 changed files with 405 additions and 3 deletions

View File

@@ -10,6 +10,7 @@ import Stats from 'three/addons/libs/stats.module.js';
import { TerrainGenerator } from './TerrainGenerator.js';
import { VegetationSystem } from './VegetationSystem.js';
import { DEFAULT_SCENE_PARAMS } from './weatherPresets.js';
import { OffshoreWindTurbineAsset } from './objects/OffshoreWindTurbineAsset.js';
const RAIN_AUDIO_URL = '/audio/rain-calming.mp3';
const THUNDER_AUDIO_URL = '/audio/thunder-distant.mp3';
@@ -25,8 +26,10 @@ export class OceanScene {
this.sky = null;
this.starField = null;
this.moonSprite = null;
this.moonGlowSprite = null;
this.galaxyBand = null;
this.sun = new THREE.Vector3();
this.initialSun = new THREE.Vector3();
this.terrain = null;
this.vegetation = null;
this.vegetationSystem = null;
@@ -50,6 +53,7 @@ export class OceanScene {
this.fogLayers = [];
this.horizonFog = null;
this.skyHazeBand = null;
this.windTurbine = null;
this.rainAudioPool = [];
this.rainAudioActiveIndex = 0;
this.rainAudioIsPlaying = false;
@@ -85,6 +89,7 @@ export class OceanScene {
this.initFog();
await this.initWater();
await this.initTerrain();
await this.initWindTurbine();
await this.initVegetation();
this.initSunPosition();
this.initEventListeners();
@@ -645,6 +650,20 @@ export class OceanScene {
this.moonSprite.scale.setScalar(490);
this.scene.add(this.moonSprite);
const moonGlowTexture = this.createMoonGlowTexture();
const moonGlowMaterial = new THREE.SpriteMaterial({
map: moonGlowTexture,
color: 0xc6dbff,
transparent: true,
opacity: 0,
depthWrite: false,
depthTest: true,
blending: THREE.AdditiveBlending
});
this.moonGlowSprite = new THREE.Sprite(moonGlowMaterial);
this.moonGlowSprite.scale.setScalar(980);
this.scene.add(this.moonGlowSprite);
const galaxyTexture = this.createGalaxyTexture();
const galaxyMaterial = new THREE.SpriteMaterial({
map: galaxyTexture,
@@ -704,6 +723,28 @@ export class OceanScene {
return texture;
}
createMoonGlowTexture() {
const canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 512;
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
const glow = ctx.createRadialGradient(256, 256, 0, 256, 256, 256);
glow.addColorStop(0, 'rgba(255,255,255,0.62)');
glow.addColorStop(0.12, 'rgba(236,242,255,0.46)');
glow.addColorStop(0.28, 'rgba(198,216,255,0.26)');
glow.addColorStop(0.52, 'rgba(148,184,255,0.11)');
glow.addColorStop(0.78, 'rgba(120,160,255,0.05)');
glow.addColorStop(1, 'rgba(120,160,255,0)');
ctx.fillStyle = glow;
ctx.fillRect(0, 0, canvas.width, canvas.height);
const texture = new THREE.CanvasTexture(canvas);
texture.colorSpace = THREE.SRGBColorSpace;
return texture;
}
createGalaxyTexture() {
const canvas = document.createElement('canvas');
canvas.width = 1024;
@@ -1259,15 +1300,36 @@ export class OceanScene {
const baseWaterOnBeforeRender = this.water.onBeforeRender.bind(this.water);
this.water.onBeforeRender = (...args) => {
const starsWereVisible = this.starField?.visible ?? false;
const moonWasVisible = this.moonSprite?.visible ?? false;
const moonGlowWasVisible = this.moonGlowSprite?.visible ?? false;
const galaxyWasVisible = this.galaxyBand?.visible ?? false;
if (this.starField) {
this.starField.visible = false;
}
if (this.moonSprite) {
this.moonSprite.visible = false;
}
if (this.moonGlowSprite) {
this.moonGlowSprite.visible = false;
}
if (this.galaxyBand) {
this.galaxyBand.visible = false;
}
try {
baseWaterOnBeforeRender(...args);
} finally {
if (this.starField) {
this.starField.visible = starsWereVisible;
}
if (this.moonSprite) {
this.moonSprite.visible = moonWasVisible;
}
if (this.moonGlowSprite) {
this.moonGlowSprite.visible = moonGlowWasVisible;
}
if (this.galaxyBand) {
this.galaxyBand.visible = galaxyWasVisible;
}
}
};
@@ -1299,6 +1361,18 @@ export class OceanScene {
this.terrainGenerator = terrainGen;
}
async initWindTurbine() {
this.windTurbine = new OffshoreWindTurbineAsset({
position: new THREE.Vector3(280, 0, -2350),
yaw: 0,
scale: 0.68,
rotorSpeed: 0.24
});
await this.windTurbine.load();
this.windTurbine.addToScene(this.scene);
this.windTurbine.faceDirection(this.sun);
}
async initVegetation() {
const vegSystem = new VegetationSystem(this.terrainGenerator, {
@@ -1344,6 +1418,7 @@ export class OceanScene {
}
initSunPosition() {
this.initialSun.copy(this.sun);
this.updateSun();
}
@@ -1352,6 +1427,9 @@ export class OceanScene {
const theta = THREE.MathUtils.degToRad(this.params.azimuth);
this.sun.setFromSphericalCoords(1, phi, theta);
if (this.initialSun.lengthSq() === 0) {
this.initialSun.copy(this.sun);
}
this.sky.material.uniforms['sunPosition'].value.copy(this.sun);
this.water.material.uniforms['sunDirection'].value.copy(this.sun).normalize();
@@ -1965,7 +2043,7 @@ export class OceanScene {
this.starField.material.uniforms.intensity.value = opacity;
if (this.moonSprite) {
const moonAngle = THREE.MathUtils.degToRad(this.params.azimuth - 42);
const moonAngle = Math.atan2(this.initialSun.z, this.initialSun.x);
const moonDistance = 3200;
this.moonSprite.position.set(
Math.cos(moonAngle) * moonDistance,
@@ -1977,6 +2055,13 @@ export class OceanScene {
this.moonSprite.material.opacity = THREE.MathUtils.lerp(0.0, 2.4, moonGlow);
const moonScale = THREE.MathUtils.lerp(410, 730, moonGlow);
this.moonSprite.scale.setScalar(moonScale);
if (this.moonGlowSprite) {
this.moonGlowSprite.position.copy(this.moonSprite.position);
this.moonGlowSprite.visible = this.moonSprite.visible;
this.moonGlowSprite.material.opacity = moonGlow * 1.18;
this.moonGlowSprite.scale.setScalar(THREE.MathUtils.lerp(980, 1680, moonGlow));
}
}
if (this.galaxyBand) {
@@ -2070,7 +2155,8 @@ export class OceanScene {
requestAnimationFrame(() => this.animate());
this.stats?.begin();
const time = this.clock.getElapsedTime();
const delta = this.clock.getDelta();
const time = this.clock.elapsedTime;
this.updateLightning(time);
this.updateThunder(time);
this.updateRainAudioLoop();
@@ -2107,6 +2193,11 @@ export class OceanScene {
this.vegetationSystem.update(time);
}
if (this.windTurbine) {
this.windTurbine.faceDirection(this.sun);
this.windTurbine.update(time, delta);
}
if (this.lightningFlash > 0.001) {
this.updateClouds();
this.updateFog();