Skip to content

Commit 722edd7

Browse files
GWToolbox Botclaude
andcommitted
Route all in-world overlays through the shared occlude-behind-terrain setting
River, Weather and Loot Beacons each carried their own occlude_behind_terrain (River/LootBeacons as a user toggle, Weather as an always-on constant). Point them all at the "In-game rendering" module's GetOccludeBehindTerrain() (and the shared depth planes where they aren't entangled with other math), so terrain occlusion for every in-world overlay is configured in one place. Also stop asserting a specific depth mechanism in the Danger/Skill ring comments - the artifact is only reproduced with occlusion on; the exact depth-buffer interaction isn't verified here, so the comment now states just that, and the shared setting defaults off so the rings draw whole. Behaviour note: River and Weather occlusion previously defaulted on; they now follow the shared setting, which defaults off. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent fa34660 commit 722edd7

5 files changed

Lines changed: 27 additions & 24 deletions

File tree

GWToolboxdll/Modules/DangerRingsModule.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ namespace {
1818
constexpr int kSegments = 48;
1919
constexpr int kMaxBuildsPerFrame = 4; // draping QueryAltitude budget: ~200 queries per ring build
2020

21-
// Occlusion (whether the rings hide behind terrain, and the depth-projection planes it needs) is shared with
22-
// the "In-game rendering" module via GameWorldRenderer::GetOccludeBehindTerrain()/GetDepthZNear()/GetDepthZFar()
23-
// so it's configured in one place. It defaults off there: with occlusion on, the ring and the terrain it hugs
24-
// land at nearly-equal depths, and the depth-test tie is resolved by the compositor's reconstructed projection
25-
// vs GW's real one - a mismatch that grows non-linearly with distance, so arcs drop in/out as the camera moves.
21+
// Occlusion behind terrain (and the depth-projection planes it needs) is shared with the "In-game rendering"
22+
// module via GameWorldRenderer::GetOccludeBehindTerrain()/GetDepthZNear()/GetDepthZFar(), so it's configured in
23+
// one place. The incomplete-ring artifact (arcs that drop in/out with the camera) only occurs with occlusion
24+
// ON - it's an interaction between our depth test and GW's depth buffer - and this shared setting defaults off,
25+
// so rings draw whole by default.
2626
float render_max_distance = 5000.f;
2727
float fog_factor = 1.0f;
2828
float ring_thickness = 40.f;

GWToolboxdll/Modules/LootBeaconsModule.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,16 @@
1616
#include <Utils/SettingsRegistry.h>
1717
#include <Utils/TerrainDrape.h>
1818
#include <Utils/ToolboxUtils.h>
19+
#include <Widgets/Minimap/GameWorldRenderer.h>
1920

2021
namespace {
21-
constexpr float kZNear = 47.0f, kZFar = 100000.f; // must match GW's projection for occlusion to line up
2222
constexpr int kRingSegments = 32;
2323
constexpr float kRingBandWidth = 12.f;
2424
constexpr int kMaxBuildsPerFrame = 8; // draping QueryAltitude budget: ~70 queries per beacon build
2525
constexpr uint32_t kScanIntervalMs = 250; // item agents don't move; classification only needs a coarse tick
2626

27-
bool occlude_behind_terrain = true;
27+
// Occlusion behind terrain (and its depth-projection planes) is shared with the "In-game rendering" module
28+
// via GameWorldRenderer::GetOccludeBehindTerrain()/GetDepthZNear()/GetDepthZFar() so it's set in one place.
2829
float render_max_distance = 20000.f;
2930
float fog_factor = 0.5f;
3031
float beam_height = 225.f;
@@ -237,7 +238,9 @@ void LootBeaconsModule::DrawInWorld(IDirect3DDevice9* device)
237238

238239
IDirect3DStateBlock9* state_block = nullptr;
239240
if (device->CreateStateBlock(D3DSBT_ALL, &state_block) != D3D_OK) return;
240-
if (GameWorldCompositor::SetupPipeline(device, occlude_behind_terrain, kZNear, kZFar, render_max_distance, fog_factor)) {
241+
if (GameWorldCompositor::SetupPipeline(device, GameWorldRenderer::GetOccludeBehindTerrain(),
242+
GameWorldRenderer::GetDepthZNear(), GameWorldRenderer::GetDepthZFar(),
243+
render_max_distance, fog_factor)) {
241244
constexpr BOOL dotted_off[1] = {FALSE};
242245
device->SetPixelShaderConstantB(0, dotted_off, 1);
243246
device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, static_cast<UINT>(scratch.size() / 3), scratch.data(), sizeof(BeaconVertex));
@@ -248,7 +251,6 @@ void LootBeaconsModule::DrawInWorld(IDirect3DDevice9* device)
248251

249252
void LootBeaconsModule::RegisterSettings(ToolboxModule* module)
250253
{
251-
SettingsRegistry::RegisterField(module, "occlude_behind_terrain", &occlude_behind_terrain);
252254
SettingsRegistry::RegisterField(module, "render_max_distance", &render_max_distance);
253255
SettingsRegistry::RegisterField(module, "fog_factor", &fog_factor);
254256
SettingsRegistry::RegisterField(module, "beam_height", &beam_height);
@@ -321,7 +323,7 @@ void LootBeaconsModule::DrawSettingsInternal()
321323
ImGui::ShowHelp("Drawn dimmed. Off: only unreserved drops and drops assigned to you.");
322324

323325
ImGui::Separator();
324-
ImGui::Checkbox("Occlude behind terrain", &occlude_behind_terrain);
326+
ImGui::TextDisabled("Occlusion behind terrain follows the \"In-game rendering\" module's setting.");
325327
ImGui::DragFloat("Maximum render distance", &render_max_distance, 25.f, 10.f, 100000.f, "%.0f", ImGuiSliderFlags_AlwaysClamp);
326328
if (ImGui::DragFloat("Beam height", &beam_height, 5.f, 50.f, 5000.f, "%.0f", ImGuiSliderFlags_AlwaysClamp)) beacons_dirty = true;
327329
if (ImGui::DragFloat("Beam width", &beam_width, 1.f, 5.f, 500.f, "%.0f", ImGuiSliderFlags_AlwaysClamp)) beacons_dirty = true;

GWToolboxdll/Modules/RiverModule.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <Utils/GameWorldCompositor.h>
1515
#include <Utils/SettingsDoc.h>
1616
#include <Utils/SettingsRegistry.h>
17+
#include <Widgets/Minimap/GameWorldRenderer.h>
1718

1819
// Generated by CMake (fxc) from the .hlsl in the shared shaders dir.
1920
#include "Widgets/Minimap/Shaders/river_ps.h"
@@ -35,13 +36,13 @@ namespace lava_river_module {
3536
namespace {
3637
using namespace lava_river_module;
3738

38-
constexpr float kZNear = 47.0f, kZFar = 100000.f; // must match GW's projection for occlusion to line up
3939
constexpr float kSampleSpacing = 50.f; // resample a river centerline every ~50 gu (follow slopes)
4040
constexpr float kAltUnknown = 1e30f; // sentinel: no terrain data at this (x,y)
4141
constexpr size_t kMaxVertices = 1500000; // safety cap on total surface geometry per map (raise cell_size if hit)
4242

4343
// Settings (persisted scalars via SettingsRegistry; rivers persisted separately as JSON).
44-
bool occlude_behind_terrain = true;
44+
// Occlusion behind terrain (and its depth-projection planes) is shared with the "In-game rendering" module
45+
// via GameWorldRenderer::GetOccludeBehindTerrain()/GetDepthZNear()/GetDepthZFar() so it's set in one place.
4546
float render_max_distance = 5000.f;
4647
float fog_factor = 1.0f; // distance-fade strength fed to the shader
4748
float glow = 0.4f; // emissive brightness boost (0 = plain texture)
@@ -499,8 +500,8 @@ void RiverModule::DrawInWorld(IDirect3DDevice9* device)
499500

500501
IDirect3DStateBlock9* state_block = nullptr; // restored on exit so GW's own rendering isn't corrupted
501502
if (device->CreateStateBlock(D3DSBT_ALL, &state_block) != D3D_OK) return;
502-
if (device->SetVertexShader(lava_vs) == D3D_OK && device->SetPixelShader(lava_ps) == D3D_OK && device->SetVertexDeclaration(lava_decl) == D3D_OK && GameWorldCompositor::SetWorldViewProj(device, kZNear, kZFar)) {
503-
GameWorldCompositor::SetWorldRenderStates(device, occlude_behind_terrain);
503+
if (device->SetVertexShader(lava_vs) == D3D_OK && device->SetPixelShader(lava_ps) == D3D_OK && device->SetVertexDeclaration(lava_decl) == D3D_OK && GameWorldCompositor::SetWorldViewProj(device, GameWorldRenderer::GetDepthZNear(), GameWorldRenderer::GetDepthZFar())) {
504+
GameWorldCompositor::SetWorldRenderStates(device, GameWorldRenderer::GetOccludeBehindTerrain());
504505
GameWorldCompositor::SetDistanceFog(device, render_max_distance, fog_factor);
505506
const float wave_const[4] = {t_seconds, wave_amplitude * env, wave_scale, 0.f};
506507
device->SetVertexShaderConstantF(8, wave_const, 1);
@@ -527,7 +528,6 @@ void RiverModule::DrawInWorld(IDirect3DDevice9* device)
527528

528529
void RiverModule::RegisterSettings(ToolboxModule* module)
529530
{
530-
SettingsRegistry::RegisterField(module, "occlude_behind_terrain", &occlude_behind_terrain);
531531
SettingsRegistry::RegisterField(module, "render_max_distance", &render_max_distance);
532532
SettingsRegistry::RegisterField(module, "glow", &glow);
533533
SettingsRegistry::RegisterField(module, "flow_speed", &flow_speed);
@@ -589,7 +589,7 @@ void RiverModule::DrawSettings()
589589
}
590590
if (textures.empty()) ImGui::TextColored(red, "No texture selected - nothing will draw.");
591591

592-
ImGui::Checkbox("Occlude behind terrain", &occlude_behind_terrain);
592+
ImGui::TextDisabled("Occlusion behind terrain follows the \"In-game rendering\" module's setting.");
593593
ImGui::DragFloat("Maximum render distance", &render_max_distance, 5.f, 10.f, 100000.f, "%.0f", ImGuiSliderFlags_AlwaysClamp);
594594
ImGui::DragFloat("Glow", &glow, 0.02f, 0.f, 4.f, "%.2f", ImGuiSliderFlags_AlwaysClamp);
595595
ImGui::DragFloat("Flow speed", &flow_speed, 0.01f, -2.f, 2.f, "%.2f");

GWToolboxdll/Modules/SkillRangeRingsModule.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ namespace {
2222
constexpr float kMaxRingRadius = 5200.f; // ignore bogus range data past compass-ish sizes
2323
constexpr uint8_t kTargetNone = 0; // Skill.target == no_target (flash enchant / stance / self-cast form)
2424

25-
// Occlusion (whether the rings hide behind terrain, and the depth-projection planes it needs) is shared with
26-
// the "In-game rendering" module via GameWorldRenderer::GetOccludeBehindTerrain()/GetDepthZNear()/GetDepthZFar()
27-
// so it's configured in one place. It defaults off there: with occlusion on, the ring and the terrain it hugs
28-
// land at nearly-equal depths, and the depth-test tie is resolved by the compositor's reconstructed projection
29-
// vs GW's real one - a mismatch that grows non-linearly with distance, so arcs drop in/out as the camera moves.
25+
// Occlusion behind terrain (and the depth-projection planes it needs) is shared with the "In-game rendering"
26+
// module via GameWorldRenderer::GetOccludeBehindTerrain()/GetDepthZNear()/GetDepthZFar(), so it's configured in
27+
// one place. The incomplete-ring artifact (arcs that drop in/out with the camera) only occurs with occlusion
28+
// ON - it's an interaction between our depth test and GW's depth buffer - and this shared setting defaults off,
29+
// so rings draw whole by default.
3030
float render_max_distance = 7000.f;
3131
float fog_factor = 0.6f;
3232
float ring_thickness = 24.f;

GWToolboxdll/Modules/WeatherModule.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <Utils/SettingsDoc.h>
2626
#include <Utils/SettingsRegistry.h>
2727
#include <Utils/TextUtils.h>
28+
#include <Widgets/Minimap/GameWorldRenderer.h>
2829

2930
// Generated by CMake (fxc) from the .hlsl in the shared shaders dir.
3031
#include <GWCA/Context/MapContext.h>
@@ -230,8 +231,8 @@ namespace {
230231
}
231232
std::vector<ClimateProfile> climate_profiles = DefaultClimateProfiles();
232233

233-
// Fixed, not user-facing: weather always occludes behind terrain and renders to the compass range.
234-
constexpr bool occlude_behind_terrain = true;
234+
// Occlusion behind terrain follows the shared "In-game rendering" setting (GetOccludeBehindTerrain()) so it's
235+
// configured in one place with the other in-world overlays. render_max_distance stays fixed at the compass range.
235236
constexpr float render_max_distance = kMaxRadius;
236237
unsigned int ambient_color = 0xFFA09078u; // overcast tint of the condition currently driving the dimming (runtime)
237238
unsigned int active_tint = 0xFFFFFFFFu; // the active condition's particle tint, fed to the instanced draws (runtime)
@@ -1325,7 +1326,7 @@ void WeatherModule::DrawInWorld(IDirect3DDevice9* device)
13251326
IDirect3DStateBlock9* state_block = nullptr; // restored on exit so GW's own rendering isn't corrupted
13261327
if (device->CreateStateBlock(D3DSBT_ALL, &state_block) != D3D_OK) return;
13271328
if (device->SetPixelShader(weather_ps) == D3D_OK && GameWorldCompositor::SetWorldViewProj(device, kZNear, kZFar)) {
1328-
GameWorldCompositor::SetWorldRenderStates(device, occlude_behind_terrain);
1329+
GameWorldCompositor::SetWorldRenderStates(device, GameWorldRenderer::GetOccludeBehindTerrain());
13291330
GameWorldCompositor::SetDistanceFog(device, render_max_distance, fog_factor);
13301331
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
13311332
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

0 commit comments

Comments
 (0)