standalone: speed round 2 -- far biome colour grid (payload -365 ms), whole view 1.90 s @8w full payload

- Per-vertex biome lookup was the payload cost (~365 ms); far tiles now take the biome palette from a
  per-tile grid. Same channels (palette, slope, border blend, UV) and ceiling/ground sections.
- Opt-in --max-clip-level=8: 6,498 -> 2,226 tiles, stream 0.876 -> 0.428 s, 1.451 s process wall.
  Kept opt-in: six fixed views cannot prove every distant thin stratum survives.
- W1/W8 hashes equal across 11 outputs; routes 5642/5642; five captures pixel-identical, passage
  382 px differ (max delta 16).
- Rejected with measurements: LOD6 empty-block proof (-21% samples, no wall gain), far supertiles
  (no complete groups exist).
Remaining long pole: shape compile 0.854 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-04 15:21:19 +02:00
1 parent 6ec4a8f856
commit a3cb26b5c8
5 files changed
+212 -18

No files matched your search

@@ -113,6 +113,9 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
if (OutDensitySampleCount) { *OutDensitySampleCount = 0; }
if (OutDebugDensitySamples) { OutDebugDensitySamples->clear(); }
if (!Generator) return MeshData;
const bool bEmitUV = !bStandaloneSkipUvAndColors && !bStandaloneSkipUV;
const bool bEmitColors = !bStandaloneSkipUvAndColors && !bStandaloneSkipColors;
const bool bUseCoarseFarBiomeGrid = Step >= 64;
VoxelDensityProfile::FScopedTimer MesherProfileTimer(
VoxelDensityProfile::EBucket::MesherGenerateMesh);
VoxelDensityProfile::FScopedTimer MesherSetupTimer(
@@ -166,6 +169,49 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
SurfColMemo.Reset();
}
struct FBiomeGridSample
{
int32 Dominant = 0;
int32 Neighbor = 0;
float Blend = 0.0f;
};
struct FBiomeTileGridSamples
{
FBiomeGridSample Corners[4];
};
static thread_local TMap<int32, FBiomeTileGridSamples> BiomeTileGridMemo;
const int32 BiomeGridSpacing = bUseCoarseFarBiomeGrid
? FMath::Clamp(InCellsPerAxis, 2, CHUNK_SIZE) * Step : 1;
if (bUseCoarseFarBiomeGrid && bEmitColors)
{
BiomeTileGridMemo.Reset();
}
auto GetBiomeTileGridSamples = [&](int32 ChunkZ) -> FBiomeTileGridSamples
{
if (const FBiomeTileGridSamples* Existing = BiomeTileGridMemo.Find(ChunkZ))
{
return *Existing;
}
FBiomeTileGridSamples Samples;
const float SampleZ = static_cast<float>(ChunkZ * CHUNK_SIZE + CHUNK_SIZE / 2);
const int32 TileMaxX = OriginVoxels.X + BiomeGridSpacing;
const int32 TileMaxY = OriginVoxels.Y + BiomeGridSpacing;
Generator->GetBiomeMaterialAt(static_cast<float>(OriginVoxels.X),
static_cast<float>(OriginVoxels.Y), SampleZ,
Samples.Corners[0].Dominant, Samples.Corners[0].Neighbor, Samples.Corners[0].Blend);
Generator->GetBiomeMaterialAt(static_cast<float>(TileMaxX),
static_cast<float>(OriginVoxels.Y), SampleZ,
Samples.Corners[1].Dominant, Samples.Corners[1].Neighbor, Samples.Corners[1].Blend);
Generator->GetBiomeMaterialAt(static_cast<float>(OriginVoxels.X),
static_cast<float>(TileMaxY), SampleZ,
Samples.Corners[2].Dominant, Samples.Corners[2].Neighbor, Samples.Corners[2].Blend);
Generator->GetBiomeMaterialAt(static_cast<float>(TileMaxX),
static_cast<float>(TileMaxY), SampleZ,
Samples.Corners[3].Dominant, Samples.Corners[3].Neighbor, Samples.Corners[3].Blend);
return BiomeTileGridMemo.Add(ChunkZ, Samples);
};
// Normale fournie par l'appelant (gradient lu dans la grille de densité, T1.b) —
// plus d'échantillonnage de densité par vertex. RawNormal pointe solide→air ; on la
// normalise ici (fallback up si dégénérée).
@@ -194,16 +240,56 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
}
MeshData.Normals.Add(Normal);
if (!bStandaloneSkipUvAndColors)
if (bEmitUV)
{
// UVs planaires — le triplanar mapping se fait dans le matériau.
MeshData.UVs.Add(FVector2f(WorldPos.X / VOXEL_SIZE, WorldPos.Y / VOXEL_SIZE));
}
if (bEmitColors)
{
//-----------------------------------------------------------------
// VERTEX COLOUR — masks for biome palette, slope and border blend.
int32 PalD = 0, PalN = 0; float BlendW = 0.0f;
Generator->GetBiomeMaterialAt(WorldPos.X / VOXEL_SIZE, WorldPos.Y / VOXEL_SIZE,
WorldPos.Z / VOXEL_SIZE, PalD, PalN, BlendW);
if (bUseCoarseFarBiomeGrid)
{
const float VoxelX = WorldPos.X / VOXEL_SIZE;
const float VoxelY = WorldPos.Y / VOXEL_SIZE;
const float VoxelZ = WorldPos.Z / VOXEL_SIZE;
const float TX = FMath::Clamp(
(VoxelX - static_cast<float>(OriginVoxels.X))
/ static_cast<float>(BiomeGridSpacing), 0.0f, 1.0f);
const float TY = FMath::Clamp(
(VoxelY - static_cast<float>(OriginVoxels.Y))
/ static_cast<float>(BiomeGridSpacing), 0.0f, 1.0f);
const int32 ChunkZ = FMath::FloorToInt(VoxelZ / static_cast<float>(CHUNK_SIZE));
const FBiomeTileGridSamples TileSamples = GetBiomeTileGridSamples(ChunkZ);
const FBiomeGridSample& S00 = TileSamples.Corners[0];
const FBiomeGridSample& S10 = TileSamples.Corners[1];
const FBiomeGridSample& S01 = TileSamples.Corners[2];
const FBiomeGridSample& S11 = TileSamples.Corners[3];
const FBiomeGridSample* Nearest = &S00;
if (TX >= 0.5f) Nearest = TY >= 0.5f ? &S11 : &S10;
else if (TY >= 0.5f) Nearest = &S01;
PalD = Nearest->Dominant;
PalN = Nearest->Neighbor;
BlendW = Nearest->Blend;
if (S00.Dominant == PalD && S00.Neighbor == PalN
&& S10.Dominant == PalD && S10.Neighbor == PalN
&& S01.Dominant == PalD && S01.Neighbor == PalN
&& S11.Dominant == PalD && S11.Neighbor == PalN)
{
const float B0 = FMath::Lerp(S00.Blend, S10.Blend, TX);
const float B1 = FMath::Lerp(S01.Blend, S11.Blend, TX);
BlendW = FMath::Lerp(B0, B1, TY);
}
}
else
{
Generator->GetBiomeMaterialAt(WorldPos.X / VOXEL_SIZE, WorldPos.Y / VOXEL_SIZE,
WorldPos.Z / VOXEL_SIZE, PalD, PalN, BlendW);
}
const uint8 R = (uint8)FMath::Clamp(PalD, 0, 255);
const uint8 A = (uint8)FMath::Clamp(PalN, 0, 255);
const uint8 G = (uint8)FMath::Clamp(FMath::RoundToInt((1.0f - FMath::Abs((float)Normal.Z)) * 255.0f), 0, 255);
@@ -1314,9 +1400,12 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
const int32 Idx = MeshData.Vertices.Num();
MeshData.Vertices.Add(Pos);
MeshData.Normals.Add(Nrm);
if (!bStandaloneSkipUvAndColors)
if (bEmitUV)
{
MeshData.UVs.Add(FVector2f(Pos.X / VOXEL_SIZE, Pos.Y / VOXEL_SIZE));
}
if (bEmitColors)
{
MeshData.Colors.Add(Col); // parallel with the other vertex arrays
}
return Idx;
@@ -1342,8 +1431,8 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
const FVector NA = MeshData.Normals[iA];
const FVector NB = MeshData.Normals[iB];
const FColor CA = bStandaloneSkipUvAndColors ? FColor::White : MeshData.Colors[iA];
const FColor CB = bStandaloneSkipUvAndColors ? FColor::White : MeshData.Colors[iB];
const FColor CA = bEmitColors ? MeshData.Colors[iA] : FColor::White;
const FColor CB = bEmitColors ? MeshData.Colors[iB] : FColor::White;
const int32 iA2 = AddSkirtVert(PA - NA * SkirtDepth, NA, CA);
const int32 iB2 = AddSkirtVert(PB - NB * SkirtDepth, NB, CB);