From bfbc7cf865f8aaf39d230b8d0842d0d0094ab72b Mon Sep 17 00:00:00 2001 From: jacob Date: Sat, 10 Jan 2026 06:46:30 -0600 Subject: [PATCH] wall auto-tiling experimentation --- src/base/base.cgh | 4 +- src/base/base_shader.gh | 49 +++++++-- src/pp/pp_sim/pp_sim_core.c | 6 +- src/pp/pp_sim/pp_sim_shared.cg | 12 +-- src/pp/pp_sim/pp_sim_shared.cgh | 9 +- src/pp/pp_vis/pp_vis_core.c | 27 ++++- src/pp/pp_vis/pp_vis_gpu.g | 183 ++++++++++++++++++-------------- src/pp/pp_vis/pp_vis_shared.cgh | 17 ++- 8 files changed, 194 insertions(+), 113 deletions(-) diff --git a/src/base/base.cgh b/src/base/base.cgh index bfdbb35e..1c4807b9 100644 --- a/src/base/base.cgh +++ b/src/base/base.cgh @@ -754,7 +754,7 @@ // Based on Jon Maiga's "mx3" // https://jonkagstrom.com/mx3/mx3_rev2.html -u64 MixU64(u64 seed) +Inline u64 MixU64(u64 seed) { seed = (seed ^ (seed >> 32)) * 0xbea225f9eb34556d; seed = (seed ^ (seed >> 29)) * 0xbea225f9eb34556d; @@ -763,7 +763,7 @@ u64 MixU64(u64 seed) return seed; } -u64 MixU64s(u64 seed_a, u64 seed_b) +Inline u64 MixU64s(u64 seed_a, u64 seed_b) { return MixU64((seed_a * 3) + seed_b); } diff --git a/src/base/base_shader.gh b/src/base/base_shader.gh index 90453762..ffccf45e 100644 --- a/src/base/base_shader.gh +++ b/src/base/base_shader.gh @@ -76,6 +76,39 @@ u32 countof(T arr[N]) #define ClampI64(...) clamp(__VA_ARGS__) #define ClampF64(...) clamp(__VA_ARGS__) +#define MatchFloor(a, b) all(floor(a) == floor(b)) + +//////////////////////////////////////////////////////////// +//~ Float ops + +//- Round +#define RoundF32(v) round(v) +#define RoundF64(v) round(v) + +//- Floor +#define FloorF32(v) floor(v) +#define FloorF64(v) floor(v) + +//- Ceil +#define CeilF32(v) ceil(v) +#define CeilF64(v) ceil(v) + +//- Trunc +#define TruncF32(v) trunc(v) +#define TruncF64(v) trunc(v) + +//- Mod +#define ModF32(v, m) fmod((v), (m)) +#define ModF64(v, m) fmod((v), (m)) + +//- Abs +#define AbsF32(v) abs(v) +#define AbsF64(v) abs(v) + +//- Sign +#define SignF32(v) sign(v) +#define SignF64(v) sign(v) + //////////////////////////////////////////////////////////// //~ Derivative helpers @@ -84,7 +117,7 @@ u32 countof(T arr[N]) //////////////////////////////////////////////////////////// //~ Color helpers -Vec4 Vec4FromU32(u32 v) +Inline Vec4 Vec4FromU32(u32 v) { Vec4 result = 0; result.x = ((v >> 0) & 0xFF) / 255.0; @@ -94,7 +127,7 @@ Vec4 Vec4FromU32(u32 v) return result; } -u32 U32FromVec4(Vec4 v) +Inline u32 U32FromVec4(Vec4 v) { u32 result = 0; result |= (((u32)(v.x * 255.0)) & 0xFF) << 0; @@ -104,7 +137,7 @@ u32 U32FromVec4(Vec4 v) return result; } -f32 LinearFromSrgbF32(f32 srgb) +Inline f32 LinearFromSrgbF32(f32 srgb) { f32 result; if (srgb <= 0.04045f) @@ -118,7 +151,7 @@ f32 LinearFromSrgbF32(f32 srgb) return result; } -Vec4 LinearFromSrgb(Vec4 srgb) +Inline Vec4 LinearFromSrgb(Vec4 srgb) { Vec4 result; result.x = LinearFromSrgbF32(srgb.x); @@ -128,7 +161,7 @@ Vec4 LinearFromSrgb(Vec4 srgb) return result; } -Vec4 Premul(Vec4 v) +Inline Vec4 Premul(Vec4 v) { Vec4 result; result.rgb = v.rgb * v.a; @@ -139,7 +172,7 @@ Vec4 Premul(Vec4 v) //////////////////////////////////////////////////////////// //~ Vertex ID helpers -Vec2 RectUvFromVertexId(u32 id) +Inline Vec2 RectUvFromVertexId(u32 id) { static const Vec2 uvs[4] = { Vec2(0, 0), @@ -153,7 +186,7 @@ Vec2 RectUvFromVertexId(u32 id) //////////////////////////////////////////////////////////// //~ Ndc helpers -Vec2 NdcFromPos(Vec2 pos, Vec2 size) +Inline Vec2 NdcFromPos(Vec2 pos, Vec2 size) { Vec2 result; result = pos / size; @@ -162,7 +195,7 @@ Vec2 NdcFromPos(Vec2 pos, Vec2 size) return result; } -Vec2 NdcFromUv(Vec2 uv) +Inline Vec2 NdcFromUv(Vec2 uv) { Vec2 result; result = uv; diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index 77760c1d..493b8a8a 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -142,11 +142,11 @@ void S_UpdateWorldFromDelta(Arena *arena, S_World *world, S_Delta *delta) for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) { i32 src_tile_x = tile_x - range.p0.x; - Vec2I32 src_tile_pos = VEC2I32(src_tile_x, src_tile_y); + Vec2 src_tile_pos = VEC2(src_tile_x, src_tile_y); i32 src_tile_idx = S_TileIdxFromTilePos(src_tile_pos); u8 src_tile = delta->raw_tiles[src_tile_idx]; - Vec2I32 tile_pos = VEC2I32(tile_x, tile_y); + Vec2 tile_pos = VEC2(tile_x, tile_y); i32 tile_idx = S_TileIdxFromTilePos(tile_pos); world->tiles[tile_idx] = src_tile; } @@ -161,7 +161,7 @@ void S_UpdateWorldFromDelta(Arena *arena, S_World *world, S_Delta *delta) { for (i32 tile_x = range.p0.x; tile_x < range.p1.x; ++tile_x) { - Vec2I32 tile_pos = VEC2I32(tile_x, tile_y); + Vec2 tile_pos = VEC2(tile_x, tile_y); i32 tile_idx = S_TileIdxFromTilePos(tile_pos); world->tiles[tile_idx] = (u8)tile; } diff --git a/src/pp/pp_sim/pp_sim_shared.cg b/src/pp/pp_sim/pp_sim_shared.cg index 155f78ea..649599f2 100644 --- a/src/pp/pp_sim/pp_sim_shared.cg +++ b/src/pp/pp_sim/pp_sim_shared.cg @@ -1,17 +1,9 @@ //////////////////////////////////////////////////////////// //~ Tile helpers -Vec2I32 S_TilePosFromWorldPos(Vec2 p) +i32 S_TileIdxFromTilePos(Vec2 p) { - Vec2I32 result; - result.x = ClampI32((p.x + S_WorldPitch * ((f32)S_WorldPitch / (f32)S_TilesPitch)) * 2, 0, S_TilesPitch - 1); - result.y = ClampI32((p.y + S_WorldPitch * ((f32)S_WorldPitch / (f32)S_TilesPitch)) * 2, 0, S_TilesPitch - 1); - return result; -} - -i32 S_TileIdxFromTilePos(Vec2I32 p) -{ - i32 result = ClampI32(p.x + (p.y * S_TilesPitch), 0, S_TilesCount); + i32 result = ClampI32(FloorF32(p.x) + (FloorF32(p.y) * S_TilesPitch), 0, S_TilesCount); return result; } diff --git a/src/pp/pp_sim/pp_sim_shared.cgh b/src/pp/pp_sim/pp_sim_shared.cgh index 5b1cc356..1f93eae4 100644 --- a/src/pp/pp_sim/pp_sim_shared.cgh +++ b/src/pp/pp_sim/pp_sim_shared.cgh @@ -2,7 +2,11 @@ //~ Tile types #define S_WorldPitch 64.0 -#define S_TilesPitch (S_WorldPitch * 2) + +#define S_TilesPerMeter 2.0 +#define S_TilesPerSqMeter (V_TilesPerMeter * V_TilesPerMeter) + +#define S_TilesPitch (S_WorldPitch * S_TilesPerMeter) #define S_TilesCount (S_TilesPitch * S_TilesPitch) #define S_TilesXMacro(X) \ @@ -23,8 +27,7 @@ Enum(S_TileKind) //////////////////////////////////////////////////////////// //~ Tile helpers -Vec2I32 S_TilePosFromWorldPos(Vec2 p); -i32 S_TileIdxFromTilePos(Vec2I32 p); +i32 S_TileIdxFromTilePos(Vec2 p); #if IsLanguageC String S_TileNameFromKind(S_TileKind kind); diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 96330aac..feb631bc 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -933,6 +933,16 @@ void V_TickForever(WaveLaneCtx *lane) frame->xf.cell_to_world = InvertXform(frame->xf.world_to_cell); } + // World <-> tile + // TODO: This never changes, should be #defined (so shaders don't need to read it every frame) + frame->xf.world_to_tile = XformIdentity; + frame->xf.tile_to_world = XformIdentity; + { + frame->xf.world_to_tile = ScaleXform(frame->xf.world_to_tile, VEC2(S_TilesPerMeter, S_TilesPerMeter)); + frame->xf.world_to_tile = TranslateXform(frame->xf.world_to_tile, VEC2((S_WorldPitch / 2.0), (S_WorldPitch / 2.0))); + frame->xf.tile_to_world = InvertXform(frame->xf.world_to_tile); + } + ////////////////////////////// //- Update cursors / selection @@ -990,9 +1000,8 @@ void V_TickForever(WaveLaneCtx *lane) { // TODO: Fix clamp when both start & end are outside of world Rng2I32 tile_range = Zi; - tile_range.p0 = S_TilePosFromWorldPos(last_frame->world_selection.p0); - tile_range.p1 = S_TilePosFromWorldPos(last_frame->world_selection.p1); - tile_range.p1 = AddVec2I32(tile_range.p1, VEC2I32(1, 1)); + tile_range.p0 = Vec2I32FromVec(FloorVec2(MulXformV2(frame->xf.world_to_tile, last_frame->world_selection.p0))); + tile_range.p1 = Vec2I32FromVec(CeilVec2(MulXformV2(frame->xf.world_to_tile, last_frame->world_selection.p1))); S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Delta); cmd->delta.kind = S_DeltaKind_Tile; @@ -2221,12 +2230,12 @@ void V_TickForever(WaveLaneCtx *lane) UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); { UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); - Vec2I32 tile_pos = S_TilePosFromWorldPos(frame->world_cursor); + Vec2 tile_pos = MulXformV2(frame->xf.world_to_tile, frame->world_cursor); Vec2 cell_pos = MulXformV2(frame->xf.world_to_cell, frame->world_cursor); i32 tile_idx = S_TileIdxFromTilePos(tile_pos); UI_BuildLabelF("Camera pos: %F", FmtFloat2(frame->camera_pos)); UI_BuildLabelF("Cursor world pos: %F", FmtFloat2(frame->world_cursor)); - UI_BuildLabelF("Cursor tile pos: %F", FmtSint2(tile_pos)); + UI_BuildLabelF("Cursor tile pos: %F", FmtFloat2(tile_pos)); UI_BuildLabelF("Cursor tile idx: %F", FmtSint(tile_idx)); UI_BuildLabelF("Cursor cell pos: %F", FmtFloat2(cell_pos)); UI_BuildLabelF("Hovered ent: %F", S_FmtKey(hovered_ent->key)); @@ -3223,7 +3232,15 @@ void V_TickForever(WaveLaneCtx *lane) G_DumbMemoryLayoutSync(frame->cl, gpu_tiles, G_Layout_DirectQueue_ShaderRead); } + // Flags + V_GpuFlag gpu_flags = 0; + if (frame->show_console) + { + gpu_flags |= V_GpuFlag_DebugDraw; + } + // Constants + G_SetConstant(frame->cl, V_ShaderConst_GpuFlags, gpu_flags); G_SetConstant(frame->cl, V_ShaderConst_State, gpu_state_ref); G_SetConstant(frame->cl, V_ShaderConst_Params, gpu_params_ref); G_SetConstant(frame->cl, V_ShaderConst_NoiseTex, G_BasicNoiseTexture()); diff --git a/src/pp/pp_vis/pp_vis_gpu.g b/src/pp/pp_vis/pp_vis_gpu.g index f36c4c91..c1b1e8be 100644 --- a/src/pp/pp_vis/pp_vis_gpu.g +++ b/src/pp/pp_vis/pp_vis_gpu.g @@ -73,10 +73,6 @@ ComputeShader2D(V_BackdropCS, 8, 8) const Vec4 background_color_a = LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1)); const Vec4 background_color_b = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)); - const Vec4 grid_color = LinearFromSrgb(Vec4(0, 0, 0, 1)); - const Vec4 x_axis_color = LinearFromSrgb(Vec4(0.75, 0, 0, 1)); - const Vec4 y_axis_color = LinearFromSrgb(Vec4(0, 0.75, 0, 1)); - const Vec4 bounds_color = LinearFromSrgb(Vec4(0.75, 0.75, 0, 1)); Vec2 ui_pos = SV_DispatchThreadID + Vec2(0.5, 0.5); if (ui_pos.x < params.target_size.x && ui_pos.y < params.target_size.y) @@ -84,21 +80,18 @@ ComputeShader2D(V_BackdropCS, 8, 8) Vec4 result = Vec4(0.025, 0.025, 0.025, 1); Vec2 world_pos = mul(params.xf.ui_to_world, Vec3(ui_pos, 1)); - Vec2I32 tile_pos = S_TilePosFromWorldPos(world_pos); - Vec2I32 tile_pos_right = tile_pos; - tile_pos_right.x += 1; + Vec2 tile_pos = mul(params.xf.world_to_tile, Vec3(world_pos, 1)); - S_TileKind tile = tiles.Load(Vec3I32(tile_pos, 0)); - S_TileKind tile_right = tiles.Load(Vec3I32(tile_pos_right, 0)); + S_TileKind tile = tiles.Load(Vec3(tile_pos, 0)); f32 half_thickness = 1; f32 half_bounds_size = S_WorldPitch * 0.5; Vec2 bounds_screen_p0 = mul(params.xf.world_to_ui, Vec3(-half_bounds_size, -half_bounds_size, 1)); Vec2 bounds_screen_p1 = mul(params.xf.world_to_ui, Vec3(half_bounds_size, half_bounds_size, 1)); bool is_in_bounds = ui_pos.x > (bounds_screen_p0.x - half_thickness) && - ui_pos.y > (bounds_screen_p0.y - half_thickness) && - ui_pos.x < (bounds_screen_p1.x + half_thickness) && - ui_pos.y < (bounds_screen_p1.y + half_thickness); + ui_pos.y > (bounds_screen_p0.y - half_thickness) && + ui_pos.x < (bounds_screen_p1.x + half_thickness) && + ui_pos.y < (bounds_screen_p1.y + half_thickness); if (is_in_bounds) { // Grid checker @@ -128,78 +121,51 @@ ComputeShader2D(V_BackdropCS, 8, 8) } result = colors[color_idx]; } - // Grid outline - // { - // Vec2 grid_screen_p0 = mul(params.xf.world_to_ui, Vec3(floor(world_pos), 1)); - // Vec2 grid_screen_p1 = mul(params.xf.world_to_ui, Vec3(ceil(world_pos), 1)); - // f32 grid_dist = 100000; - // grid_dist = min(grid_dist, abs(ui_pos.x - grid_screen_p0.x)); - // grid_dist = min(grid_dist, abs(ui_pos.x - grid_screen_p1.x)); - // grid_dist = min(grid_dist, abs(ui_pos.y - grid_screen_p0.y)); - // grid_dist = min(grid_dist, abs(ui_pos.y - grid_screen_p1.y)); - // if (grid_dist <= half_thickness) - // { - // result = grid_color; - // } - // } - // Axis - { - Vec2 zero_screen = mul(params.xf.world_to_ui, Vec3(0, 0, 1)); - f32 x_dist = abs(ui_pos.x - zero_screen.x); - f32 y_dist = abs(ui_pos.y - zero_screen.y); - if (y_dist <= half_thickness) - { - result = x_axis_color; - } - else if (x_dist <= half_thickness) - { - result = y_axis_color; - } - } - // World bounds - { - f32 bounds_dist = 100000; - bounds_dist = min(bounds_dist, abs(ui_pos.x - bounds_screen_p0.x)); - bounds_dist = min(bounds_dist, abs(ui_pos.x - bounds_screen_p1.x)); - bounds_dist = min(bounds_dist, abs(ui_pos.y - bounds_screen_p0.y)); - bounds_dist = min(bounds_dist, abs(ui_pos.y - bounds_screen_p1.y)); - if (bounds_dist <= half_thickness) - { - result = bounds_color; - } - } - - - - - // Tile test // TODO: Remove this { - if (tile == S_TileKind_Floor) + S_TileKind tile_tl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y - 1, 0)); + S_TileKind tile_tr = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y - 1, 0)); + S_TileKind tile_br = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y + 1, 0)); + S_TileKind tile_bl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y + 1, 0)); + S_TileKind tile_t = tiles.Load(Vec3(tile_pos.x, tile_pos.y - 1, 0)); + S_TileKind tile_r = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y, 0)); + S_TileKind tile_b = tiles.Load(Vec3(tile_pos.x, tile_pos.y + 1, 0)); + S_TileKind tile_l = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y, 0)); + + f32 tile_edge_dist = Inf; + S_TileKind edge_tile = tile; + if (tile_tl != tile) { edge_tile = tile_tl; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(floor(tile_pos.x), floor(tile_pos.y)))); } + if (tile_tr != tile) { edge_tile = tile_tr; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), floor(tile_pos.y)))); } + if (tile_br != tile) { edge_tile = tile_br; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), ceil(tile_pos.y)))); } + if (tile_bl != tile) { edge_tile = tile_bl; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(floor(tile_pos.x), ceil(tile_pos.y)))); } + if (tile_l != tile) { edge_tile = tile_l; tile_edge_dist = min(tile_edge_dist, frac(tile_pos.x)); } + if (tile_r != tile) { edge_tile = tile_r; tile_edge_dist = min(tile_edge_dist, 1.0 - frac(tile_pos.x)); } + if (tile_t != tile) { edge_tile = tile_t; tile_edge_dist = min(tile_edge_dist, frac(tile_pos.y)); } + if (tile_b != tile) { edge_tile = tile_b; tile_edge_dist = min(tile_edge_dist, 1.0 - frac(tile_pos.y)); } + + if (tile == S_TileKind_Wall) + { + Vec4 outer = LinearFromSrgb(Vec4(0.05, 0.05, 0.05, 1)); + Vec4 inner = LinearFromSrgb(Vec4(0.10, 0.10, 0.10, 1)); + // result = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.375)); + result = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.5)); + } + else if (tile != S_TileKind_Empty) { SamplerState wrap_sampler = G_Dereference(params.pt_wrap_sampler); SPR_Slice slice = params.tile_slices[tile]; Texture2D tile_tex = G_Dereference(slice.tex); - result = tile_tex.Sample(wrap_sampler, world_pos); + Vec4 floor_col = tile_tex.Sample(wrap_sampler, world_pos); + + // if (edge_tile == S_TileKind_Wall && tile_edge_dist < 0.05) + // { + // // floor_col.rgb *= 0.25; + // } + + result = floor_col; } - else if (tile == S_TileKind_Wall) - { - // Distance to edge of wall in cells - f32 wall_dist = 0; - result = Color_Black; - - - - - // result.rgb *= wall_dist; - if (wall_dist > 1) - { - result = Color_White; - } - } - // switch (tile) // { @@ -557,10 +523,18 @@ PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input) Vec4 result = 0; Vec2 world_pos = mul(params.xf.ui_to_world, Vec3(ui_pos, 1)); - Vec2I32 tile_pos = S_TilePosFromWorldPos(world_pos); + Vec2 tile_pos = mul(params.xf.world_to_tile, Vec3(world_pos, 1)); S_TileKind equipped_tile = params.equipped_tile; f32 half_thickness = 1; + f32 half_bounds_size = S_WorldPitch * 0.5; + Vec2 bounds_screen_p0 = mul(params.xf.world_to_ui, Vec3(-half_bounds_size, -half_bounds_size, 1)); + Vec2 bounds_screen_p1 = mul(params.xf.world_to_ui, Vec3(half_bounds_size, half_bounds_size, 1)); + bool is_in_bounds = ui_pos.x > (bounds_screen_p0.x - half_thickness) && + ui_pos.y > (bounds_screen_p0.y - half_thickness) && + ui_pos.x < (bounds_screen_p1.x + half_thickness) && + ui_pos.y < (bounds_screen_p1.y + half_thickness); + Vec4 border_color = LinearFromSrgb(Vec4(1, 1, 1, 1)); // Vec4 inner_color = LinearFromSrgb(Vec4(0.4, 0.4, 0.4, 0.25)); @@ -569,9 +543,9 @@ PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input) Rng2 screen_selection = params.draw_selection; Rng2 world_selection = params.world_selection; - Rng2I32 tile_selection; - tile_selection.p0 = S_TilePosFromWorldPos(world_selection.p0); - tile_selection.p1 = S_TilePosFromWorldPos(world_selection.p1); + Rng2 tile_selection; + tile_selection.p0 = floor(mul(params.xf.world_to_tile, Vec3(world_selection.p0, 1))); + tile_selection.p1 = ceil(mul(params.xf.world_to_tile, Vec3(world_selection.p1, 1))); if (params.has_mouse_focus) { @@ -607,6 +581,57 @@ PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input) } } + if (is_in_bounds) + { + // Grid outline + if (V_ShaderConst_GpuFlags & V_GpuFlag_DebugDraw) + { + const Vec4 grid_color = LinearFromSrgb(Vec4(1, 1, 1, 0.1)); + Vec2 grid_screen_p0 = mul(params.xf.world_to_ui, Vec3(floor(world_pos), 1)); + Vec2 grid_screen_p1 = mul(params.xf.world_to_ui, Vec3(ceil(world_pos), 1)); + f32 grid_dist = 100000; + grid_dist = min(grid_dist, abs(ui_pos.x - grid_screen_p0.x)); + grid_dist = min(grid_dist, abs(ui_pos.x - grid_screen_p1.x)); + grid_dist = min(grid_dist, abs(ui_pos.y - grid_screen_p0.y)); + grid_dist = min(grid_dist, abs(ui_pos.y - grid_screen_p1.y)); + if (grid_dist <= half_thickness * 0.5) + { + result = grid_color; + } + } + // Axis + if (V_ShaderConst_GpuFlags & V_GpuFlag_DebugDraw) + { + const Vec4 x_axis_color = LinearFromSrgb(Vec4(0.75, 0, 0, 1)); + const Vec4 y_axis_color = LinearFromSrgb(Vec4(0, 0.75, 0, 1)); + + Vec2 zero_screen = mul(params.xf.world_to_ui, Vec3(0, 0, 1)); + f32 x_dist = abs(ui_pos.x - zero_screen.x); + f32 y_dist = abs(ui_pos.y - zero_screen.y); + if (y_dist <= half_thickness) + { + result = x_axis_color; + } + else if (x_dist <= half_thickness) + { + result = y_axis_color; + } + } + // World bounds + { + const Vec4 bounds_color = LinearFromSrgb(Vec4(0.75, 0.75, 0, 1)); + f32 bounds_dist = 100000; + bounds_dist = min(bounds_dist, abs(ui_pos.x - bounds_screen_p0.x)); + bounds_dist = min(bounds_dist, abs(ui_pos.x - bounds_screen_p1.x)); + bounds_dist = min(bounds_dist, abs(ui_pos.y - bounds_screen_p0.y)); + bounds_dist = min(bounds_dist, abs(ui_pos.y - bounds_screen_p1.y)); + if (bounds_dist <= half_thickness) + { + result = bounds_color; + } + } + } + V_OverlayPSOutput output; output.sv_target0 = result; return output; diff --git a/src/pp/pp_vis/pp_vis_shared.cgh b/src/pp/pp_vis/pp_vis_shared.cgh index 09181066..d6b7f3f0 100644 --- a/src/pp/pp_vis/pp_vis_shared.cgh +++ b/src/pp/pp_vis/pp_vis_shared.cgh @@ -9,9 +9,16 @@ //////////////////////////////////////////////////////////// //~ Constant types -G_DeclConstant(G_RWStructuredBufferRef, V_ShaderConst_State, 0); -G_DeclConstant(G_StructuredBufferRef, V_ShaderConst_Params, 1); -G_DeclConstant(G_Texture3DRef, V_ShaderConst_NoiseTex, 2); +Enum(V_GpuFlag) +{ + V_GpuFlag_None = 0, + V_GpuFlag_DebugDraw = (1 << 0), +}; + +G_DeclConstant(V_GpuFlag, V_ShaderConst_GpuFlags, 0); +G_DeclConstant(G_RWStructuredBufferRef, V_ShaderConst_State, 1); +G_DeclConstant(G_StructuredBufferRef, V_ShaderConst_Params, 2); +G_DeclConstant(G_Texture3DRef, V_ShaderConst_NoiseTex, 3); Enum(V_SelectionMode) { @@ -36,6 +43,10 @@ Struct(V_Xforms) // World <-> cell Xform world_to_cell; Xform cell_to_world; + + // World <-> tile + Xform world_to_tile; + Xform tile_to_world; }; Struct(V_GpuState)