Files
WeirdUtils/ideas/ground-projected-raid-markers.md
T
MarcelineVQ 2aaa089c76 Add module control API, bigcursor with fractional scaling, shared mutex
Module control API:
- Three cdecl exports: WeirdUtils_IsModuleActive, WeirdUtils_DisableModule, WeirdUtils_DisableAll
- C header include/weirdutils_api.h for runtime DLL discovery
- All modules gain pub module_name, isActive(), shared mutex via src/mutex.zig
- build.zig refactored to module_list array of ModuleDesc

Bigcursor:
- D3D9 vtable hooks on SetCursorProperties/ShowCursor
- Scale2x/Scale3x pixel-art upscalers in pure Zig (replaces 12K-line hqx C)
- Bilinear resampler for fractional scales (1.0-4.0, default 1.2)
- Win32 cursor via CreateIconIndirect bypasses D3D9 32x32 limit
- FNV-1a hash cache for ~16 cursor bitmaps
- Lua API: SetCursorScale(n) / GetCursorScale()
- CVar cursorScale for Config.wtf persistence (tenths)

Other:
- Add dpslog module stub
- Docs and README updates
2026-03-06 13:27:35 -08:00

274 lines
8.0 KiB
Markdown

# Ground-Projected Raid Markers
**Goal:** Render placeable raid markers (like Wrath+) that project onto the ground as area indicators.
**Status:** Research complete, implementation pending
---
## What We Have
### D3D9 Rendering Infrastructure
- **File:** `src/outline/d3d9_hook.zig`
- Render target management (silhouette RT, JFA ping-pong buffers)
- Shader assembly via D3DX (PS 3.0)
- Fullscreen quad rendering with `DrawPrimitiveUP`
- Complete state save/restore around custom passes
- Hooks: EndScene, DrawIndexedPrimitive, Reset
### Model Rendering Hooks
- **File:** `src/outline/model_hook.zig`
- `CM2SceneRenderDraw` hook - batch reordering for depth control
- `CM2Scene_DrawBatchProjected` hook - per-batch interception
- Access to render context and model pointers
- Batch reordering ensures outline targets render when only terrain+WMO depth exists
### Render Pipeline Documentation
- **File:** `docs/RENDER_ARCHITECTURE.md`
- Terrain renderer: `CullAndProcessWorldChunks` (0x00683040)
- WMO renderer: `ProcessStaticObjectsCulling` (0x00683bf0)
- M2 model pipeline fully mapped
- Depth buffer control via hook ordering
### Outline Rendering Research
- **File:** `docs/outline-rendering-research.md`
- JFA (Jump Flood Algorithm) for distance-field outlines
- Stencil + blur techniques (Valve L4D style)
- Screen-space dilation approaches
- All SM 3.0 compatible
### UnitXP SP3 Reference
- **Path:** `/media/storage/projects/UnitXP_SP3_Orig/UnitXP_SP3/`
- **Key file:** `Vanilla1121_functions.h`
- `vanilla1121_worldToScreen(C3Vector& world)` - world → screen projection
- `CWorld_Intersect()` - raycast through world geometry
- `vanilla1121_unitPosition()` - unit world position
- `vanilla1121_getCameraPosition()` - camera world position
### WoWee Terrain Renderer Reference
- **Path:** `/media/storage/projects/WoWee/src/rendering/terrain_renderer.cpp`
- Modern OpenGL terrain rendering with multi-layer textures
- Frustum culling, LOD, shadow mapping
- Good reference for understanding terrain data structures
---
## What's Missing
### 1. Terrain Height Query
```c
// Need: Get terrain Z at world (X, Y)
float GetTerrainHeight(float worldX, float worldY);
```
**Options:**
- Reverse engineer WoW's internal terrain height function
- Use `CWorld_Intersect()` with vertical ray: `(x, y, +1000) → (x, y, -1000)`
- ADT tile parsing (complex, requires MPQ access)
### 2. Terrain Normal Query
```c
// Need: Get terrain normal at world (X, Y) for quad orientation
C3Vector GetTerrainNormal(float worldX, float worldY);
```
**Options:**
- Sample height at 4 neighboring points, compute normal
- Reverse engineer WoW's internal function
### 3. Depth Buffer as Texture (for projected decals)
```c
// Need: Access depth buffer as readable texture
IDirect3DTexture9* GetDepthAsTexture();
```
**D3D9 approaches:**
- `INTZ` / `RAWZ` format hack (requires driver support)
- `D3DFMT_D24S8` → `D3DFMT_D24X8` with `INTZ` fourcc
- Render depth to separate RT during terrain pass
- See: https://aras-p.info/texts/D3D9GPUHacks.html
---
## Implementation Options
### Option A: Screen-Space Marker (Simplest)
**Complexity:** Low
**Visual Quality:** Basic (icon on screen, no ground conformity)
**Implementation:**
1. Hook raid target array at `0x00B71368` (8 GUIDs)
2. Get marked unit's world position via `vanilla1121_unitPosition()`
3. Project to screen via `vanilla1121_worldToScreen()`
4. Draw icon sprite in EndScene at screen position
5. Optional: Depth test against terrain depth buffer
**Pros:**
- Minimal implementation
- Uses existing infrastructure
- No terrain queries needed
**Cons:**
- Marker doesn't conform to terrain
- Looks like a floating icon, not ground projection
- No "area on the ground" effect
---
### Option B: Projected Ground Decal (Recommended)
**Complexity:** Medium
**Visual Quality:** Good (conforms to terrain, area indicator)
**Implementation:**
1. Store marker world positions (from raid target array or click events)
2. In EndScene, after terrain+WMO depth written:
3. For each active marker:
- Bind depth buffer as texture (INTZ hack or separate RT)
- Render fullscreen quad with decal shader
- Shader reconstructs world position from depth
- If within marker radius, output marker color/texture
- Distance fade at edges for soft boundary
**Decal Shader (HLSL SM 3.0):**
```hlsl
// Uniforms set by CPU
float3 MarkerCenter; // World position
float MarkerRadius; // In world units
float4 MarkerColor; // RGBA
float2 ScreenSize; // For UV calculation
// Depth buffer bound to s0
sampler2D DepthSampler : register(s0);
float4 DecalPS(float2 uv : TEXCOORD0) : COLOR
{
// Read depth, reconstruct world position
float depth = tex2D(DepthSampler, uv).r;
float3 worldPos = ReconstructWorldPosition(uv, depth);
// Distance from marker center (XZ plane)
float2 offset = worldPos.xz - MarkerCenter.xz;
float dist = length(offset);
// Soft falloff
float alpha = saturate(1.0 - (dist / MarkerRadius));
alpha = smoothstep(0.0, 0.3, alpha); // Soft edge
// Output
return float4(MarkerColor.rgb, MarkerColor.a * alpha);
}
```
**Pros:**
- Conforms to terrain contours
- Looks like ground projection
- Can support multiple markers
- Soft edges for aesthetic
**Cons:**
- Requires depth buffer access (driver-dependent)
- More complex shader setup
- Per-marker render pass overhead
---
### Option C: World-Space Quad (Best Conformity)
**Complexity:** High
**Visual Quality:** Best (actual geometry on terrain)
**Implementation:**
1. Create marker quad mesh (4 vertices, 2 triangles)
2. Hook `CM2SceneRenderDraw` to inject custom geometry
3. For each marker:
- Query terrain height at marker position
- Query terrain normal for orientation
- Position quad at terrain height, orient to normal
- Add to render batch with marker texture
4. Render as part of M2 batch with depth testing
**Pros:**
- Perfect terrain conformity
- Actual geometry, not shader trick
- Proper depth testing with other objects
**Cons:**
- Requires terrain height/normal queries
- More complex geometry management
- Hook injection into render pipeline
---
## Recommended Path
### Phase 1: Proof of Concept (Screen-Space)
1. Implement basic screen-space marker rendering
2. Hook raid target array, project positions
3. Draw simple circle/icon at screen position
4. Verify hook integration works
**Estimated effort:** 1-2 hours
### Phase 2: Ground Decal (Primary Target)
1. Implement INTZ depth texture hack
2. Write decal projection shader
3. Add marker position storage
4. Render projected circles on terrain
**Estimated effort:** 4-6 hours
### Phase 3: Polish
1. Add marker textures (skull, cross, square, etc.)
2. Soft edge falloff
3. Multiple marker colors
4. Optional: Click-to-place interface
**Estimated effort:** 2-3 hours
---
## Key Files to Create/Modify
### New Files
```
src/marker/
├── marker_tracker.zig # Track active markers, positions
├── marker_decal.zig # Decal rendering shader + pipeline
├── marker_hooks.zig # Raid target array hooks
└── marker_types.zig # Data structures
```
### Modified Files
```
src/outline/d3d9_hook.zig # Add depth texture creation
src/outline/types.zig # Add depth texture format constants
src/main.zig # Initialize marker system
```
---
## External References
### D3D9 Depth Buffer Hacks
- https://aras-p.info/texts/D3D9GPUHacks.html
- INTZ / RAWZ format for reading depth as texture
### Decal Rendering Techniques
- Valve L4D Glow Effect (stencil + blur): https://developer.valvesoftware.com/wiki/L4D_Glow_Effect
- Unreal Engine deferred decals: https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/DeferredRendering/
### WoW 1.12.1 Internals
- wowdev.wiki for ADT terrain format
- UnitXP_SP3 for function signatures and calling conventions
---
## Notes
- Raid markers in Wrath+ use ground-projected circles with icon in center
- Our outline system already has the render target / shader infrastructure
- Depth buffer access is the main technical challenge for Option B
- Option A is good for quick testing, Option B is the production target