merge: A7 lighting Fix C (sun-vector brightness) + handoff into main
Brings Fix C (57c1135, sun-vector magnitude / ~32% over-bright) + the A7 lighting handoff doc onto main. Auto-merged clean against the D.2b line. Merged tree builds green; 18/18 sky tests pass. Fix A/B already on main (37911ed). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
4795a6c7f3
4 changed files with 187 additions and 56 deletions
|
|
@ -100,22 +100,23 @@ public sealed class SkyDescLoaderTests
|
|||
{
|
||||
// The loader stores DirColor and DirBright RAW. The SunColor property
|
||||
// composes them via |sunVec| per retail's UpdateLightsInternal at
|
||||
// 0x59b57c (decomp 424118) — the diffuse magnitude is sqrt(x²+y²+z²)
|
||||
// where the sun vector is built from heading/pitch/brightness with
|
||||
// Y unscaled by brightness (decomp 261352).
|
||||
// 0x59b57c (decomp 424118) — diffuse = DirColor × |LScape::sunlight|.
|
||||
// cdb-verified (reference-retail-ambient-values): |LScape::sunlight| ==
|
||||
// DirBright for every keyframe (world-space spherical vector, magnitude
|
||||
// DirBright·sqrt(cos²P+sin²P) = DirBright).
|
||||
//
|
||||
// For this region: H=180°, P=70°, B=1.5
|
||||
// sunVec = (sin(180)*1.5*cos(70), cos(70), 1.5*sin(70))
|
||||
// = (0, 0.342, 1.410)
|
||||
// |sunVec| = sqrt(0 + 0.117 + 1.988) = 1.4509
|
||||
// sunVec = 1.5 × (cos(70)·sin(180), cos(70)·cos(180), sin(70))
|
||||
// = (0, -0.513, 1.410)
|
||||
// |sunVec| = sqrt(0 + 0.263 + 1.988) = 1.500 (= DirBright)
|
||||
// DirColor.X = 200/255 = 0.7843
|
||||
// SunColor.X = 0.7843 × 1.4509 = 1.138
|
||||
// SunColor.X = 0.7843 × 1.500 = 1.1765
|
||||
var region = MakeRegion(dirBright: 1.5f, rBgrOrder: 200);
|
||||
var loaded = SkyDescLoader.LoadFromRegion(region);
|
||||
Assert.NotNull(loaded);
|
||||
|
||||
var kf = loaded!.DayGroups[0].SkyTimes[0].Keyframe;
|
||||
Assert.InRange(kf.SunColor.X, 1.13f, 1.15f);
|
||||
Assert.InRange(kf.SunColor.X, 1.17f, 1.18f);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -66,24 +66,33 @@ public sealed class SkyStateTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void RetailSunVector_AtHorizonNorth_MagnitudeIsOne()
|
||||
public void RetailSunVector_MagnitudeAlwaysEqualsDirBright()
|
||||
{
|
||||
// Sun on horizon to the north (H=0°, P=0°): cos(P)=1, sin(P)=0.
|
||||
// sunVec = (sin(0)×B×1, 1, B×0) = (0, 1, 0)
|
||||
// |sunVec| = 1 regardless of B (because Y is unscaled by B)
|
||||
var kf = new SkyKeyframe(
|
||||
Begin: 0f,
|
||||
SunHeadingDeg: 0f,
|
||||
SunPitchDeg: 0f,
|
||||
DirColor: Vector3.One,
|
||||
DirBright: 2.0f, // anything
|
||||
AmbColor: Vector3.One,
|
||||
AmbBright: 1f,
|
||||
FogColor: Vector3.One,
|
||||
FogDensity: 0f);
|
||||
// cdb-verified (2026-06-18, reference-retail-ambient-values): retail's
|
||||
// world-space LScape::sunlight = DirBright × (cosP·sinH, cosP·cosH, sinP),
|
||||
// whose magnitude is DirBright·sqrt(cos²P·(sin²H+cos²H)+sin²P) = DirBright
|
||||
// for ALL headings/pitches. (The prior y=cos(P) port gave |sunVec|≈1 at the
|
||||
// horizon — that was the ~30% over-bright bug.)
|
||||
// Horizon north (H=0°, P=0°): (0, B, 0), |.| = B.
|
||||
var horizon = new SkyKeyframe(
|
||||
Begin: 0f, SunHeadingDeg: 0f, SunPitchDeg: 0f,
|
||||
DirColor: Vector3.One, DirBright: 2.0f,
|
||||
AmbColor: Vector3.One, AmbBright: 1f,
|
||||
FogColor: Vector3.One, FogDensity: 0f);
|
||||
Assert.InRange(SkyStateProvider.RetailSunVector(horizon).Length(), 1.99f, 2.01f);
|
||||
|
||||
var v = SkyStateProvider.RetailSunVector(kf);
|
||||
Assert.InRange(v.Length(), 0.99f, 1.01f);
|
||||
// Reproduce the live cdb capture: dawn keyframe H=90°, P=0.9°, DirBright=0.224
|
||||
// → LScape::sunlight = (0.2238, ~0, 0.00352), magnitude 0.224 = DirBright.
|
||||
var dawn = new SkyKeyframe(
|
||||
Begin: 0f, SunHeadingDeg: 90f, SunPitchDeg: 0.9f,
|
||||
DirColor: Vector3.One, DirBright: 0.224f,
|
||||
AmbColor: Vector3.One, AmbBright: 0.40f,
|
||||
FogColor: Vector3.One, FogDensity: 0f);
|
||||
var v = SkyStateProvider.RetailSunVector(dawn);
|
||||
Assert.InRange(v.X, 0.223f, 0.225f); // DirBright·cosP·sin(90°) ≈ 0.224
|
||||
Assert.InRange(v.Y, -0.001f, 0.001f); // DirBright·cosP·cos(90°) ≈ 0 (was the bug: ≈1)
|
||||
Assert.InRange(v.Z, 0.003f, 0.004f); // DirBright·sin(0.9°) ≈ 0.0035
|
||||
Assert.InRange(v.Length(), 0.223f, 0.225f); // = DirBright
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue