Snyggare moln

This commit is contained in:
2026-11-03 22:56:33 +01:00
parent 6ea397a9e5
commit 490da8e97f
34 changed files with 1270 additions and 72 deletions

View File

@@ -400,8 +400,32 @@ Ringens atmosfär och moln använder cylindriska volymer begränsade av kanterna
Terräng och hav tar emot trädens kaskadskuggor, styrda av `vegetation.shadowDistancesMeters`, `shadowResolution`, `shadowSoftness` och `shadowBiasMeters`. Stommen och båda kantväggarna skymmer direkt solljus enligt sina faktiska cylindriska volymer, inklusive väggarnas ovan- och utsidor. Mark, vatten, växter och atmosfär använder samma skugggeometri i ringens lokala koordinater, så skuggorna följer solen när ringen roterar. Molnskuggorna integrerar tätheten längs solstrålen genom det invändiga molnlagret. De följer de synliga molnens seed, vind och täckning; `clouds.shadowStrength` styr styrkan (0 stänger av molnskuggorna).
Närmaterialen använder både färg, normal och roughness från materialkatalogen. Mark, växtmodeller och trädens impostorer delar ett diffust himmelsljus i ringens gravitationsram; löv får även ljusgenomsläpp. Stjärnor tonas ned när spelaren står i dagsljus i ringens atmosfär.
Molnen har två cylindriska volymlager. Huvudlagret använder befintliga `clouds` för höjd, täckning, täthet, vind och ljus. `shapeScaleMeters` styr molnformationernas storlek, `detailScaleMeters` och `erosion` detaljerna i deras kanter. Cachade 3D-volymer med fraktal- och Worley-brus ger rundade molnformer och mindre luckor. Större väderområden skiftar täckningen över ringen; `ringWorld.cloudDetail.weatherScaleMeters` styr deras fysiska skala (standard 90 km), `weatherVariation` variationens styrka (0–1, 0,9 i standardringen). Noll ger jämn täckning men behåller enskilda molnformer. Täckning 0 och 1 i huvudlagret är fortfarande helt klar respektive helt mulen himmel.
`ringWorld.cloudDetail` styr också ett tunnare närlager för små, finare moln. `nearEnabled` slår av och på lagret. Standardringen använder `nearBaseAltitudeMeters: 7200`, `nearThicknessMeters: 700`, `nearScaleMeters: 3200`, `nearDetailScaleMeters: 240`, `nearCoverage: 0.3` och `nearDensity: 0.24`. Båda höjdvärdena mäts från ringens invändiga nollnivå; hela lagret måste rymmas i atmosfären. Närmolnen samlas i större väderfläckar med tydliga blå luckor mellan grupperna. De finaste brusoktaverna bidrar svagare, och mycket tunna resttätheter tas bort för att undvika ett jämnt kornigt täcke. Standardringen använder även glesare huvudmoln med täckning 0,29, skala 26 km och erosion 0,2. Närlagret är oberoende av huvudlagrets täckning och täthet men kräver `clouds.enabled: true`.
`nearDistanceMeters` är 100 km i standardringen. Närlagret tonar bort från 65 procent av räckvidden och renderas inte bortom gränsen, så de små molnen hamnar inte på ringens bortre sida. Närdetaljer i huvudlagret tonas också bort med avstånd och pixelstorlek. På avstånd används större, varierade former och väderområden. Brusfält och vind är bundna till ringens lokala koordinater och saknar longitudskarv. Molnskuggorna använder samma väder och stora former med grövre filtrering för stabila skuggkanter.
Molnen renderas separat från luften med `clouds.resolutionScale` (standard 0,5) och skalas upp med hjälp av scenens djup. `clouds.viewSteps` och `lightSteps` begränsar provtagningen nära kameran (standard 96 och 2); avlägsna moln använder högst 24 respektive 2 steg. Närlagret får tätare provtagning för fina detaljer. Självskuggning, flera approximationer av ljusspridning och luftperspektiv ger ljusa kanter, mörkare undersidor och mjukare färg på avstånd. Ringens huvudlager begränsas inte av Jordens `clouds.maxViewDistanceMeters`, eftersom ringens bortre sida ska synas. Närlagret begränsas av sin egen räckvidd.
`ringWorld.meadow` lägger till ett separat gräslager med geometriska strån nära spelaren. `enabled` stänger av lagret, `distanceMeters` styr räckvidden (8–80 m), `spacingMeters` avståndet mellan tuvorna (0,3–2 m) och `heightMeters` grundhöjden (0,05–1 m). Standardringen använder 48 m, 0,35 m och 0,28 m. Tuvornas höjd varierar och tonas av mot räckviddens slut. Rötter genereras deterministiskt i små lokala rutor på en bakgrundstråd; stråna byggs på grafikkortet, följer marken och tar emot träd-, vägg- och molnskuggor. Lagret utesluter vatten, sand, snö och branta sluttningar. Det kastar inte egna individuella stråskuggor. Befintliga örter, buskar och träd renderas separat.
Gräsets täthet och höjd varierar i sammanhängande fläckar som går över rutgränserna. Varje strå har egen längd, böjning och färgvariation, tre böjda sektioner, en ljusare mittnerv och en svag glans. Vindrörelsen varierar mellan tuvorna.
`ringWorld.rendering.temporalAntialiasing` aktiverar åtta subpixelpositioner och återanvänder tidigare HDR-bildrutor nära marken (inom 100 m). Historiken följer ringens lokala koordinater genom omlopp, rotation och spelarens rörelse. Djupjämförelse och begränsning mot aktuella grannpixlar minskar släp vid nya silhuetter. Historiken återställs vid byte av värld, teleportering, ändrad upplösning, synfält och shaderomladdning. Gräsets och lövens vind har ingen separat rörelsevektortextur; små rörelser hanteras med djup- och färgavvisning. På avstånd används kortare historik för moln, och bakgrunden utan ytdjup ackumuleras inte.
`ringWorld.rendering.contactOcclusion` aktiverar korta kontaktskuggor från djupbilden nära marken. `contactStrength` styr mörkningen (0–1, standard 0,45). Effekten beräknas i halv upplösning och skalas upp med djupfiltrering för att undvika mörka kanter mot himlen. Den använder bara synlig geometri och ersätter inte trädens eller väggarnas solskuggor. Båda renderingseffekterna är aktiva i standardringen och kan stängas av var för sig i JSON.
Verifiera med `dotnet test tests/Universe.Tests/Universe.Tests.csproj -c Release -m:1` och `dotnet run -c Release --project src/Universe.App -- --ring-world-report`. Grafikrapporten kör de riktiga OpenGL-shadrarna och sparar översikt, insida, mark, fötter och hav i `graphics-report/ring-world/` bredvid appen. `surface-map.png` visar hela färgkartan som fyra efterföljande remsor med bevarade proportioner. Rapporten skriver ut faktisk upplösning i meter och kontrollerar även att vegetation laddas och att markdjup finns under spelaren.
`performance.txt` redovisar median och 95:e percentilen för bildrutetid, kostnad per renderingspass samt en separat mätning med spelare, trädkollisioner, omlopp och rotation aktiva. Den mäter också oavsiktlig rörelse relativt ringen; högst 5 mm tillåts. Testsviten kontrollerar dessutom 60 sekunders stillastående på ojämn mark med både frusen och rörlig ring. FPS-värdena gäller aktuell dator, upplösning och inläst testscen.
Lägg till `--report-1440p` efter `--ring-world-report` för ett dolt fönster på 2560 × 1440. Rapporten mäter även gång, kamerarörelse och aktiv vind, skriver antal synliga grästuvor och sparar `walking.png`. Gräslagret ingår i tiden för terrängpasset. Kontaktskuggor och temporal kantutjämning redovisas separat; DLSS ingår inte.
GPU-rapporten kontrollerar också temporal kantutjämning mot ett medelvärde av åtta subpixelprov, återställning efter kameraklipp och att kontaktskuggorna lämnar en plan yta oförändrad men skuggar intill en upphöjning. `surface-effects-off.png`, `contact-on.png` och `surface-effects-on.png` jämför samma vy med effekterna av och på. Testsviten kontrollerar att geometri och rekonstruerade synstrålar använder samma jitter samt att återprojektionen följer en roterande och förflyttad ring.
Molnkontrollerna kör den riktiga molnshadern med isolerat närlager och huvudlager. De verifierar att närmoln är synliga nära kameran, helt saknas på avstånd och kan stängas av, samt att väderinställningen förändrar avlägsna moln. `cloud-near.png`, `cloud-distant.png` och `cloud-inside-near.png` visar marknära vyer och en vy inifrån närlagret. `cloud-near-fixture.png` och `cloud-far-fixture.png` visar de isolerade GPU-kontrollerna. Molnens kostnad redovisas separat under `clouds` i prestandarapporten.
Grafikrapporten testar även solstrålar över och under båda väggkanterna, stommens in- och utsida samt det öppna centrumet direkt i produktionsshadern. Den kontrollerar molnskuggornas täckning, vindrörelse och koordinattransformation, och sparar jämförelsebilderna `tree-shadows-on/off.png` och `cloud-shadows-on/off.png`. Trädjämförelsen isolerar skuggorna på ringens ytor; molnjämförelsen använder en kontrollerad mulen himmel med samma träd och terräng.

View File

@@ -23,7 +23,7 @@
"enabled": true,
"flatMaterial": "leafy-grass",
"slopeMaterial": "rock-ground",
"scaleMeters": 8,
"scaleMeters": 2,
"fadeDistanceMeters": 2000,
"strength": 0.8
},
@@ -32,12 +32,12 @@
"densityTextureStrength": 0.0,
"baseAltitudeMeters": 2100,
"thicknessMeters": 4300,
"coverage": 0.4,
"density": 0.85,
"shapeScaleMeters": 18000,
"detailScaleMeters": 2400,
"erosion": 0.45,
"cloudType": 0.9,
"coverage": 0.29,
"density": 0.7,
"shapeScaleMeters": 26000,
"detailScaleMeters": 1300,
"erosion": 0.2,
"cloudType": 0.75,
"windSpeedMetersPerSecond": 18,
"windDirectionDegrees": 25,
"extinctionPerMeter": 0.0007,
@@ -48,9 +48,9 @@
"sunlightStrength": 1.0,
"sunsetStrength": 1.4,
"shadowStrength": 0.7,
"viewSteps": 48,
"lightSteps": 4,
"resolutionScale": 0.4,
"viewSteps": 96,
"lightSteps": 2,
"resolutionScale": 0.5,
"maxViewDistanceMeters": 220000
},
"ocean": {
@@ -133,7 +133,8 @@
150,
400
],
"grassDistanceMeters": 80,
"grassDistanceMeters": 65,
"groundDensityPerHectare": 16000,
"shrubDistanceMeters": 150,
"affectGroundMaterials": true,
"uploadBudgetMilliseconds": 1,
@@ -147,6 +148,29 @@
]
},
"ringWorld": {
"cloudDetail": {
"weatherScaleMeters": 90000,
"weatherVariation": 0.9,
"nearEnabled": true,
"nearBaseAltitudeMeters": 7200,
"nearThicknessMeters": 700,
"nearScaleMeters": 3200,
"nearDetailScaleMeters": 240,
"nearCoverage": 0.3,
"nearDensity": 0.24,
"nearDistanceMeters": 100000
},
"rendering": {
"temporalAntialiasing": true,
"contactOcclusion": true,
"contactStrength": 0.45
},
"meadow": {
"enabled": true,
"distanceMeters": 48,
"spacingMeters": 0.35,
"heightMeters": 0.28
},
"diameterMeters": 5000000,
"widthMeters": 500000,
"thicknessMeters": 50000,