Probleme mit der HD rendern - moonphase
This commit is contained in:
+116
-95
@@ -309,7 +309,7 @@ try {
|
|||||||
<script type="module">
|
<script type="module">
|
||||||
import * as THREE from './js/three.module.min.js';
|
import * as THREE from './js/three.module.min.js';
|
||||||
|
|
||||||
const moonCanvas = document.getElementById('moonCanvas');
|
let moonCanvas = document.getElementById('moonCanvas');
|
||||||
const moonCraterOverlay = document.getElementById('moonCraterOverlay');
|
const moonCraterOverlay = document.getElementById('moonCraterOverlay');
|
||||||
const datePicker = document.getElementById('datePicker');
|
const datePicker = document.getElementById('datePicker');
|
||||||
const timeSlider = document.getElementById('timeSlider');
|
const timeSlider = document.getElementById('timeSlider');
|
||||||
@@ -553,8 +553,33 @@ async function fetchWithProgress(url, onProgress) {
|
|||||||
return URL.createObjectURL(new Blob(chunks));
|
return URL.createObjectURL(new Blob(chunks));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function destroyMoonScene() {
|
||||||
|
if (!moonSceneState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { renderer, scene, moonMesh } = moonSceneState;
|
||||||
|
|
||||||
|
moonMesh.material.map && moonMesh.material.map.dispose();
|
||||||
|
moonMesh.material.displacementMap && moonMesh.material.displacementMap.dispose();
|
||||||
|
moonMesh.material.dispose();
|
||||||
|
moonMesh.geometry.dispose();
|
||||||
|
scene.clear();
|
||||||
|
renderer.dispose();
|
||||||
|
|
||||||
|
// Canvas durch frisches Element ersetzen damit kein alter WebGL-Kontext hängt
|
||||||
|
const newCanvas = document.createElement('canvas');
|
||||||
|
newCanvas.id = moonCanvas.id;
|
||||||
|
newCanvas.setAttribute('aria-label', moonCanvas.getAttribute('aria-label') || '');
|
||||||
|
moonCanvas.replaceWith(newCanvas);
|
||||||
|
moonCanvas = newCanvas;
|
||||||
|
|
||||||
|
moonSceneState = null;
|
||||||
|
moonSceneInitPromise = null;
|
||||||
|
}
|
||||||
|
|
||||||
async function loadHdTextures() {
|
async function loadHdTextures() {
|
||||||
if (hdTexturesLoaded || hdTexturesLoading || !moonSceneState) {
|
if (hdTexturesLoaded || hdTexturesLoading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,17 +588,8 @@ async function loadHdTextures() {
|
|||||||
moonLoading.classList.remove('is-hidden', 'is-error');
|
moonLoading.classList.remove('is-hidden', 'is-error');
|
||||||
setMoonLoadingProgress(0, 'HD-Texturen werden geladen... 0 %');
|
setMoonLoadingProgress(0, 'HD-Texturen werden geladen... 0 %');
|
||||||
|
|
||||||
const textureLoader = new THREE.TextureLoader();
|
|
||||||
const objectUrls = [];
|
const objectUrls = [];
|
||||||
|
|
||||||
const loadTexture = (objectUrl, colorSpace) => new Promise((resolve, reject) => {
|
|
||||||
textureLoader.load(objectUrl, tex => {
|
|
||||||
tex.colorSpace = colorSpace;
|
|
||||||
tex.anisotropy = moonSceneState.renderer.capabilities.getMaxAnisotropy();
|
|
||||||
resolve(tex);
|
|
||||||
}, undefined, reject);
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let prog1 = 0;
|
let prog1 = 0;
|
||||||
let prog2 = 0;
|
let prog2 = 0;
|
||||||
@@ -583,23 +599,25 @@ async function loadHdTextures() {
|
|||||||
setMoonLoadingProgress(combined, `HD-Texturen werden geladen... ${Math.round(combined * 100)} %`);
|
setMoonLoadingProgress(combined, `HD-Texturen werden geladen... ${Math.round(combined * 100)} %`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Beide Dateien parallel herunterladen (RAM, noch kein GPU)
|
||||||
const [url1, url2] = await Promise.all([
|
const [url1, url2] = await Promise.all([
|
||||||
fetchWithProgress(MOON_TEXTURE_PATH_HD, p => { prog1 = p; updateProgress(); }),
|
fetchWithProgress(MOON_TEXTURE_PATH_HD, p => { prog1 = p; updateProgress(); }),
|
||||||
fetchWithProgress(MOON_DISPLACEMENT_MAP_PATH_HD, p => { prog2 = p; updateProgress(); })
|
fetchWithProgress(MOON_DISPLACEMENT_MAP_PATH_HD, p => { prog2 = p; updateProgress(); })
|
||||||
]);
|
]);
|
||||||
|
|
||||||
objectUrls.push(url1, url2);
|
objectUrls.push(url1, url2);
|
||||||
setMoonLoadingProgress(1, 'HD-Texturen werden verarbeitet...');
|
setMoonLoadingProgress(1, 'Alte Scene wird entfernt...');
|
||||||
|
|
||||||
const [hdTex, hdDisp] = await Promise.all([
|
// Alte Scene komplett zerstören → GPU-VRAM vollständig frei
|
||||||
loadTexture(url1, THREE.SRGBColorSpace),
|
destroyMoonScene();
|
||||||
loadTexture(url2, THREE.NoColorSpace)
|
|
||||||
]);
|
|
||||||
|
|
||||||
moonSceneState.moonMesh.material.map = hdTex;
|
// Warten damit der Browser/GPU den Speicher wirklich freigibt
|
||||||
moonSceneState.moonMesh.material.displacementMap = hdDisp;
|
await new Promise(resolve => window.setTimeout(resolve, 200));
|
||||||
moonSceneState.moonMesh.material.bumpMap = hdDisp;
|
|
||||||
moonSceneState.moonMesh.material.needsUpdate = true;
|
setMoonLoadingProgress(1, 'HD-Scene wird aufgebaut...');
|
||||||
|
|
||||||
|
// Scene neu aufbauen mit den HD-Blob-URLs
|
||||||
|
await buildMoonSceneFromUrls(url1, url2);
|
||||||
|
|
||||||
hdTexturesLoaded = true;
|
hdTexturesLoaded = true;
|
||||||
hdTexturesLoading = false;
|
hdTexturesLoading = false;
|
||||||
@@ -814,6 +832,83 @@ async function fetchMoonPhaseData(date) {
|
|||||||
|
|
||||||
let moonSceneInitPromise = null;
|
let moonSceneInitPromise = null;
|
||||||
|
|
||||||
|
async function buildMoonSceneFromUrls(url1, url2) {
|
||||||
|
const renderer = new THREE.WebGLRenderer({
|
||||||
|
canvas: moonCanvas,
|
||||||
|
antialias: true,
|
||||||
|
alpha: false,
|
||||||
|
powerPreference: 'high-performance'
|
||||||
|
});
|
||||||
|
renderer.outputColorSpace = THREE.SRGBColorSpace;
|
||||||
|
renderer.setClearColor(0x010102, 1);
|
||||||
|
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 3));
|
||||||
|
renderer.shadowMap.enabled = true;
|
||||||
|
renderer.shadowMap.type = THREE.PCFShadowMap;
|
||||||
|
|
||||||
|
const scene = new THREE.Scene();
|
||||||
|
const camera = new THREE.PerspectiveCamera(28, 1, 0.1, 100);
|
||||||
|
camera.position.set(0, 0, MOON_CAMERA_BASE_Z);
|
||||||
|
|
||||||
|
const ambientLight = new THREE.AmbientLight(0x1b2230, 0.004);
|
||||||
|
scene.add(ambientLight);
|
||||||
|
|
||||||
|
const sunLight = new THREE.DirectionalLight(0xffffff, 2.9);
|
||||||
|
sunLight.castShadow = true;
|
||||||
|
sunLight.shadow.mapSize.width = 4096;
|
||||||
|
sunLight.shadow.mapSize.height = 4096;
|
||||||
|
sunLight.shadow.bias = -0.00015;
|
||||||
|
sunLight.shadow.normalBias = 0.02;
|
||||||
|
sunLight.shadow.camera.near = 1;
|
||||||
|
sunLight.shadow.camera.far = 20;
|
||||||
|
sunLight.shadow.camera.left = -3;
|
||||||
|
sunLight.shadow.camera.right = 3;
|
||||||
|
sunLight.shadow.camera.top = 3;
|
||||||
|
sunLight.shadow.camera.bottom = -3;
|
||||||
|
scene.add(sunLight);
|
||||||
|
|
||||||
|
const rimLight = new THREE.DirectionalLight(0x89a8ff, 0.015);
|
||||||
|
rimLight.position.set(-2.5, 1.2, 3.2);
|
||||||
|
scene.add(rimLight);
|
||||||
|
|
||||||
|
const textureLoader = new THREE.TextureLoader();
|
||||||
|
const maxAnisotropy = renderer.capabilities.getMaxAnisotropy();
|
||||||
|
|
||||||
|
const loadTex = (url, colorSpace) => new Promise((resolve, reject) => {
|
||||||
|
textureLoader.load(url, tex => {
|
||||||
|
tex.colorSpace = colorSpace;
|
||||||
|
tex.anisotropy = maxAnisotropy;
|
||||||
|
resolve(tex);
|
||||||
|
}, undefined, reject);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sequenziell laden um GPU-Speicherspitzen zu vermeiden
|
||||||
|
const texture = await loadTex(url1, THREE.SRGBColorSpace);
|
||||||
|
const displacementMap = await loadTex(url2, THREE.NoColorSpace);
|
||||||
|
|
||||||
|
const geometry = new THREE.SphereGeometry(1.6, 256, 256);
|
||||||
|
const material = new THREE.MeshStandardMaterial({
|
||||||
|
map: texture,
|
||||||
|
displacementMap,
|
||||||
|
displacementScale: MOON_DISPLACEMENT_SCALE,
|
||||||
|
displacementBias: MOON_DISPLACEMENT_BIAS,
|
||||||
|
bumpMap: displacementMap,
|
||||||
|
bumpScale: MOON_BUMP_SCALE,
|
||||||
|
roughness: 1,
|
||||||
|
metalness: 0
|
||||||
|
});
|
||||||
|
const moonMesh = new THREE.Mesh(geometry, material);
|
||||||
|
moonMesh.castShadow = true;
|
||||||
|
moonMesh.receiveShadow = true;
|
||||||
|
moonMesh.rotation.y = MOON_TEXTURE_BASE_ROTATION_Y;
|
||||||
|
scene.add(moonMesh);
|
||||||
|
|
||||||
|
moonSceneState = { renderer, scene, camera, moonMesh, sunLight, ambientLight, rimLight };
|
||||||
|
|
||||||
|
resizeMoonScene();
|
||||||
|
applyMoonZoom();
|
||||||
|
renderer.render(scene, camera);
|
||||||
|
}
|
||||||
|
|
||||||
async function ensureMoonScene() {
|
async function ensureMoonScene() {
|
||||||
if (moonSceneState) {
|
if (moonSceneState) {
|
||||||
return moonSceneState;
|
return moonSceneState;
|
||||||
@@ -846,81 +941,7 @@ async function ensureMoonScene() {
|
|||||||
objectUrls.push(url1, url2);
|
objectUrls.push(url1, url2);
|
||||||
setMoonLoadingProgress(1, 'Mondtexturen werden verarbeitet...');
|
setMoonLoadingProgress(1, 'Mondtexturen werden verarbeitet...');
|
||||||
|
|
||||||
const renderer = new THREE.WebGLRenderer({
|
await buildMoonSceneFromUrls(url1, url2);
|
||||||
canvas: moonCanvas,
|
|
||||||
antialias: true,
|
|
||||||
alpha: false,
|
|
||||||
powerPreference: 'high-performance'
|
|
||||||
});
|
|
||||||
renderer.outputColorSpace = THREE.SRGBColorSpace;
|
|
||||||
renderer.setClearColor(0x010102, 1);
|
|
||||||
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 3));
|
|
||||||
renderer.shadowMap.enabled = true;
|
|
||||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
|
||||||
|
|
||||||
const scene = new THREE.Scene();
|
|
||||||
const camera = new THREE.PerspectiveCamera(28, 1, 0.1, 100);
|
|
||||||
camera.position.set(0, 0, MOON_CAMERA_BASE_Z);
|
|
||||||
|
|
||||||
const ambientLight = new THREE.AmbientLight(0x1b2230, 0.004);
|
|
||||||
scene.add(ambientLight);
|
|
||||||
|
|
||||||
const sunLight = new THREE.DirectionalLight(0xffffff, 2.9);
|
|
||||||
sunLight.castShadow = true;
|
|
||||||
sunLight.shadow.mapSize.width = 4096;
|
|
||||||
sunLight.shadow.mapSize.height = 4096;
|
|
||||||
sunLight.shadow.bias = -0.00015;
|
|
||||||
sunLight.shadow.normalBias = 0.02;
|
|
||||||
sunLight.shadow.camera.near = 1;
|
|
||||||
sunLight.shadow.camera.far = 20;
|
|
||||||
sunLight.shadow.camera.left = -3;
|
|
||||||
sunLight.shadow.camera.right = 3;
|
|
||||||
sunLight.shadow.camera.top = 3;
|
|
||||||
sunLight.shadow.camera.bottom = -3;
|
|
||||||
scene.add(sunLight);
|
|
||||||
|
|
||||||
const rimLight = new THREE.DirectionalLight(0x89a8ff, 0.015);
|
|
||||||
rimLight.position.set(-2.5, 1.2, 3.2);
|
|
||||||
scene.add(rimLight);
|
|
||||||
|
|
||||||
const textureLoader = new THREE.TextureLoader();
|
|
||||||
const maxAnisotropy = renderer.capabilities.getMaxAnisotropy();
|
|
||||||
|
|
||||||
const loadTex = (url, colorSpace) => new Promise((resolve, reject) => {
|
|
||||||
textureLoader.load(url, tex => {
|
|
||||||
tex.colorSpace = colorSpace;
|
|
||||||
tex.anisotropy = maxAnisotropy;
|
|
||||||
resolve(tex);
|
|
||||||
}, undefined, reject);
|
|
||||||
});
|
|
||||||
|
|
||||||
const [texture, displacementMap] = await Promise.all([
|
|
||||||
loadTex(url1, THREE.SRGBColorSpace),
|
|
||||||
loadTex(url2, THREE.NoColorSpace)
|
|
||||||
]);
|
|
||||||
|
|
||||||
const geometry = new THREE.SphereGeometry(1.6, 256, 256);
|
|
||||||
const material = new THREE.MeshStandardMaterial({
|
|
||||||
map: texture,
|
|
||||||
displacementMap,
|
|
||||||
displacementScale: MOON_DISPLACEMENT_SCALE,
|
|
||||||
displacementBias: MOON_DISPLACEMENT_BIAS,
|
|
||||||
bumpMap: displacementMap,
|
|
||||||
bumpScale: MOON_BUMP_SCALE,
|
|
||||||
roughness: 1,
|
|
||||||
metalness: 0
|
|
||||||
});
|
|
||||||
const moonMesh = new THREE.Mesh(geometry, material);
|
|
||||||
moonMesh.castShadow = true;
|
|
||||||
moonMesh.receiveShadow = true;
|
|
||||||
moonMesh.rotation.y = MOON_TEXTURE_BASE_ROTATION_Y;
|
|
||||||
scene.add(moonMesh);
|
|
||||||
|
|
||||||
moonSceneState = { renderer, scene, camera, moonMesh, sunLight, ambientLight, rimLight };
|
|
||||||
|
|
||||||
resizeMoonScene();
|
|
||||||
applyMoonZoom();
|
|
||||||
renderer.render(scene, camera);
|
|
||||||
|
|
||||||
moonLoadingText.textContent = 'Mondtexturen geladen';
|
moonLoadingText.textContent = 'Mondtexturen geladen';
|
||||||
window.setTimeout(hideMoonLoading, 350);
|
window.setTimeout(hideMoonLoading, 350);
|
||||||
|
|||||||
Reference in New Issue
Block a user