# Färgstyrd vegetation `vegetation.json` är den gemensamma katalogen. Sökvägar till modeller utgår från denna mapp. Den äldre mappen `Content/Vegetations/` med markmaterial finns kvar. ## Tillgångar och offlineverktyg De tio modellpaketen kommer från [Poly Haven](https://polyhaven.com), med [CC0-licens](https://polyhaven.com/license). `sources.json` innehåller ursprungliga nedladdningsadresser, filstorlekar och MD5-kontrollsummor. Startpaketet omfattar 1 697 MiB originaldata inklusive 2K-material för skogsmark, torrt gräs och snö. Nedladdaren hämtar bara filer som saknas eller har fel kontrollsumma och stoppar över 2 GB nedladdning. Förberedda modeller, alphakort och avståndsbilder ingår i spelets innehåll. Originalen och mellansteget `source/bake-source.glb` behövs bara vid import, ignoreras av Git och kopieras inte till distributionen. Spelet behöver inte nätåtkomst, Node eller Python. Återskapa resurser från projektroten med Python 3, Node och .NET 10: ```powershell python tools/vegetation/download.py npm ci --prefix tools/vegetation node --max-old-space-size=16384 tools/vegetation/prepare.mjs --source-only pine_tree_01 fir_tree_01 tree_small_02 fir_sapling_medium dotnet build src/Universe.App -c Release ./src/Universe.App/bin/Release/net10.0/Universe.App.exe --prepare-vegetation --bake-foliage node --max-old-space-size=16384 tools/vegetation/prepare.mjs dotnet build src/Universe.App -c Release ./src/Universe.App/bin/Release/net10.0/Universe.App.exe --prepare-vegetation --force dotnet build src/Universe.App -c Release ``` Importen använder glTF Transform och Meshoptimizer. Tungt barr-/lövverk bakas från full geometri till 24 rumsliga grupper med tre alphakort per grupp. Stammar och grenar behåller geometri. GLB-scenerna `LOD0`, `LOD1`, `LOD2` delar material. Startpaketets träd använder cirka 12 000 / 2 000 / 350 trianglar **per trädvariant**, under planens övre budget på 60 000 / 12 000 / 2 000. `preparation.json` redovisar summerade antal över alla varianter. Slutligen bakas 16 riktningar och tre elevationsvinklar per variant till impostorer med färg och normaler. Gräsets torra variant heter `dry.glb`. ## Färgregler `matchColorRgb` anger kartfärgen för placering, inte modellens färg. Avståndet är `100 * length(sRGB - target) / (255 * sqrt(3))`, med mjuk uttoning under toleransens yttersta 20 %. RGB-värden anges 0–255. Överlappande biomvikter normaliseras och används också av markshadern. Katalogens fyra biomer ligger i ordningen skog, torr mark, sand och snö. Varje växt anger `id`, `model`, `type` (`tree`, `shrub`, `grass`, `fern`), `matchColorRgb`, `colorTolerancePercent`, `spawnWeight`, `scaleRange`, `altitudeMeters`, `absoluteLatitudeDegrees`, `maxSlopeDegrees`, `minimumSpacingMeters`, `windStrength` och valfri `trunkCollision` med `radiusMeters` och `heightMeters`. Material och växtfärger kommer från GLB-filen. Arter väljs viktat inom respektive skikts täthetsbudget; fler arter ökar inte automatiskt antalet växter. Valfri `lodMeters` på en träddefinition ersätter planetens tre meshgränser. `distanceMeters` kan förkorta artens räckvidd. Planetens `depthPrepass` aktiverar ett extra djupsteg före terrängen. Det döljer dyr terrängskuggning bakom lövverk och låter endast de främsta löven få full ljusberäkning. Standard är av: mätningen på Jorden visade att steget kostade mer vegetationstid än det sparade i terrängen. Dess GPU-tid ingår i vegetationsbudgeten och redovisas också separat i debugpanelen när det aktiveras. Vatten, snö och olämplig höjd/lutning filtreras bort. Höjdintervall räknas från planetens referensradie, i projektets höjddata. Jordens globala höjdkarta har höga värden även över många gröna områden, så startkatalogen tillåter träd upp till 6 000 m. Det är ingen exakt karta över jordens verkliga skogar. ## Inställningar per planet Ange exempelvis i planetens JSON: ```json "vegetation": { "enabled": true, "densityMultiplier": 1, "allowedPlants": ["pine_tree_01", "fir_tree_01", "fern_02"], "affectGroundMaterials": true, "treeDensityPerHectare": 600, "shrubDensityPerHectare": 350, "groundDensityPerHectare": 20000, "forestScaleMeters": 450, "treeLodMeters": [40, 150, 400], "treeDistanceMeters": 2000, "shrubDistanceMeters": 150, "grassDistanceMeters": 80, "uploadBudgetMilliseconds": 1, "maximumCachedTiles": 2048, "maximumInstances": 650000, "shadowResolution": 2048, "shadowDistancesMeters": [100, 400], "shadowSoftness": 1, "shadowCascadeBlend": 0.2, "shadowBiasMeters": 0.035, "collisionDistanceMeters": 64 } ``` Utelämnad `allowedPlants` tillåter hela katalogen. Valfri `biomeTexture` anger en separat kartbild relativt `KnownSolarSystem/`; annars används `surfaceTexture`. Utan färgkarta används seedad proceduriell biomfördelning. Jorden är uttryckligen aktiverad. Atmosfäriska planeter av typen `terrestrial` får standardprofilen; andra fasta planeter kan aktiveras explicit. Gasplaneter tillåts inte. Proceduriella jordliknande planeter får också en standardprofil. Jordens startprofil använder `densityMultiplier: 0.7`, motsvarande nominellt 420 träd, 245 buskar och 14 000 markväxter per hektar före biom-, täthetsbrus- och terrängfiltrering. Sätt multiplikatorn till 1 för den tätare grundprofilen. Placeringarna bestäms av planet-ID, seed och fasta kubsfärsrutor, oberoende av terrängens LOD och planetens rotation. Trädrutor är cirka 256 m, buskrutor 128 m och markväxtrutor 32 m för att slippa generera stora mängder gräs långt bort. En begränsad arbetspool delas med terrängen. Inaktuella jobb avbryts. Resurs- och avståndsinstansdata laddas upp stegvis med den angivna tidsbudgeten; ett enskilt drivrutinsanrop kan inte avbrytas mitt i en uppladdning. Avståndsinstanser byggs i bakgrunden och använder två uppsättningar återanvända CPU-/GPU-buffertar. Terrängcachen behåller inaktiva rutor i upp till 60 sekunder, med en budget på 16 384 rutor per planet. De äldsta överflödiga rutorna frigörs stegvis, så korta utflykter till omloppsbana inte omedelbart tvingar fram samma terräng igen. Vegetationscachen följer spelarens position och täcker alla riktningar. En huvudvridning byter därför inte ut rutor eller startar nya vegetationsjobb. Standardgränsen är 2 048 rutor och fortfarande högst 650 000 instanser; detta behåller mer vegetation i minnet än den tidigare gränsen på 640 rutor. Små kameravridningar återanvänder instansbuffertarna med en konservativ marginal i synfältet. Skuggornas instanslistor uppdateras vid förflyttning eller nytt innehåll. Terrängrutor delar sin indextopologi och skriver vertexdata direkt till färdiga arrayer för att minska tillfälliga allokeringar. Detaljmaterial för avlägsna himlakroppar laddas först inom materialets synliga avstånd, så månens marktexturer inte läses in när man tittar runt på Jorden. Vind följer simulationstiden. Alphamippar bevarar täckningen. Träd växlar med dither mellan tre mesh-LOD och därefter flervyade impostorer. Två lokala skuggkaskader stöder upp till två solar. Vegetationen ritas före havet och kan därför speglas av befintlig SSR när den syns i scenbilden. FPS-spelaren sveps mot stamkapslar och glider längs dem; fri kamera, gräs, buskar och löv påverkas inte. Vegetationen ritas även före terrängen. Dess färdiga djupbild används för att undvika full terrängskuggning bakom stammar och löv, utan ett extra geometristeg. Separat `depthPrepass` är ett ytterligare, valfritt steg för lövens egen överlappning. ## Benchmark och felsökning Vegetationsskuggor filtreras med bilinära djupjämförelser på GPU:n. Marken använder ett viktat 5×5-filter med nio texturhämtningar; löv använder ett 3×3-filter med fyra hämtningar. Ingen slumpmässig sampling används. `shadowSoftness` (0–1) blandar mellan en bilinjär djupjämförelse och det mjuka filtret; standard är 1. `shadowCascadeBlend` (0–0,4, standard 0,2) anger hur stor del av närskuggans räckvidd som blandas med fjärrskuggan. `shadowBiasMeters` (0,001–0,25, standard 0,035) är djupmarginalen i meter och är oberoende av kaskadens räckvidd. Kartorna centreras på spelarens position och snäpps till texlar i dubbelprecision; att vrida huvudet flyttar inte kartorna. `Universe.App.exe --shadow-report` verifierar produktionsfiltret mot en separat CPU-referens, mjukare skuggkanter, löv, två solar och kontinuerliga kaskadövergångar. Testbilder sparas i `graphics-report/shadows/`. P-menyn innehåller **BENCHMARK FOREST**: omloppsvy, mjuk landning till 1,8 m, promenad, skogsbryn och uppstigning. Därefter återställs Jordvyn. Resultat med FPS-graf samt CSV/JSON sparas i `benchmark-results/forest-*` bredvid appen. Debugpanelen visar vegetation, vegetationsskuggor, CPU-/uppladdningstid, inskickade instanser/trianglar, LOD och väntande rutor. `Universe.App.exe --lookaround-report` står still i skogen på Jorden och mäter en stillastående vy följd av två hela kameravarv i 1440 × 900. Efter uppvärmningen sparas bildrutetider, vegetationsgenerering, cacheändringar, terränguppladdningar, minnesallokeringar och GC-räkningar i `graphics-report/lookaround/`. GPU:n synkroniseras per bildruta. Lägg till `--profile-passes` för att lokalisera långsamma pass; den extra synkroniseringen påverkar då tiderna. `Universe.App.exe --vegetation-report` kör samma rutt i 2560 × 1440 utan VSync, med vegetation av/på och kall/varm vegetationscache. Initial modell-/texturinläsning samt uppvärmning av shaders och terräng sker före mätningen. Kall körning tömmer vegetationsrutorna och deras instansbuffertar; varm körning återanvänder dem från föregående resa. Rapporten synkroniserar GPU:n per bildruta och sparar bilder, FPS-grafer, bildrutetider, statistik och PASS/FAIL i `graphics-report/vegetation/`. `--preview-only` avslutar efter bildkontrollen. Gränserna är 60 FPS i medel, 55 FPS i 1 %-låg, högst 50 ms och vegetation inklusive skuggor högst 5 ms vid 99:e percentilen. Hela scenens kostnad ingår i FPS; rapporten visar missade gränser i stället för att dölja dem. Senaste kontrollen på RTX 5080, 2560 × 1440 och Jordens starttäthet 0,7: | Vegetationscache | Medel-FPS | 1 %-låg FPS | Max bildruta | Vegetation + skuggor, GPU p99 | | --- | ---: | ---: | ---: | ---: | | Kall | 102,7 | 56,5 | 19,03 ms | 4,23 ms | | Varm | 99,2 | 48,1 | 23,11 ms | 4,23 ms | Varm körning klarar ännu inte gränsen 55 FPS för 1 %-låg; hela prestandamatrisen rapporteras därför som FAIL. Medel-FPS, vegetationsbudgeten och gränsen 50 ms klaras. Mätvärden varierar med vy och belastning. Grafikrapporten kontrollerar också två solar, giltiga OpenGL-resultat och minst 99 % närliggande yttäckning i djupbilden under spelarens fötter efter en orbital resa; senaste kontrollen gav 100 % täckning.