From 7a81397fd1d4c12dc8226fb779b11915a96ecf9d Mon Sep 17 00:00:00 2001 From: jacob Date: Thu, 22 Jan 2026 11:03:03 -0600 Subject: [PATCH] shading pass progress --- src/base/base_math.h | 48 ++-- src/pp/pp_vis/pp_vis_core.c | 29 ++- src/pp/pp_vis/pp_vis_gpu.g | 472 ++++++++++++++++++++++-------------- src/ui/ui_gpu.g | 2 +- 4 files changed, 329 insertions(+), 222 deletions(-) diff --git a/src/base/base_math.h b/src/base/base_math.h index 1e2641d6..8a41a7cf 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -229,28 +229,28 @@ f64 SaturateF64(f64 v); //~ Float ops //- Round -#define RoundF32(v) roundf(v) -#define RoundF64(v) round(v) +#define RoundF32 roundf +#define RoundF64 round //- Floor -#define FloorF32(v) floorf(v) -#define FloorF64(v) floor(v) +#define FloorF32 floorf +#define FloorF64 floor //- Ceil -#define CeilF32(v) ceilf(v) -#define CeilF64(v) ceil(v) +#define CeilF32 ceilf +#define CeilF64 ceil //- Trunc -#define TruncF32(v) truncf(v) -#define TruncF64(v) trunc(v) +#define TruncF32 truncf +#define TruncF64 trunc //- Mod -#define ModF32(v, m) fmodf((v), (m)) -#define ModF64(v, m) fmod((v), (m)) +#define ModF32 fmodf +#define ModF64 fmod //- Abs -#define AbsF32(v) fabsf(v) -#define AbsF64(v) fabs(v) +#define AbsF32 fabsf +#define AbsF64 fabs //- Sign i32 SignF32(f32 v); @@ -261,15 +261,15 @@ i32 SignF64(f64 v); u64 PowU64(u64 v, u8 exp); -#define PowF32(v, exp) powf((v), (exp)) -#define PowF64(v, exp) pow((v), (exp)) +#define PowF32 powf +#define PowF64 pow -#define SqrtF32(v) sqrtf(v) -#define SqrtF64(v) sqrt(v) +#define SqrtF32 sqrtf +#define SqrtF64 sqrt -#define LnF32(v) log(v) -#define Log2F32(v) log2f(v) -#define Log10F32(v) log10f(v) +#define LnF32 log +#define Log2F32 log2f +#define Log10F32 log10f //////////////////////////////////////////////////////////// //~ Align @@ -280,11 +280,11 @@ u64 NextPow2U64(u64 x); //////////////////////////////////////////////////////////// //~ Trig -#define SinF32(v) sinf(v) -#define CosF32(v) cosf(v) -#define TanF32(x) tanf(x) -#define ArcTanF32(x) atanf(x) -#define ArcTan2F32(y, x) atan2f((y), (x)) +#define SinF32 sinf +#define CosF32 cosf +#define TanF32 tanf +#define ArcTanF32 atanf +#define ArcTan2F32 atan2f //////////////////////////////////////////////////////////// //~ Angle unwind diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 096916cf..05b385ad 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -345,7 +345,7 @@ void V_TickForever(WaveLaneCtx *lane) const f32 zoom_rate = 1.50; const f32 min_zoom = 0.03; const f32 max_zoom = 15.0; - const f32 meters_per_screen_width = 16; + const f32 meters_per_camera_width = 16; NET_PipeHandle net_pipe = NET_AcquirePipe(); BB_Buff packer_bb = BB_AcquireDynamicBuff(Gibi(64)); @@ -678,13 +678,16 @@ void V_TickForever(WaveLaneCtx *lane) frame->screen_dims.x = MaxF32(frame->screen_dims.x, 64); frame->screen_dims.y = MaxF32(frame->screen_dims.y, 64); - // frame->shade_dims = frame->screen_dims; + // Since a shaded cell is smaller than a screen pixel, we increase the + // dimensions of our shaded texture to prevent gaps at the edge of the screen + Vec2 shade_extra_dims = VEC2(1, 1); f32 max_shade_aspect_ratio = 16.0 / 10.0; - frame->shade_dims.x = V_CellsPerMeter * meters_per_screen_width; + frame->shade_dims.x = V_CellsPerMeter * meters_per_camera_width; frame->shade_dims.y = frame->shade_dims.x / (frame->screen_dims.x / frame->screen_dims.y); frame->shade_dims.y = MinF32(frame->shade_dims.y, frame->shade_dims.x / max_shade_aspect_ratio); - + frame->shade_dims = AddVec2(frame->shade_dims, shade_extra_dims); + frame->shade_dims = CeilVec2(frame->shade_dims); ////////////////////////////// //- Pop sim -> vis data @@ -824,8 +827,8 @@ void V_TickForever(WaveLaneCtx *lane) Xform prev_frame_edit_to_screen_xf = Zi; Xform edit_to_screen_xf = Zi; { - f32 prev_edit_camera_scale = (f32)prev_frame->screen_dims.x / (meters_per_screen_width * prev_frame->edit_camera_zoom); - f32 edit_camera_scale = (f32)frame->screen_dims.x / (meters_per_screen_width * frame->edit_camera_zoom); + f32 prev_edit_camera_scale = (f32)prev_frame->screen_dims.x / (meters_per_camera_width * prev_frame->edit_camera_zoom); + f32 edit_camera_scale = (f32)frame->screen_dims.x / (meters_per_camera_width * frame->edit_camera_zoom); prev_frame_edit_to_screen_xf = XformFromScale(VEC2(prev_edit_camera_scale, prev_edit_camera_scale)); prev_frame_edit_to_screen_xf = TranslateXform(prev_frame_edit_to_screen_xf, NegVec2(prev_frame->edit_camera_pos)); prev_frame_edit_to_screen_xf = WorldTranslateXform(prev_frame_edit_to_screen_xf, MulVec2(Vec2FromVec(frame->screen_dims), 0.5)); @@ -860,8 +863,7 @@ void V_TickForever(WaveLaneCtx *lane) target_camera_pos.x = ClampF32(target_camera_pos.x, -world_pitch / 2, world_pitch / 2); target_camera_pos.y = ClampF32(target_camera_pos.y, -world_pitch / 2, world_pitch / 2); target_camera_zoom = ClampF32(target_camera_zoom, min_zoom, max_zoom); - - // Create world <-> screen xforms + // Interpolate camera { if (prev_frame->tick == 0) { @@ -899,10 +901,10 @@ void V_TickForever(WaveLaneCtx *lane) frame->xf.world_to_screen = XformIdentity; frame->xf.screen_to_world = XformIdentity; { - f32 camera_scale = (f32)frame->screen_dims.x / (meters_per_screen_width * frame->camera_zoom); + f32 camera_scale = frame->screen_dims.x / (meters_per_camera_width * frame->camera_zoom); frame->xf.world_to_screen = XformFromScale(VEC2(camera_scale, camera_scale)); frame->xf.world_to_screen = TranslateXform(frame->xf.world_to_screen, NegVec2(frame->camera_pos)); - frame->xf.world_to_screen = WorldTranslateXform(frame->xf.world_to_screen, MulVec2(Vec2FromVec(frame->screen_dims), 0.5)); + frame->xf.world_to_screen = WorldTranslateXform(frame->xf.world_to_screen, MulVec2(frame->screen_dims, 0.5)); frame->xf.world_to_screen.og = RoundVec2(frame->xf.world_to_screen.og); frame->xf.screen_to_world = InvertXform(frame->xf.world_to_screen); } @@ -911,7 +913,11 @@ void V_TickForever(WaveLaneCtx *lane) frame->xf.world_to_shade = XformIdentity; frame->xf.shade_to_world = XformIdentity; { - frame->xf.world_to_shade = MulXform(frame->xf.world_to_screen, frame->xf.screen_to_shade); + f32 camera_scale = (frame->shade_dims.x - shade_extra_dims.x) / (meters_per_camera_width * frame->camera_zoom); + frame->xf.world_to_shade = XformFromScale(VEC2(camera_scale, camera_scale)); + frame->xf.world_to_shade = TranslateXform(frame->xf.world_to_shade, NegVec2(frame->camera_pos)); + frame->xf.world_to_shade = WorldTranslateXform(frame->xf.world_to_shade, MulVec2(frame->shade_dims, 0.5)); + frame->xf.world_to_shade.og = RoundVec2(frame->xf.world_to_shade.og); frame->xf.shade_to_world = InvertXform(frame->xf.world_to_shade); } @@ -919,6 +925,7 @@ void V_TickForever(WaveLaneCtx *lane) frame->xf.shade_to_screen = XformIdentity; frame->xf.screen_to_shade = XformIdentity; { + frame->xf.shade_to_screen = MulXform(frame->xf.world_to_screen, frame->xf.shade_to_world); frame->xf.screen_to_shade = InvertXform(frame->xf.shade_to_screen); } diff --git a/src/pp/pp_vis/pp_vis_gpu.g b/src/pp/pp_vis/pp_vis_gpu.g index f905fdcb..463c13d1 100644 --- a/src/pp/pp_vis/pp_vis_gpu.g +++ b/src/pp/pp_vis/pp_vis_gpu.g @@ -76,198 +76,199 @@ ComputeShader2D(V_BackdropCS, 8, 8) const Vec4 background_color_b = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)); Vec2 screen_pos = SV_DispatchThreadID + Vec2(0.5, 0.5); - if (all(screen_pos < params.screen_dims)) + + Vec4 result = Vec4(0.025, 0.025, 0.025, 1); + Vec2 world_pos = mul(params.xf.screen_to_world, Vec3(screen_pos, 1)); + Vec2 cell_pos = floor(mul(params.xf.world_to_cell, Vec3(world_pos, 1))); + Vec2 tile_pos = mul(params.xf.world_to_tile, Vec3(world_pos, 1)); + + P_TileKind tile = tiles.Load(Vec3(tile_pos, 0)); + + f32 half_thickness = 1; + f32 half_world_bounds_size = P_WorldPitch * 0.5; + Vec2 world_bounds_screen_p0 = mul(params.xf.world_to_screen, Vec3(-half_world_bounds_size, -half_world_bounds_size, 1)); + Vec2 world_bounds_screen_p1 = mul(params.xf.world_to_screen, Vec3(half_world_bounds_size, half_world_bounds_size, 1)); + b32 is_in_world_bounds = + screen_pos.x > (world_bounds_screen_p0.x - half_thickness) && + screen_pos.y > (world_bounds_screen_p0.y - half_thickness) && + screen_pos.x < (world_bounds_screen_p1.x + half_thickness) && + screen_pos.y < (world_bounds_screen_p1.y + half_thickness); + + if (is_in_world_bounds) { - Vec4 result = Vec4(0.025, 0.025, 0.025, 1); - Vec2 world_pos = mul(params.xf.screen_to_world, Vec3(screen_pos, 1)); - Vec2 cell_pos = floor(mul(params.xf.world_to_cell, Vec3(world_pos, 1))); - Vec2 tile_pos = mul(params.xf.world_to_tile, Vec3(world_pos, 1)); + // // Checkered grid + // { + // i32 color_idx = 0; + // Vec4 colors[2] = { + // background_color_a, + // background_color_b + // }; + // const f32 checker_size = 0.5; + // Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(checker_size * 2, checker_size * 2)); + // if (world_pos_modded.x < checker_size) + // { + // color_idx = !color_idx; + // } + // if (world_pos_modded.y < checker_size) + // { + // color_idx = !color_idx; + // } + // if (world_pos.x < 0) + // { + // color_idx = !color_idx; + // } + // if (world_pos.y < 0) + // { + // color_idx = !color_idx; + // } + // result = colors[color_idx]; + // } - P_TileKind tile = tiles.Load(Vec3(tile_pos, 0)); - - f32 half_thickness = 1; - f32 half_world_bounds_size = P_WorldPitch * 0.5; - Vec2 world_bounds_screen_p0 = mul(params.xf.world_to_screen, Vec3(-half_world_bounds_size, -half_world_bounds_size, 1)); - Vec2 world_bounds_screen_p1 = mul(params.xf.world_to_screen, Vec3(half_world_bounds_size, half_world_bounds_size, 1)); - b32 is_in_world_bounds = - screen_pos.x > (world_bounds_screen_p0.x - half_thickness) && - screen_pos.y > (world_bounds_screen_p0.y - half_thickness) && - screen_pos.x < (world_bounds_screen_p1.x + half_thickness) && - screen_pos.y < (world_bounds_screen_p1.y + half_thickness); - - if (is_in_world_bounds) + // Tile test + // TODO: Remove this { - // Checkered grid + P_TileKind tile_tl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y - 1, 0)); + P_TileKind tile_tr = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y - 1, 0)); + P_TileKind tile_br = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y + 1, 0)); + P_TileKind tile_bl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y + 1, 0)); + P_TileKind tile_t = tiles.Load(Vec3(tile_pos.x, tile_pos.y - 1, 0)); + P_TileKind tile_r = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y, 0)); + P_TileKind tile_b = tiles.Load(Vec3(tile_pos.x, tile_pos.y + 1, 0)); + P_TileKind tile_l = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y, 0)); + + f32 tile_edge_dist = Inf; + P_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 == P_TileKind_Wall) { - i32 color_idx = 0; - Vec4 colors[2] = { - background_color_a, - background_color_b - }; - const f32 checker_size = 0.5; - Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(checker_size * 2, checker_size * 2)); - if (world_pos_modded.x < checker_size) - { - color_idx = !color_idx; - } - if (world_pos_modded.y < checker_size) - { - color_idx = !color_idx; - } - if (world_pos.x < 0) - { - color_idx = !color_idx; - } - if (world_pos.y < 0) - { - color_idx = !color_idx; - } - result = colors[color_idx]; + Vec4 outer = LinearFromSrgb(Vec4(0.05, 0.05, 0.05, 1)); + Vec4 inner = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 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 != P_TileKind_Empty) + { + SPR_Slice slice = params.tile_slices[tile]; + Texture2D tile_tex = G_Dereference(slice.tex); + Vec4 tile_col = tile_tex.SampleLevel(wrap_sampler, world_pos, 0); + + result = tile_col; } - // Tile test - // TODO: Remove this - { - P_TileKind tile_tl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y - 1, 0)); - P_TileKind tile_tr = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y - 1, 0)); - P_TileKind tile_br = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y + 1, 0)); - P_TileKind tile_bl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y + 1, 0)); - P_TileKind tile_t = tiles.Load(Vec3(tile_pos.x, tile_pos.y - 1, 0)); - P_TileKind tile_r = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y, 0)); - P_TileKind tile_b = tiles.Load(Vec3(tile_pos.x, tile_pos.y + 1, 0)); - P_TileKind tile_l = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y, 0)); - - f32 tile_edge_dist = Inf; - P_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 == P_TileKind_Wall) - { - Vec4 outer = LinearFromSrgb(Vec4(0.05, 0.05, 0.05, 1)); - Vec4 inner = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 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 != P_TileKind_Empty) - { - SPR_Slice slice = params.tile_slices[tile]; - Texture2D tile_tex = G_Dereference(slice.tex); - Vec4 tile_col = tile_tex.Sample(wrap_sampler, world_pos); - - result = tile_col; - } - - // switch (tile) - // { - // default: break; - - // case P_TileKind_Floor: - // { - // result = Color_Blue; - // } break; - - // case P_TileKind_Wall: - // { - // // result = Color_Red; - // result = Color_Black; - // } break; - // } - } - - - - - - // TODO: Remove this - // Cells test - { - RWTexture2D stains = G_Dereference(params.stains); - RWTexture2D cells = G_Dereference(params.cells); - RWTexture2D drynesses = G_Dereference(params.drynesses); - - Vec4 stain = stains.Load(cell_pos); - Vec4 cell = cells.Load(cell_pos); - f32 dryness = drynesses[cell_pos]; - - stain = V_DryColor(stain, dryness); - - // cell.rgb *= cell.a; - // stain.rgb *= stain.a; - - result.rgb = (stain.rgb * stain.a) + (result.rgb * (1.0 - stain.a)); - result.a = (stain.a * 1) + (result.a * (1.0 - stain.a)); - - result.rgb = (cell.rgb * cell.a) + (result.rgb * (1.0 - cell.a)); - result.a = (cell.a * 1) + (result.a * (1.0 - cell.a)); - - // Vec4 cell = cells.Load(cell_pos); - // if (cell.a != 0) - // { - // result = cell; - // } - // else - // { - // Vec4 stain = stains.Load(cell_pos); - // if (stain.a != 0) - // { - // result = stain; - // } - // } - } - - - - - - - // // TODO: Remove this - // // Cells test + // switch (tile) // { - // RWTexture2D cells = G_Dereference(params.cells); - // Vec2 cell_pos = floor(mul(params.xf.world_to_cell, Vec3(world_pos, 1))); - // Vec4 cell = cells.Load(cell_pos); - // if (cell.a != 0) + // default: break; + + // case P_TileKind_Floor: // { - // result = cell; - // } - // else + // result = Color_Blue; + // } break; + + // case P_TileKind_Wall: // { - // RWTexture2D stains = G_Dereference(params.stains); - // Vec4 stain = stains.Load(cell_pos); - // if (stain.a != 0) - // { - // result = stain; - // } - // } + // // result = Color_Red; + // result = Color_Black; + // } break; // } - - - - // TODO: Remove this - // Stains test - // { - // RWTexture2D stains = G_Dereference(params.stains); - // Vec2 cell_pos = mul(params.xf.world_to_cell, Vec3(world_pos, 1)); - // V_ParticleKind stain = stains.Load(cell_pos); - - // if (stain == V_ParticleKind_Test) - // { - // // result = Color_Yellow; - // // result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1)); - // // result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1)); - // } - // } - } - screen[SV_DispatchThreadID] = result; + + + + + // TODO: Remove this + // Cells test + { + RWTexture2D stains = G_Dereference(params.stains); + RWTexture2D cells = G_Dereference(params.cells); + RWTexture2D drynesses = G_Dereference(params.drynesses); + + Vec4 stain = stains.Load(cell_pos); + Vec4 cell = cells.Load(cell_pos); + f32 dryness = drynesses[cell_pos]; + + stain = V_DryColor(stain, dryness); + + // cell.rgb *= cell.a; + // stain.rgb *= stain.a; + + result.rgb = (stain.rgb * stain.a) + (result.rgb * (1.0 - stain.a)); + result.a = (stain.a * 1) + (result.a * (1.0 - stain.a)); + + result.rgb = (cell.rgb * cell.a) + (result.rgb * (1.0 - cell.a)); + result.a = (cell.a * 1) + (result.a * (1.0 - cell.a)); + + // Vec4 cell = cells.Load(cell_pos); + // if (cell.a != 0) + // { + // result = cell; + // } + // else + // { + // Vec4 stain = stains.Load(cell_pos); + // if (stain.a != 0) + // { + // result = stain; + // } + // } + } + + + + + + + // // TODO: Remove this + // // Cells test + // { + // RWTexture2D cells = G_Dereference(params.cells); + // Vec2 cell_pos = floor(mul(params.xf.world_to_cell, Vec3(world_pos, 1))); + // Vec4 cell = cells.Load(cell_pos); + // if (cell.a != 0) + // { + // result = cell; + // } + // else + // { + // RWTexture2D stains = G_Dereference(params.stains); + // Vec4 stain = stains.Load(cell_pos); + // if (stain.a != 0) + // { + // result = stain; + // } + // } + // } + + + + // TODO: Remove this + // Stains test + // { + // RWTexture2D stains = G_Dereference(params.stains); + // Vec2 cell_pos = mul(params.xf.world_to_cell, Vec3(world_pos, 1)); + // V_ParticleKind stain = stains.Load(cell_pos); + + // if (stain == V_ParticleKind_Test) + // { + // // result = Color_Yellow; + // // result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1)); + // // result = LinearFromSrgb(Vec4(0.5, 0.1, 0.1, 1)); + // } + // } + + } + + if (all(screen_pos < countof(screen))) + { + screen[screen_pos] = result; } } @@ -469,14 +470,113 @@ ComputeShader2D(V_ShadeCS, 8, 8) { V_GpuParams params = G_Dereference(V_ShaderConst_Params)[0]; RWTexture2D shade_tex = G_Dereference(params.shade_rw); + Texture2D tiles = G_Dereference(params.tiles); + SamplerState wrap_sampler = G_Dereference(params.pt_wrap_sampler); Vec2 shade_pos = SV_DispatchThreadID + Vec2(0.5, 0.5); + Vec2 world_pos = mul(params.xf.shade_to_world, Vec3(shade_pos, 1)); + Vec2 cell_pos = floor(mul(params.xf.world_to_cell, Vec3(world_pos, 1))); + Vec2 tile_pos = mul(params.xf.world_to_tile, Vec3(world_pos, 1)); + + P_TileKind tile = tiles.Load(Vec3(tile_pos, 0)); + + Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5; + b32 is_in_world_bounds = all(world_pos > -half_world_dims) && all(world_pos < half_world_dims); + + //- Tile color + // TODO: Remove this + b32 tile_is_wall = 0; + Vec4 tile_color = 0; + if (is_in_world_bounds) + { + P_TileKind tile_tl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y - 1, 0)); + P_TileKind tile_tr = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y - 1, 0)); + P_TileKind tile_br = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y + 1, 0)); + P_TileKind tile_bl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y + 1, 0)); + P_TileKind tile_t = tiles.Load(Vec3(tile_pos.x, tile_pos.y - 1, 0)); + P_TileKind tile_r = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y, 0)); + P_TileKind tile_b = tiles.Load(Vec3(tile_pos.x, tile_pos.y + 1, 0)); + P_TileKind tile_l = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y, 0)); + + f32 tile_edge_dist = Inf; + P_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 == P_TileKind_Wall) + { + Vec4 outer = LinearFromSrgb(Vec4(0.05, 0.05, 0.05, 1)); + Vec4 inner = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)); + tile_color = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.375)); + // tile_color = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.5)); + tile_is_wall = 1; + } + else if (tile != P_TileKind_Empty) + { + SPR_Slice slice = params.tile_slices[tile]; + Texture2D tile_tex = G_Dereference(slice.tex); + tile_color = tile_tex.SampleLevel(wrap_sampler, world_pos, 0); + } + // Checkered grid + else if (tile == P_TileKind_Empty) + { + i32 color_idx = 0; + Vec4 colors[2] = { + LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1)), + LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)) + }; + const f32 checker_size = 0.5; + Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(checker_size * 2, checker_size * 2)); + if (world_pos_modded.x < checker_size) + { + color_idx = !color_idx; + } + if (world_pos_modded.y < checker_size) + { + color_idx = !color_idx; + } + if (world_pos.x < 0) + { + color_idx = !color_idx; + } + if (world_pos.y < 0) + { + color_idx = !color_idx; + } + tile_color = colors[color_idx]; + } + + // switch (tile) + // { + // default: break; + + // case P_TileKind_Floor: + // { + // tile_color = Color_Blue; + // } break; + + // case P_TileKind_Wall: + // { + // // tile_color = Color_Red; + // tile_color = Color_Black; + // } break; + // } + } + + + //- Composite + Vec4 result = 0; + result = BlendPremul(!tile_is_wall * tile_color, result); // Blend floor tile + result = BlendPremul(tile_is_wall * tile_color, result); // Blend wall tile + if (all(shade_pos < countof(shade_tex))) { - Vec4 result = 0; - result.r = shade_pos.x / countof(shade_tex).x; - - result.a = 1; shade_tex[shade_pos] = result; } } @@ -529,7 +629,7 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input) if (all(shade_pos >= Vec2(0, 0)) && all(shade_pos < countof(shade_tex))) { Vec2 shade_uv = shade_pos / countof(shade_tex); - shade_color = shade_tex.Sample(clamp_sampler, shade_uv); + shade_color = shade_tex.SampleLevel(clamp_sampler, shade_uv, 0); } //- Tile selection overlay @@ -637,9 +737,9 @@ PixelShader(V_CompositePS, V_CompositePSOutput, V_CompositePSInput input) //- Composite Vec4 result = 0; + result = BlendPremul(shade_color, result); result = BlendPremul(selection_color, result); result = BlendPremul(overlay_color, result); - result = BlendPremul(shade_color, result); result = Unpremul(result); diff --git a/src/ui/ui_gpu.g b/src/ui/ui_gpu.g index 136993da..431e45b2 100644 --- a/src/ui/ui_gpu.g +++ b/src/ui/ui_gpu.g @@ -78,7 +78,7 @@ PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input) else { Texture2D tex = G_Dereference(rect.tex); - background_premul = tex.Sample(sampler, input.tex_uv); + background_premul = tex.SampleLevel(sampler, input.tex_uv, 0); background_premul.rgb *= background_premul.a; } }