mirror of
https://github.com/sal063/AC6_recomp
synced 2026-09-02 02:12:34 -04:00
Fix lines on open waters seen at an acute angle (undefined shader derivatives)
The water shader's wave-normal lookup sits inside control flow this translator generates from the guest's predication and jumps, where DXBC derivatives are undefined: the gradient collapses to zero along the ocean mesh's seams, the LOD clamps to the finest mip, and grazing Fresnel amplifies that into a bright line. Computing the gradients in the prologue, where the quad is uniform, restores them.
This commit is contained in:
+20
-4
@@ -18,6 +18,7 @@ REXCVAR_DECLARE(std::string, ac6_neutralize_deswizzle_hashes);
|
||||
REXCVAR_DECLARE(std::string, ac6_snap_guest_texel_hashes);
|
||||
REXCVAR_DECLARE(std::string, ac6_densify_x_fetch_hashes);
|
||||
REXCVAR_DECLARE(std::string, ac6_densify_y_fetch_hashes);
|
||||
REXCVAR_DECLARE(std::string, ac6_fix_hoisted_fetch_gradients_hashes);
|
||||
REXCVAR_DECLARE(bool, param_gen_integer_guest_position);
|
||||
REXCVAR_DECLARE(bool, param_gen_host_subpixel_restore);
|
||||
REXCVAR_DECLARE(std::string, log_level);
|
||||
@@ -59,6 +60,9 @@ REXCVAR_DEFINE_BOOL(ac6_fix_dof, true, "AC6/Fixes",
|
||||
"Fix cutscene depth-of-field striping and ghosting at resolution "
|
||||
"scale above 1x.")
|
||||
.lifecycle(rex::cvar::Lifecycle::kRequiresRestart);
|
||||
REXCVAR_DEFINE_BOOL(ac6_fix_water_line, true, "AC6/Fixes",
|
||||
"Fix the thin bright lines across open water.")
|
||||
.lifecycle(rex::cvar::Lifecycle::kRequiresRestart);
|
||||
|
||||
#include "generated/ac6recomp_config.h"
|
||||
#include "generated/ac6recomp_init.h"
|
||||
@@ -192,6 +196,16 @@ void ApplyAc6FixDefaults() {
|
||||
rex::cvar::SetSessionDefault("ac6_densify_y_fetch_hashes", "5bd20f9d0d911687",
|
||||
"ac6_fix_dof");
|
||||
}
|
||||
// Water pixel shader, interpolator 4 - the wave-normal UVs. Its fetches sit
|
||||
// inside translated guest control flow, where DXBC derivatives are undefined,
|
||||
// so the gradient collapses at the ocean mesh's seams and the lookup clamps
|
||||
// to the finest mip. Hoisting the gradients to the prologue restores what the
|
||||
// console computes. Not gated on draw scale: the seams are in the game's own
|
||||
// vertex data, so this bites at 1x too.
|
||||
if (REXCVAR_GET(ac6_fix_water_line)) {
|
||||
rex::cvar::SetSessionDefault("ac6_fix_hoisted_fetch_gradients_hashes",
|
||||
"35a80cb48a481624:4", "ac6_fix_water_line");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -227,16 +241,18 @@ void ApplyAc6PerformanceModeOverridesPublic() {
|
||||
void LogAc6ConfigPresetSummary() {
|
||||
REXLOG_ERROR("AC6 config: graphics mode={} capture={}", REXCVAR_GET(ac6_graphics_mode),
|
||||
REXCVAR_GET(ac6_render_capture) ? "true" : "false");
|
||||
REXLOG_ERROR("AC6 fixes: scaling={} deswizzle={} dof={} perf_mode={} unlock_fps={}",
|
||||
REXLOG_ERROR("AC6 fixes: scaling={} deswizzle={} dof={} water_line={} perf_mode={} "
|
||||
"unlock_fps={}",
|
||||
REXCVAR_GET(ac6_fix_scaling), REXCVAR_GET(ac6_fix_deswizzle),
|
||||
REXCVAR_GET(ac6_fix_dof), REXCVAR_GET(ac6_performance_mode),
|
||||
REXCVAR_GET(ac6_unlock_fps));
|
||||
REXCVAR_GET(ac6_fix_dof), REXCVAR_GET(ac6_fix_water_line),
|
||||
REXCVAR_GET(ac6_performance_mode), REXCVAR_GET(ac6_unlock_fps));
|
||||
REXLOG_ERROR("AC6 fix payloads: neutralize='{}' snap='{}' densify_x='{}' densify_y='{}' "
|
||||
"param_gen={}/{}",
|
||||
"hoisted_gradients='{}' param_gen={}/{}",
|
||||
REXCVAR_GET(ac6_neutralize_deswizzle_hashes),
|
||||
REXCVAR_GET(ac6_snap_guest_texel_hashes),
|
||||
REXCVAR_GET(ac6_densify_x_fetch_hashes),
|
||||
REXCVAR_GET(ac6_densify_y_fetch_hashes),
|
||||
REXCVAR_GET(ac6_fix_hoisted_fetch_gradients_hashes),
|
||||
REXCVAR_GET(param_gen_integer_guest_position),
|
||||
REXCVAR_GET(param_gen_host_subpixel_restore));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user