fix(render): #226 detail overlay uses retail's single-pass combine; drop the dead distance fade (Campaign VM VM1)
VM2's live cdb read against the PDB-paired retail client (GUID 9e847e2f-777c-4bd9-886c-22256bb87f32) proved m_caps.bCanDoSinglePassDetailing = 1 and trysinglepass = 1 on real hardware, so D3DPolyRender::RenderMeshSubset (0x0059ca10) never falls back to the two-pass framebuffer blend the earlier #226 port reproduced. Every loaded CGfxObj sets use_built_mesh = 1 (CGfxObj::InitLoad 0x005346b0), so buildings and EnvCells always take the single-pass texture-stage combine set up in D3DPolyRender::SetSurface (0x0059c4d0): result = lerp(base * diffuse, detail.rgb, detail.a * diffuse.a) RenderMeshSubset lights opaque built-mesh subsets with tmpmaterial.Diffuse.a = 1, so on the live Dereth category texture 0x06006D58 (mean rgb 0.165, mean alpha 0.132) the combine works out to ~0.868 * base + 0.022 — a mild darkening, the opposite sign of the fallback DstColor blend's brightening. Also removes the invented 10 m / 50 m distance fade. Retail's ACRender::get_alpha_for_z (0x006b6230) is only evaluated in D3DPolyRender::DrawPolyInternal (0x0059d7c0, the immediate-polygon path) and only when the static noFadeDetail (0x00820e38, initialised to 1) is 0 — unreachable for built meshes. Attenuation is the sampler's linear mip chain converging to the texture mean, not a scripted ramp. Changes: - mesh_detail.vert/.frag: drop vDetailFade and its distance term; add vDetailOpacity mirroring mesh_modern.vert's InstanceAlphaBuf (binding 7) read, and output detail.rgb with alpha = detail.a * vDetailOpacity under the corrected pipeline blend. - VulkanViewportMapping.BlendFactorsOf / GpuEnums.GpuBlendMode.RetailDetail: SrcAlpha + OneMinusSrcAlpha instead of DstColor + OneMinusSrcAlpha. - RetailDetailTextureContract: replaced the distance-fade constants and FramebufferFactor with Expected(base, detail, opacity) and IsNeutral, matching the lerp; contract tests cover zero-alpha/zero-opacity no-ops, the measured darkening on the live category texture, and full-alpha replacement. - Regenerated mesh_detail's committed SPIR-V and the shader manifest (tools/compile-shaders.ps1); no other shader pair changed. - Docs: #226's pseudocode note, the docs/ISSUES.md #226 entry, and the retired TS-52 divergence-register row corrected from the two-pass DESTCOLOR description to the single-pass path and the darkening expectation, each citing the VM2 cdb note. Verified: dotnet build AcDream.slnx -c Release (0 warnings, 0 errors); dotnet test on AcDream.App.Tests and AcDream.Core.Tests (Release, hermetic lanes) both green. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
30e72a2af8
commit
059703066f
13 changed files with 266 additions and 128 deletions
|
|
@ -137,10 +137,13 @@ internal enum GpuBlendMode
|
|||
InverseAlpha,
|
||||
|
||||
/// <summary>
|
||||
/// Retail building/EnvCell detail overlay:
|
||||
/// <c>DstColor, OneMinusSrcAlpha</c>. This intentionally preserves the
|
||||
/// retail client's measured brightening; it is not a conventional
|
||||
/// modulate/roughening blend.
|
||||
/// Retail building/EnvCell detail overlay: <c>SrcAlpha,
|
||||
/// OneMinusSrcAlpha</c>. VM2's live cdb read proved retail hardware runs
|
||||
/// the single-pass texture-stage combine (<c>D3DPolyRender::SetSurface</c>
|
||||
/// 0x0059c4d0), a lerp toward the detail colour by
|
||||
/// <c>detail.a * diffuse.a</c> — a mild darkening on the live Dereth
|
||||
/// category texture, not the two-pass <c>DstColor</c> fallback's
|
||||
/// brightening.
|
||||
/// </summary>
|
||||
RetailDetail,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,9 +175,12 @@ internal static class VulkanViewportMapping
|
|||
GpuBlendMode.Additive => (BlendFactor.SrcAlpha, BlendFactor.One),
|
||||
// Retail's third mode, found at slice V4c in WbDrawDispatcher.ApplyRetailBlend.
|
||||
GpuBlendMode.InverseAlpha => (BlendFactor.OneMinusSrcAlpha, BlendFactor.SrcAlpha),
|
||||
// ACRender::SetDetailSurfaceInternal with DrawBuilding/DrawEnvCell's
|
||||
// category state: D3DBLEND_DESTCOLOR + D3DBLEND_INVSRCALPHA.
|
||||
GpuBlendMode.RetailDetail => (BlendFactor.DstColor, BlendFactor.OneMinusSrcAlpha),
|
||||
// VM2 (live cdb read, 2026-08-22): real hardware runs the single-pass
|
||||
// texture-stage detail combine, not the two-pass DESTCOLOR fallback.
|
||||
// D3DPolyRender::SetSurface's stage-1 BLENDCURRENTALPHA is a lerp
|
||||
// toward the detail colour by detail.a * diffuse.a, which is the
|
||||
// ordinary straight-alpha-over factor pair.
|
||||
GpuBlendMode.RetailDetail => (BlendFactor.SrcAlpha, BlendFactor.OneMinusSrcAlpha),
|
||||
GpuBlendMode.None => (BlendFactor.One, BlendFactor.Zero),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(blend), blend, "Unknown blend mode."),
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue