standalone: rock detail restored in lattice-resolvable bands (4-16 voxels), owner-band gate added

- Relief per wavelength band compared with the owner field; the 4-8 and 8-16 voxel bands were lost.
  Restored within the partition-of-unity blend; max detail gradient 0.545 (limit 0.55).
- New owner-band gate: fails all six views on de14f00, passes all six now.
- W1/W8 44/44; path hash both directions; routes 5642/5642; stair-distance, ring, thin-sheet,
  coarse-panel, far-survival audits pass; bad-shell control fails.
- Cold 1.127 s vs 1.108 s (within spread); nearest-tile readiness 12.20 vs 12.16 ms.
Caveats: the 143-ray GridStair normal audit is at 62.2% vs its 60% limit (was 76.9%); in the tunnel
capture the floor shows a regular dimple pattern, and the passage shaft close-up is still smooth.

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-06 05:43:31 +02:00
1 parent de14f0042d
commit 566d1f342a
7 files changed
+575 -42

No files matched your search

+31 -20
View File
@@ -1307,7 +1307,7 @@ private:
// cave family's amplitude instead of multiplying both family contributions.
return 1.35f*StrataWeight+1.00f*CaveWeight+0.55f*FloorWeight;
}
static float BlendDetailFamilies(float Relief,float OwnerRelief,
static float BlendDetailFamilies(float Relief,float PassageBandRelief,float OwnerRelief,
float CaveInfluence,float FloorInfluence,float PassageInfluence)
{
const float Cave=std::clamp(CaveInfluence,0.0f,1.0f);
@@ -1320,7 +1320,9 @@ private:
const float StrataRelief=1.35f*(Relief+0.5f*OwnerRelief);
const float CaveRelief=1.00f*Relief;
const float FloorRelief=0.55f*Relief;
const float PassageRelief=0.75f*Relief;
// Passage walls keep the broad coherent relief bands but omit the shortest
// octave, which makes repeated rings on the authored shafts.
const float PassageRelief=0.75f*PassageBandRelief;
return StrataWeight*StrataRelief+CaveWeight*CaveRelief
+FloorWeight*FloorRelief+Passage*PassageRelief;
}
@@ -1348,8 +1350,8 @@ private:
OwnerBound=3.15f*VOXEL_NOISE_SCALE*Params.SurfaceRoughness*Fade*Fade;
}
}
const float ReliefBound=std::abs(MacroValue)
+(0.80f+0.25f*MacroValue)*(0.85f+0.18f);
const float ReliefBound=1.20f*std::abs(MacroValue)
+(0.80f+0.25f*MacroValue)*(0.40f+0.60f);
const float Contrast=DetailContrast(CaveInfluence,FloorInfluence);
const float LocalSupremum=std::min(3.9f,(ReliefBound+0.5f*OwnerBound)*Contrast);
return std::clamp(LocalSupremum+0.125f,DetailBandInnerRadius,DetailSupremum+0.125f);
@@ -3802,15 +3804,18 @@ private:
return (AnchoredWeight*Anchored+DirectWeight*Direct)*Normalization;
}
static float SurfaceRelief(float X,float Y,float Z,uint32 Seed)
static float SurfaceRelief(float X,float Y,float Z,uint32 Seed,
float* OutPassageBandRelief=nullptr)
{
// The low band carries the broad rock shapes and also gently varies mid-band
// amplitude. Keep the finest octave wider than a few marching-cubes cells so
// it does not alias into voxel-sized ledges on the full-detail surface.
// Keep all active bands at four voxels or wider: the full-detail lattice can
// resolve them without turning the surface into per-voxel steps. The broad
// owner comparison showed that the shortest octave needed more usable relief.
const float Macro=FStandaloneResearchTunnels::ValueNoise(X,Y,Z,32,Seed^0xB5297A4Du);
const float Mid=FStandaloneResearchTunnels::ValueNoise(X,Y,Z,16,Seed^0x63D83595u);
const float Fine=FStandaloneResearchTunnels::ValueNoise(X,Y,Z,6,Seed^0xA511E9B3u);
return 1.00f*Macro+(0.80f+0.25f*Macro)*(0.85f*Mid+0.18f*Fine);
const float Fine=FStandaloneResearchTunnels::ValueNoise(X,Y,Z,4,Seed^0xA511E9B3u);
if(OutPassageBandRelief)
*OutPassageBandRelief=1.20f*Macro+(0.80f+0.25f*Macro)*(0.40f*Mid);
return 1.20f*Macro+(0.80f+0.25f*Macro)*(0.40f*Mid+0.60f*Fine);
}
struct FValueNoiseLineContext
@@ -3872,16 +3877,20 @@ private:
FOwnerNoiseLineContext OwnerNoise;
FDetailNoiseLineContext(float X,float Y,uint32 Seed)
:Macro(X,Y,32,Seed^0xB5297A4Du),Mid(X,Y,16,Seed^0x63D83595u),
Fine(X,Y,6,Seed^0xA511E9B3u)
Fine(X,Y,4,Seed^0xA511E9B3u)
{}
float SurfaceReliefAt(float Z,bool bMacroKnown=false,float KnownMacro=0.0f)
float SurfaceReliefAt(float Z,bool bMacroKnown=false,float KnownMacro=0.0f,
float* OutPassageBandRelief=nullptr)
{
const float MacroValue=bMacroKnown?KnownMacro:Macro.Sample(Z);
const float MidValue=Mid.Sample(Z);
const float FineValue=Fine.Sample(Z);
return 1.00f*MacroValue+(0.80f+0.25f*MacroValue)
*(0.85f*MidValue+0.18f*FineValue);
if(OutPassageBandRelief)
*OutPassageBandRelief=1.20f*MacroValue
+(0.80f+0.25f*MacroValue)*(0.40f*MidValue);
return 1.20f*MacroValue+(0.80f+0.25f*MacroValue)
*(0.40f*MidValue+0.60f*FineValue);
}
};
@@ -3896,8 +3905,9 @@ private:
return FStandaloneResearchTunnels::NoiseValue(IX,IY,IZ,static_cast<uint32>(Owner->Seed))
*DetailSupremum;
}
float PassageBandRelief=0.0f;
const float Relief=SurfaceRelief(static_cast<float>(X),static_cast<float>(Y),
static_cast<float>(Z),static_cast<uint32>(Owner->Seed));
static_cast<float>(Z),static_cast<uint32>(Owner->Seed),&PassageBandRelief);
const float PassageWeight=std::clamp(PassageInfluence,0.0f,1.0f);
const FLayerField* Field=FindLayerField(Z);
FOwnerNoiseLineContext OwnerNoise;
@@ -3905,8 +3915,8 @@ private:
if(Field)
OwnerRelief=OwnerCaveRoughnessForDetail(X,Y,Z,SurfaceSDF,*Field,
CaveInfluence,PassageWeight,OwnerNoise);
const float Detail=std::clamp(BlendDetailFamilies(Relief,OwnerRelief,
CaveInfluence,FloorInfluence,PassageWeight),-3.9f,3.9f);
const float Detail=std::clamp(BlendDetailFamilies(Relief,PassageBandRelief,
OwnerRelief,CaveInfluence,FloorInfluence,PassageWeight),-3.9f,3.9f);
return Detail;
}
@@ -3922,8 +3932,9 @@ private:
return DetailNoise(X,Y,Z,SurfaceSDF,CaveInfluence,FloorInfluence,PassageInfluence);
using Clock=std::chrono::steady_clock;
const auto ReliefStart=Profile?Clock::now():Clock::time_point{};
float PassageBandRelief=0.0f;
const float Relief=NoiseLine.SurfaceReliefAt(static_cast<float>(Z),
bMacroKnown,KnownMacro);
bMacroKnown,KnownMacro,&PassageBandRelief);
if(Profile)
Profile->ReliefSampleNanoseconds+=static_cast<uint64>(
std::chrono::duration_cast<std::chrono::nanoseconds>(Clock::now()-ReliefStart).count());
@@ -3942,8 +3953,8 @@ private:
if(Profile)
Profile->OwnerRoughnessSampleNanoseconds+=static_cast<uint64>(
std::chrono::duration_cast<std::chrono::nanoseconds>(Clock::now()-OwnerStart).count());
const float Detail=std::clamp(BlendDetailFamilies(Relief,OwnerRelief,
CaveInfluence,FloorInfluence,PassageWeight),-3.9f,3.9f);
const float Detail=std::clamp(BlendDetailFamilies(Relief,PassageBandRelief,
OwnerRelief,CaveInfluence,FloorInfluence,PassageWeight),-3.9f,3.9f);
return Detail;
}