Probleme mit der HD rendern - moonphase

This commit is contained in:
2026-04-07 11:52:28 +02:00
parent 88c80b1c7d
commit 11cf0ae0dd
+78 -57
View File
@@ -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,38 +832,7 @@ async function fetchMoonPhaseData(date) {
let moonSceneInitPromise = null; let moonSceneInitPromise = null;
async function ensureMoonScene() { async function buildMoonSceneFromUrls(url1, url2) {
if (moonSceneState) {
return moonSceneState;
}
if (moonSceneInitPromise) {
return moonSceneInitPromise;
}
moonSceneInitPromise = (async () => {
moonLoading.classList.remove('is-hidden', 'is-error');
setMoonLoadingProgress(0, 'Lade Mondtexturen... 0 %');
const objectUrls = [];
try {
let prog1 = 0;
let prog2 = 0;
const updateProgress = () => {
const combined = (prog1 + prog2) / 2;
setMoonLoadingProgress(combined, `Lade Mondtexturen... ${Math.round(combined * 100)} %`);
};
const [url1, url2] = await Promise.all([
fetchWithProgress(MOON_TEXTURE_PATH, p => { prog1 = p; updateProgress(); }),
fetchWithProgress(MOON_DISPLACEMENT_MAP_PATH, p => { prog2 = p; updateProgress(); })
]);
objectUrls.push(url1, url2);
setMoonLoadingProgress(1, 'Mondtexturen werden verarbeitet...');
const renderer = new THREE.WebGLRenderer({ const renderer = new THREE.WebGLRenderer({
canvas: moonCanvas, canvas: moonCanvas,
antialias: true, antialias: true,
@@ -856,7 +843,7 @@ async function ensureMoonScene() {
renderer.setClearColor(0x010102, 1); renderer.setClearColor(0x010102, 1);
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 3)); renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 3));
renderer.shadowMap.enabled = true; renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; renderer.shadowMap.type = THREE.PCFShadowMap;
const scene = new THREE.Scene(); const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(28, 1, 0.1, 100); const camera = new THREE.PerspectiveCamera(28, 1, 0.1, 100);
@@ -894,10 +881,9 @@ async function ensureMoonScene() {
}, undefined, reject); }, undefined, reject);
}); });
const [texture, displacementMap] = await Promise.all([ // Sequenziell laden um GPU-Speicherspitzen zu vermeiden
loadTex(url1, THREE.SRGBColorSpace), const texture = await loadTex(url1, THREE.SRGBColorSpace);
loadTex(url2, THREE.NoColorSpace) const displacementMap = await loadTex(url2, THREE.NoColorSpace);
]);
const geometry = new THREE.SphereGeometry(1.6, 256, 256); const geometry = new THREE.SphereGeometry(1.6, 256, 256);
const material = new THREE.MeshStandardMaterial({ const material = new THREE.MeshStandardMaterial({
@@ -921,6 +907,41 @@ async function ensureMoonScene() {
resizeMoonScene(); resizeMoonScene();
applyMoonZoom(); applyMoonZoom();
renderer.render(scene, camera); renderer.render(scene, camera);
}
async function ensureMoonScene() {
if (moonSceneState) {
return moonSceneState;
}
if (moonSceneInitPromise) {
return moonSceneInitPromise;
}
moonSceneInitPromise = (async () => {
moonLoading.classList.remove('is-hidden', 'is-error');
setMoonLoadingProgress(0, 'Lade Mondtexturen... 0 %');
const objectUrls = [];
try {
let prog1 = 0;
let prog2 = 0;
const updateProgress = () => {
const combined = (prog1 + prog2) / 2;
setMoonLoadingProgress(combined, `Lade Mondtexturen... ${Math.round(combined * 100)} %`);
};
const [url1, url2] = await Promise.all([
fetchWithProgress(MOON_TEXTURE_PATH, p => { prog1 = p; updateProgress(); }),
fetchWithProgress(MOON_DISPLACEMENT_MAP_PATH, p => { prog2 = p; updateProgress(); })
]);
objectUrls.push(url1, url2);
setMoonLoadingProgress(1, 'Mondtexturen werden verarbeitet...');
await buildMoonSceneFromUrls(url1, url2);
moonLoadingText.textContent = 'Mondtexturen geladen'; moonLoadingText.textContent = 'Mondtexturen geladen';
window.setTimeout(hideMoonLoading, 350); window.setTimeout(hideMoonLoading, 350);