Both OP4 reviews converged on one headline bug (Character-tab rows never re-read live server truth after their pre-login constructor-word seed) plus overlapping MUST-FIXes. All ten converged/consolidated findings land here: MUST-FIX: - BoolOptionRow.SaveCurrentValue now re-reads its live binding (retail's GetValue()-into-SaveCurrentValue) on every OnShown — panel open, tab switch in, initial activation — instead of trusting the pre-login constructor word it was built with. Reset/tab-switch can now only restore values that were actually live at the last show. LockUI's host.Root.UiLocked one-shot mount seed now also converges on every PlayerDescription via the existing OnCharacterOptionsChanged hook. - Apply/Reset are wired to OptionPage.OnOptionChanged in production (Ghosted when nothing changed, Normal when dirty, run once at bind so both start disabled per retail's PostInit); Defaults stays ungated. - The Combat panel's three LEDs (Repeat Attacks/Auto Target/Keep in View) now read/write the same RuntimeCharacterOptionsState seam the Character tab uses instead of a disconnected client-local GameplaySettings copy — closes the "two writable copies" divergence. The three now-orphaned GameplaySettings fields and RuntimeSettingsController's mirror properties/SetCombatGameplay are deleted outright; the headless host's hardcoded AutoRepeatAttack/AutoTarget now read the live option bit. - RuntimeSettingsController.SetUiLocked's convergence guard now compares against the last value actually applied to the runtime target instead of the persisted GameplaySettings.LockUI snapshot, which could already match a server-derived request without ever having been pushed. SHOULD-FIX: - DisplayTimeStamps now prefixes every chat producer (ChatLog.Append is the one seam all of them funnel through), not just AddText's own callers — heard speech, emotes, Turbine channels, and combat text were previously missed. The prefix format escapes its colons and forces InvariantCulture instead of the culture-dependent TimeSeparator placeholder. - sky.frag now honors uFogParams.w (fog mode) like the mesh/terrain shaders, so Disable Distance Fog stops the sky dome's horizon band from blending toward fog color too. - Corrected the "byte-verified" overclaim on the timestamp format string doc comment (BN-sourced, wire doc U6) and the AP-194 anchor-column class-name typo; the RunAsDefaultMovement doc comments now cite retail's actual acclient.h enumerator name. - Added: DispatcherMovementInputSource's option x modifier truth table (incl. || AutoRunActive with the option off), the per-page Apply/Reset enable-gate tests, a real checkbox.OnClick/ToggleBehavior-driven click test, and hash-pins for the six header string keys. - Gate script step 8 corrected for the logout-flush false-failure (closing the panel before relogging is load-bearing); a new step documents the enable-gate sequence and the Combat-panel/Character-tab cross-check. Register: AP-196 (the Group-C default-source change + GameplaySettings retirement) and AP-197 (the ignored per-character timestamp format override) filed in this commit. Full Release suite: 13,044 passed / 4 skipped / 0 failed (was 13,008/4/0; net +36 tests from new coverage and legitimate assertion updates from the GameplaySettings retirement). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
84 lines
3 KiB
GLSL
84 lines
3 KiB
GLSL
#version 430 core
|
|
#extension GL_ARB_bindless_texture : require
|
|
|
|
in vec2 vTex;
|
|
in vec3 vTint;
|
|
in float vFogFactor; // 1 = no fog, 0 = full fog color
|
|
out vec4 fragColor;
|
|
|
|
// Campaign V slice V6e: the sky's texture is now read through the shared table
|
|
// (ACDREAM_SAMPLE_2D, injected by tools/ShaderCompiler/VulkanGlslPreamble.cs)
|
|
// rather than a `uniform sampler2D` bound to texture unit 0. Vulkan has no
|
|
// default uniform block to declare a loose sampler in, and set 2 is where
|
|
// every sampled texture lives.
|
|
//
|
|
// The wrap mode travels WITH the slot: SkyRenderer registers a distinct table
|
|
// entry per (texture, sampler) pair, so the per-submesh Repeat-vs-ClampToEdge
|
|
// choice that used to be a glBindSampler call is now which slot it asks for.
|
|
// That is the same shape the Vulkan table has, where a table entry is a
|
|
// combined image sampler.
|
|
uniform uint uTextureIndexA;
|
|
|
|
// The per-draw block sky.vert declares. A uniform block must be declared
|
|
// identically in every stage of a program that names it — the same rule the
|
|
// SceneLighting block below has always followed — so the whole thing appears
|
|
// here even though the fragment stage reads only the last three scalars.
|
|
layout(std140, ACDREAM_UBO_SET binding = 4) uniform SkyParams {
|
|
mat4 uModel;
|
|
mat4 uSkyView;
|
|
mat4 uSkyProjection;
|
|
vec3 uAmbientColor;
|
|
float uEmissive;
|
|
vec3 uSunColor;
|
|
float uDiffuseFactor;
|
|
vec3 uSunDir;
|
|
float uTransparency;
|
|
vec2 uUvScroll;
|
|
float uApplyFog;
|
|
float uSurfOpacity;
|
|
};
|
|
|
|
struct Light {
|
|
vec4 posAndKind;
|
|
vec4 dirAndRange;
|
|
vec4 colorAndIntensity;
|
|
vec4 coneAngleEtc;
|
|
};
|
|
layout(std140, ACDREAM_UBO_SET binding = 1) uniform SceneLighting {
|
|
Light uLights[8];
|
|
vec4 uCellAmbient;
|
|
vec4 uFogParams;
|
|
vec4 uFogColor;
|
|
vec4 uCameraAndTime;
|
|
};
|
|
|
|
void main() {
|
|
vec4 sampled = ACDREAM_SAMPLE_2D(uTextureIndexA, vTex);
|
|
|
|
vec3 rgb = sampled.rgb * vTint;
|
|
|
|
// SHOULD-FIX S2/mech NOTE N-3 (OP4 review-fix round, 2026-08-11):
|
|
// PlayerOption DisableDistanceFog forces FogMode.Off (uFogParams.w
|
|
// == 0) — mesh_modern.frag/terrain_modern.frag both gate their own
|
|
// fog blend on this same word (`if (mode == 0) return lit;`), but the
|
|
// sky dome's blend here read only uApplyFog (the CPU per-submesh
|
|
// "is this layer foggable at all" flag) and never uFogParams.w, so
|
|
// toggling the option stopped terrain/objects fading into fog while
|
|
// the dome's horizon band kept blending toward fog color.
|
|
int fogMode = int(uFogParams.w);
|
|
if (uApplyFog > 0.5 && fogMode != 0) {
|
|
const float SKY_FOG_FLOOR = 0.2;
|
|
float skyFogFactor = max(vFogFactor, SKY_FOG_FLOOR);
|
|
rgb = mix(uFogColor.rgb, rgb, skyFogFactor);
|
|
}
|
|
|
|
float flash = uFogParams.z;
|
|
rgb += flash * vec3(1.5, 1.5, 1.8);
|
|
|
|
float cap = mix(1.0, 3.0, clamp(flash, 0.0, 1.0));
|
|
rgb = min(rgb, vec3(cap));
|
|
|
|
float a = sampled.a * (1.0 - uTransparency) * uSurfOpacity;
|
|
if (a < 0.01) discard;
|
|
fragColor = vec4(rgb, a);
|
|
}
|