17 KiB
Universe
En proceduriell 3D-universumsgenerator för Windows med C#/.NET 10, Silk.NET och OpenGL 3.3.
Starta
dotnet run --configuration Release --project src/Universe.App/Universe.App.csproj
Appen börjar framför Jorden (earth) i vårt solsystem i cell (0,0,0). Startmål och vy väljs i config.json.
Solen och de åtta planeterna definieras i KnownSolarSystem/solar-systems.json. Där finns även Jordens måne, Saturnus ringar, planeternas axellutning, atmosfärer och material. Jordens färg- och höjdkartor ligger i KnownSolarSystem/Textures/. Se katalogens dokumentation för fler solsystem och för kombinationen heightmap + noise.
Content/README.md beskriver markmaterialen och den regionala höjdrutan för Alperna. Materialkatalogen och varje planets materials-inställningar är redigerbara i JSON.
| Kontroll | Funktion |
|---|---|
| WASD + mus | Fri flygning och riktning |
| P | Öppna/stäng menyn. Välj Play, Free Camera, Debug, Benchmark Earth, Benchmark Unknown, Galaxy Journey eller Quit med musen eller piltangenter och Enter |
| Space / Ctrl | Upp / ner relativt kameran |
| Mushjul | Logaritmisk hastighet, från 0,1 m/s upp till galaktisk FTL-fart (10^15 c) |
| Q | Mjuk flygning till närmaste planet |
| E | Mjuk flygning till närmaste svarta hål, även från en planets markyta |
| 1–9 | Flyg till planeten på motsvarande plats i startup.planetHotkeys i config.json |
| F2 | Mjuk flygning till en bergsvy nära ytan; hastigheten sänks till 1 200 m/s |
| F3 | Närbild av närmaste stjärna |
| F4 | Mjuk flygning till närmaste ringsystem; lokala isstenar och låg flyghastighet |
| F1 | Släpp / fånga muspekaren |
| F5 | Ladda om shaders; Debug läser direkt från shaderfilerna |
| F6 | Flyg till en solbelyst havsvy nära vattenytan; hastigheten sänks till 10 m/s |
| F7 | Flyg till en vy ovanför närmaste molnlager; hastigheten sänks till 100 m/s |
| F8 | Flyg ut till en översiktsvy av den aktuella galaxen |
| F9 | Flyg till närmaste nebulosa i galaxen |
| Esc | Stäng pausmenyn, eller avsluta när menyn är stängd |
Play växlar till förstapersonsläge. WASD går längs marken, musen ser sig omkring, Space hoppar och Ctrl hukar. Spelaren dras mot närmaste fasta planet och orienteras efter dess lokala gravitation. Från stora avstånd används en snabbare inflygning för att landningen ska vara spelbar. Free Camera återställer fri flygning. Pausmenyn stoppar rörelsen medan den är öppen. Gasjättar har ingen fast mark och väljs därför inte som landningsmål.
Benchmark Earth kör en fast 72-sekunders kameraresa vid Jorden: rymdvy, inflygning och separat mjuk bromsning sista 10 km mot Alpernas Copernicus-terrängdata, följt av en långsam promenadslinga med kameran 1,8 m över marken. Benchmark Unknown kör samma resa på den största tillgängliga proceduriella stenplaneten bland närliggande system som är större än Jorden; dess högre terrängamplitud ger kraftigare proceduriell relief. Blicken sveper runt under promenaden. När testet är klart återgår kameran till sin ursprungliga vy mot Jorden. Panelen uppe till höger visar målplanet och FPS över tid, medelvärde, lägsta bildfrekvens och 1 %-låg. Tryck P eller Esc för att avbryta och öppna menyn. Benchmarken återställer Debug-läget så debug-prober inte påverkar mätningen.
Välj Debug i P-menyn för en panel till vänster med asynkron GPU-tid för separata renderpass och varje ritad planet, CPU-tid för renderingsanropet, FPS och terrängens LOD/chunkstatus. En gång var åttonde bildruta gör debugläget dessutom en osynlig extrarendering av den dyraste planeten med en effekt avstängd. Panelen visar tidsvinsten jämfört med normalrenderingen för material, molnskuggor, bergsskuggor, planet-/ringskuggor och ytdetalj-noise. Varje effekt mäts separat, och skillnaden medelvärdesbildas över de senaste matchande mätningarna. Proberna är asynkrona och påverkar FPS något när debugläget är på; GPU FRAME visar den vanliga bildrenderingen utan probe-drawen. Skuggorna ingår också i planetens ordinarie tid eftersom de räknas i samma terrängshader.
Värld och grafik
- Kända system från JSON ersätter proceduriell generering i sina tilldelade celler. Övriga 100 AU-celler bestäms av global seed och
SectorCoordinate(long X, long Y, long Z). Positionerna behåller dubbelprecision och konverteras till kamerarelativa GPU-koordinater. - Systemens centrum förskjuts med 3D-noise. Stjärnor, lutade elliptiska planetbanor och månar får olika seedade riktningar, faser och avstånd. Alla himlakroppar hålls inom sina celler.
- Berg består av domain-warped ridged multifractal-noise. Samma höjdfält används för kollisionsytan, CPU-meshar och GPU-skuggning.
- Terrängen är en adaptiv cube-sphere med quadtree-chunks. Rutor utanför synfältet och bakom horisonten sorteras bort med konservativa gränser för berg, dalar och skarvar. Närmaste terräng förfinas först, med högre detalj nära kameran och grövre geometri på avstånd. Föräldrachunken visas tills synliga barn är klara. Chunks förankras i dubbelprecision så närflygning behåller precisionen.
- Material varierar med höjd, lutning, mineral-noise och geologiska lager. Terrängnormaler beräknas från höjdfältet vid meshgenerering, kompletteras med finare normaldetaljer och används tillsammans med höjdfältet för bergsskuggor. Alla systemets stjärnor bidrar med ljus och planetförmörkelser.
- Atmosfären integrerar Rayleigh- och Mie-spridning längs både kamera- och solljusstrålar. Djupbufferten begränsar integrationen framför marken. Det ger blå himmel, färgade horisonter, dis mellan berg och en atmosfärsrand från rymden.
- Stjärnorna har långsamt animerad plasma, filament, aktiva områden, granulation och kantförmörkning. Korona, HDR-bloom, ACES-tonmappning, kantutjämning och dithering behandlas i separata pass.
- Bakgrunden består av ett seedat stjärnfält och stjärnorna i granncellerna. Atmosfär och dagsljus dämpar stjärnfältet nära marken.
- Gas- och isjättar renderas som ljussatta, tillplattade gasvolymer med band, polarfärger och dimma vid inflygning. De har ingen terrängmesh eller fast kollisionsyta.
- Ringarnas optiska profil innehåller oregelbundna band och separata luckor. Samma täthet styr skuggor och lokal generering av isstenar. Nära ringarna ersätts ringmaterialet gradvis av instanser med detaljbyte mellan punktpartiklar och oregelbundna 3D-stenar. Inställningar finns i planetens
gasochringsi JSON; se katalogens dokumentation. - Ringstenar får upp till 81 920 trianglar på riktigt nära håll, med gradientnoise, individuella proportioner, kratrar och finare ytstruktur.
rings.rocks.asteroidstyr geometrins LOD och detaljbudget. - Varje sol har avståndsdämpade HDR-strålar, halo och färgade linsreflexer. Glöden förblir synlig långt ut i systemet och kontrolleras mot framförliggande objekt. Solens
glow-block styr effekten. - Jorden har ett separat sfäriskt hav med animerade vågor, Fresnelreflektion, solljusglitter, skum, refraktion och djupberoende ljusabsorption. Havsbotten och kustmasken används av både terrängen och kollisionen.
oceani planetens JSON styr vattenmaterialet; F6 visar havet nära ytan. - Sfäriska 3D-moln använder fraktal noise och Worley-noise, vind, självskuggning och ljus från systemets solar. Valfria equirektangulära gråskalekartor styr den geografiska täckningen; jordens
Content/Clouds/earth-clouds.pnganvänds i solsystemets JSON, där vitt betyder moln och svart klart. Molnen skuggar mark och hav, dämpar solglöden och speglas i vattnet.cloudsi planetens JSON styr karta, utseende och kvalitet.
Detta är en visuell realtidsprototyp. Banorna är statiska och terrängen använder proceduriell relief; ingen hydrologisk erosionssimulering eller atmosfär med multipel spridning beräknas.
Galaxer och nebulosor
KnownGalaxies.json definierar Vintergatan. Den bifogade galaxbilden finns i Content/Galaxies/milky-way.png och används både för utseende och faktisk systemtäthet: luminans × alpha, formad av densityGamma, blir sannolikheten att en seedad stjärnkandidat finns. Svarta eller genomskinliga områden får inga kandidater. Solsystemet är alltid fastlagt i sin kända cell. Byt bildsökvägen i texture, eller utelämna den för en automatiskt genererad spiralgalax.
Varje galaxregion är normalt en miljon ljusår bred. Proceduriella galaxer får egna radier, lutningar, spiralarmar och nebulosor från universums seed. nebulae i en känd galax kan ange id, positionLightYears relativt galaxcentrum, radiusLightYears och en valfri bild. Systemdata har GalaxyId och ett NebulaId för närmaste nebulosagrupp; gruppmedlemskapet innebär inte att varje planet ligger inne i det synliga gasmolnet.
GalaxyAddress delar adressen i en galaxregion, en lokal solsystemscell och lokala meter. De två första delarna är heltal. Befintliga UniversePosition använder fortfarande det globala heltalsrutnätet, så lokala kameror, terräng och kollision behöver aldrig en enda gigantisk flyttalsposition. Avlägsna objekt omvandlas till kamerarelativa koordinater före GPU-rendering.
galaxies i config.json styr regionstorlek, systemSpacingLightYears, galaxyStarBudget, localStarBudget och volumeSteps. Budgeterna begränsar representativa stjärnpunkter och volymsteg, inte universums storlek. Varje stjärnpunkt härleds från en verklig seedad systemkandidat. Glesa systemceller mellan stjärnorna är tomma. Närliggande system laddas först på solsystemsnivå; bakgrundspunkter, galaxvolymer och nebulosavolymer ersätter dyr planetgeometri på större skalor. Stjärnmoln beräknas på högst två bakgrundsjobb, högst en färdig punktmesh laddas upp per bildruta, och högst tre detaljerade system hålls kvar på GPU:n.
Mushjulet kan nu skala fri flyghastighet upp till galaktiska avstånd. F8 och F9 ger översiktsvyer. Vyn växlar mjukt mellan galax-/nebulosapunkter, volymer, individuella systemstjärnor och lokala planeter.
Stjärnornas rörelsespår
Stjärnsprites ritas som mjuka ljusstreck från föregående till aktuell skärmposition. Både kamerans förflyttning, rotation och gradvisa synfältsändring ingår; beräkningen använder kamerarelativa dubbelprecisionspositioner även mellan galaxer. Strecken växer med skärmrörelsen och ger fartkänsla när stjärnor passerar. Stilla stjärnor blir mjuka punkter igen utan kvarhängande efterbilder. Galax-/nebulosamarkörer, planetmeshar och gränssnitt ingår inte i effekten.
starMotionBlur i config.json styr enabled, shutterFraction (hur stor del av bildintervallet som bildar spår), maximumTrailPixels, minimumWidthPixels, movingBrightness, historyResetSeconds och starFadeSeconds. Standardinställningen är 90 % av bildintervallet och högst 180 bildpunkters spår. Kamerahopp, återställda benchmarkvyer, paus, fönsterstorleksbyte och långa bildintervall nollställer historiken. F5 laddar även om stjärnornas vertex-, geometry- och fragmentshaders.
Det lokala stjärnurvalet förankras över 32 stjärngridblock och tonas mellan färdiga urval under 0,3 sekunder. Det gamla urvalet visas tills ersättaren är klar. Detta minskar blinkningar vid laddning utöver den jämnare pixelprofilen och rörelsespåren.
Universe.App.exe --star-trails-report kör ett OpenGL-test med syntetiska stjärnor: rörelse måste ge längre streck än stillastående, den konfigurerade maxlängden kontrolleras och stopp/kamerahopp måste ge rena punktbilder. Bilderna sparas som graphics-report/star-motion-blur.png och star-motion-stopped.png.
Galaxresetest
Välj Galaxy Journey i P-menyn. Den fasta 94-sekundersbanan lämnar Jorden, visar Vintergatan, flyger genom tomrummet till galaxregion (1,0,0), går in i ett deterministiskt utvalt solsystem och landar på dess största fasta huvudplanet, 1,8 m över terrängen. Därefter återställs Jordvyn. Båda ändsystemens grova geometri och kartor förbereds innan mätningen börjar.
Grafen visar FPS över resans tid. Efteråt visas PASS eller FAIL och benchmark-results/galaxy-journey-.../ innehåller frames.csv och summary.json med bildrutetider, planet-/system-/galax-id och statistik per fas. En fas måste uppfylla både minimumBenchmarkFps för sin 1 %-låga FPS och maximumBenchmarkFrameMilliseconds för sin långsammaste bildruta. Standardgränserna är 45 FPS respektive 50 ms. Ett högt medelvärde döljer alltså inte en lång laddningsbildruta.
Kör Universe.App.exe --galaxy-journey-report för ett automatiskt OpenGL-test av samma flöde. Den använder fixerade simuleringssteg och mäter faktisk CPU-/GPU-tid med GPU-synkronisering; det är en accelererad integrationstestkörning utan VSync, inte ett löfte om samma FPS under alla spelinställningar. Bildfiler för galax, nebulosa, planet och resultat hamnar i graphics-report/. Processen returnerar kod 2 om prestandagränserna överskrids. Enhetstester kontrollerar koordinatprecision, textur-/alpha-täthet, reproducerbarhet, hierarkiskt medlemskap, markhöjd, hela resan och att injicerade bildrutetoppar ger FAIL.
Svarta hål
I proceduriella system ersätter ett svart hål stjärnan med 5 % sannolikhet. Samma seed och cell ger samma hål, massa och skivlutning. Kända system, inklusive Solsystemet, behåller sina definierade stjärnor. Planeterna placeras utanför ackretionsskivan och belyses av dess utstrålning.
Tryck E för en nio sekunders kameraresa till en sned vy över skivan. Sökningen jämför dubbelprecisionsavstånd. I galaxläget söker den bland stjärnkandidater inom åtta stjärngridblock (normalt omkring 32 ljusår); utan galaxlagret expanderar den upp till åtta solsystemsceller. Kameran lämnar först planetens yta om den behöver det.
blackHoles i config.json styr occurrenceChance (0–1), minimumMassSolar, maximumMassSolar, diskOuterRadiusInHorizons, diskBrightness och raySteps (128–512). Sätt sannolikheten till 0 för att stänga av genereringen. Standardvärdena ger 200 000–600 000 solmassor, en skiva som sträcker sig till 14 horisontradier och 256 strålsteg.
Renderingen integrerar böjda ljusbanor i en förenklad Schwarzschildmodell och en tunn, animerad skiva. Horisontskugga, böjda bilder av skivans baksida, fotonring, dopplerförstärkning, gravitationell rödskiftning och HDR-bloom skapar utseendet. Se Gralla, Holz och Wald: Black Hole Shadows, Photon Rings, and Lensing Rings för bakgrunden till lins- och fotonringarna. Bakgrunden samplas från scenbilden när den finns i bild; riktningar bakom kameran får ett proceduriellt stjärnfält. Detta är en visuell realtidsmodell med en konstnärligt styrd emissionsskiva.
Debug-panelen visar BLACK HOLE / LENSING separat. Kör Universe.App.exe --black-hole-report för att rendera närmaste hål till graphics-report/black-hole.png och kontrollera shaderkompilering, OpenGL-fel och giltiga bildvärden.
Projekt
src/Universe.Core: koordinater, systemgenerering, noise, terräng, streaming och svept kollision.src/Universe.App: fönster, kamera och OpenGL. Shaderkoden finns underGraphics/Shaders/och bäddas in i bygget.tests/Universe.Tests: koordinater, determinism, cellgränser, terrängkanter, normaler och FTL-kollision.
Bygg och verifiera
dotnet build Universe.sln --configuration Release -m:1
dotnet test tests/Universe.Tests/Universe.Tests.csproj --configuration Release
Kontrollera även den faktiska GPU-höjdfunktionen mot CPU/kollision med:
dotnet run --configuration Release --project src/Universe.App/Universe.App.csproj -- --validate-graphics
Kontrollen läser ett separat numeriskt GPU-testfält och stoppar appen om höjdfälten skiljer sig för mycket. Även Jordens heightmap, axellutning och extra noise jämförs med CPU/kollision. Den vanliga renderingens färgbuffert använder 16-bitars flyttal; testfältet använder 32-bitars flyttal.
En marknära terrängvy med ruttider och diagnostiska, synkroniserade mätningar per renderingspass kan köras med dotnet run -c Release --project src/Universe.App -- --terrain-perf-report. Resultaten varierar med vy, upplösning, laddade rutor och maskin; synkroniseringen i rapporten påverkar också tiderna.
Atmosfärens integrationsmodell bygger på principerna i GPU Gems 2, Accurate Atmospheric Scattering.
Skärmbilder
Bilder direkt från Release-appens OpenGL-rendering:
Även standardvyn för tangent 2 finns sparad i artifacts/surface-view.jpg.
Närbild och avståndsdämpad solglöd, sparade från den riktiga renderingskedjan:
Automatiska GPU-kontroller och nya bilder kan genereras med --graphics-report respektive --scene-report. Se katalogens dokumentation för kommandon och JSON-inställningar.





