Merge pull request #20 from Dipshet/fix-sunflare

Fix cull the sun-flare's spurious second billboard (flare "square")
This commit is contained in:
sal063
2026-07-08 21:00:08 +03:00
committed by GitHub
3 changed files with 40 additions and 0 deletions
+4
View File
@@ -39,6 +39,10 @@ REXCVAR_DECLARE(bool, readback_memexport_fast);
REXCVAR_DECLARE(bool, occlusion_query_enable);
REXCVAR_DECLARE(int32_t, query_occlusion_fake_sample_count);
// AC6 sun-flare "square" fix (drop the flare's spurious second billboard)
REXCVAR_DECLARE(bool, ac6_flare_drop_quad2);
REXCVAR_DECLARE(int32_t, ac6_flare_drop_index_min);
// GPU Depth / Render Target Behavior
REXCVAR_DECLARE(bool, depth_float24_round);
REXCVAR_DECLARE(bool, depth_float24_convert_in_pixel_shader);
+6
View File
@@ -65,6 +65,12 @@ REXCVAR_DEFINE_STRING(ac6_neutralize_deswizzle_hashes, "", "GPU/Shader",
"Xenos tfetch slot 4 (needed when only some fetches de-swizzle, e.g. "
"the AC6 cloud compositor: scene fetch de-swizzles, mask/cloud "
"fetches use plain UVs and must be left alone). Runtime, no rebuild.");
REXCVAR_DEFINE_BOOL(ac6_flare_drop_quad2, true, "GPU/Shader",
"AC6: cull the sun lens-flare's spurious second billboard "
"(vertices 4-7) to remove the faint rectangle in the sky");
REXCVAR_DEFINE_INT32(ac6_flare_drop_index_min, 4, "GPU/Shader",
"AC6: first vertex index of the flare draw to cull (the "
"spurious billboard is vertices 4-7 of 8)");
REXCVAR_DEFINE_BOOL(gpu_debug_markers, false, "GPU",
"Insert debug markers into GPU command streams for tools "
"like PIX and RenderDoc. Automatically enabled when "
@@ -18,6 +18,7 @@
#include <rex/assert.h>
#include <rex/cvar.h>
#include <rex/graphics/flags.h>
#include <rex/logging.h>
#include <rex/graphics/pipeline/shader/dxbc.h>
#include <rex/graphics/pipeline/shader/dxbc_translator.h>
@@ -1031,6 +1032,35 @@ void DxbcShaderTranslator::CompleteVertexOrDomainShader() {
}
}
// AC6 sun-flare "square" fix - drop the flare's second billboard
// This VS (ADF9AFC4C10921B9) emits two billboards per flare draw: V0-V3 =
// the visible glow quad, V4-V7 = a huge malformed quad (corners far
// off-screen, garbage UVs) that is invisible on real hardware but
// mis-renders in the emulator as a faint bright-edged rectangle. Cull it
// the same way as kill-vertex above: NaN the output position of vertices
// with index >= the threshold so the rasterizer discards the primitive.
// V0-V3 (the real glow) are untouched.
if (REXCVAR_GET(ac6_flare_drop_quad2) &&
current_shader().ucode_data_hash() == 0xADF9AFC4C10921B9ull &&
GetDxbcShaderModification().vertex.host_vertex_shader_type ==
Shader::HostVertexShaderType::kVertex) {
int32_t ac6_drop_index_min = REXCVAR_GET(ac6_flare_drop_index_min);
if (ac6_drop_index_min < 0) {
ac6_drop_index_min = 0;
}
uint32_t ac6_drop_temp = PushSystemTemp();
// ac6_drop_temp.x = (SV_VertexID >= index_min) ? 0xFFFFFFFF : 0
a_.OpUGE(dxbc::Dest::R(ac6_drop_temp, 0b0001),
dxbc::Src::V1D(kInRegisterVSVertexIndex, dxbc::Src::kXXXX),
dxbc::Src::LU(uint32_t(ac6_drop_index_min)));
// NaN the whole position of culled vertices.
a_.OpMovC(dxbc::Dest::R(system_temp_position_, 0b1111),
dxbc::Src::R(ac6_drop_temp, dxbc::Src::kXXXX),
dxbc::Src::LF(std::nanf("")), dxbc::Src::R(system_temp_position_));
// Release ac6_drop_temp.
PopSystemTemp();
}
// Write the position to the output.
a_.OpMov(dxbc::Dest::O(out_reg_vs_position_), dxbc::Src::R(system_temp_position_));