diff --git a/src/base/base.cgh b/src/base/base.cgh index c3b22313..b50e4ae6 100644 --- a/src/base/base.cgh +++ b/src/base/base.cgh @@ -400,15 +400,17 @@ #define Rgba(r, g, b, a) VEC4((r), (g), (b), (a)) #define Rgb(r, g, b) VEC4((r), (g), (b), 1) -#define Color_White Rgba32(0xFFFFFFFF) -#define Color_Black Rgba32(0xFF000000) -#define Color_Red Rgba32(0xFF0000FF) -#define Color_Green Rgba32(0xFF00FF00) -#define Color_Blue Rgba32(0xFFFF0000) -#define Color_Yellow Rgba32(0xFF00FFFF) -#define Color_Orange Rgba32(0xFF00A5FF) -#define Color_Purple Rgba32(0xFFFF00FF) -#define Color_Cyan Rgba32(0xFFFFFF00) +#define Color_Transparent Rgba32(0) +#define Color_White Rgba32(0xFFFFFFFF) +#define Color_Black Rgba32(0xFF000000) +#define Color_Red Rgba32(0xFF0000FF) +#define Color_Green Rgba32(0xFF00FF00) +#define Color_Blue Rgba32(0xFFFF0000) +#define Color_Yellow Rgba32(0xFF00FFFF) +#define Color_Orange Rgba32(0xFF00A5FF) +#define Color_Purple Rgba32(0xFFFF00FF) +#define Color_Cyan Rgba32(0xFFFFFF00) + //////////////////////////////////////////////////////////// //~ Type helper macros diff --git a/src/gpu/gpu_shared.cgh b/src/gpu/gpu_shared.cgh index d079d05e..2d32accc 100644 --- a/src/gpu/gpu_shared.cgh +++ b/src/gpu/gpu_shared.cgh @@ -132,7 +132,7 @@ Struct(G_IndexBufferDesc) #endif //////////////////////////////////////////////////////////// -//~ Debug printf +//~ Shader printf Enum(G_FmtArgKind) { @@ -190,7 +190,7 @@ Struct(G_FmtArg) Struct(G_TempPrintBuffer) { - // NOTE: The larger the array size, the longer the compilation time + // NOTE: Large array sizes can increase shader compilation time u32 byte_chunks[64]; u32 bytes_count; u32 chars_count; diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index ba570e98..f2c4df15 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -4402,8 +4402,6 @@ void V_TickForever(WaveLaneCtx *lane) b32 scrollbar_visible = new_thumb_height < track_height; - - { f32 ease_rate = TweakFloat("Debug palette ease rate", 20, 1, 100) * frame->dt; f32 ease_in_target = TweakFloat("Debug palette ease-in target", 1.3, 0, 2); @@ -5495,24 +5493,6 @@ void V_TickForever(WaveLaneCtx *lane) } - - - - - - - - - - - - - - - - - - @@ -5758,10 +5738,16 @@ void V_TickForever(WaveLaneCtx *lane) - //- Visible zones + + //- Generate visible zones + Struct(VisZone) { + VisZone *parent; VisZone *next; + VisZone *next_bfs; + V_Zone *zone; + u32 depth; u64 id; String name; @@ -5788,18 +5774,9 @@ void V_TickForever(WaveLaneCtx *lane) VisTrack *first_vis_track = 0; VisTrack *last_vis_track = 0; - - - - - - - - - //- Compute visible zones f32 zone_collapse_threshold_px = 10; - f32 min_zone_width_px = 1; - ProfZoneDF("Compute visible zones") + f32 min_zone_width_px = 5; + ProfZoneDF("Generate visible zones") { for (V_ZoneTrack *zone_track = V.first_zone_track; zone_track; zone_track = zone_track->next) { @@ -5810,61 +5787,31 @@ void V_TickForever(WaveLaneCtx *lane) SllQueuePush(first_vis_track, last_vis_track, vis_track); vis_track->id = zone_track->id; - Struct(BfsZone) { BfsZone *next; V_Zone *zone; }; - BfsZone *first_bfs_zone = 0; - BfsZone *last_bfs_zone = 0; + VisZone *first_bfs_vis_zone = 0; + VisZone *last_bfs_vis_zone = 0; + // Push root vis zone node to bfs { - BfsZone *root_bfs = PushStruct(frame->arena, BfsZone); + VisZone *root_bfs = PushStruct(frame->arena, VisZone); root_bfs->zone = zone_track->root_zone; - SllQueuePush(first_bfs_zone, last_bfs_zone, root_bfs); + root_bfs->start_px = -Inf; + root_bfs->end_px = Inf; + root_bfs->start_ns = I64Min; + root_bfs->end_ns = I64Max; + root_bfs->id = zone_track->root_zone->id; + SllQueuePushN(first_bfs_vis_zone, last_bfs_vis_zone, root_bfs, next_bfs); } - VisZone *prev_vis_zone = 0; - V_Zone *prev_zone_parent = 0; - for (BfsZone *bfs_zone = first_bfs_zone; bfs_zone; bfs_zone = first_bfs_zone) + for (VisZone *parent_vis = first_bfs_vis_zone; parent_vis; parent_vis = first_bfs_vis_zone) { - SllQueuePop(first_bfs_zone, last_bfs_zone); - V_Zone *zone = bfs_zone->zone; + SllQueuePopN(first_bfs_vis_zone, last_bfs_vis_zone, next_bfs); + V_Zone *parent = parent_vis->zone; - i64 zone_start_ns = zone->start_ns; - i64 zone_end_ns = MinI64(zone->end_ns, frame->time_ns); - i64 zone_elapsed_ns = zone_end_ns - zone_start_ns; - i64 visual_zone_start_ns = MaxI64(zone_start_ns, profiler->view_ns); - i64 visual_zone_end_ns = MinI64(zone_end_ns, profiler->view_ns + view_range_len_ns); - - f64 visual_zone_start_px = visual_zone_start_ns / profiler->ns_per_px; - if (prev_vis_zone && prev_zone_parent == zone->parent) - // if (prev_vis_zone) - { - // visual_zone_start_px = MaxF64(visual_zone_start_px, prev_vis_zone->end_px + 1); - - // f64 px = prev_vis_zone->end_px; - // prev_vis_zone->end_px = CeilF64(px); - // visual_zone_start_px = MaxF64(visual_zone_start_px, CeilF64(prev_vis_zone->end_px)); - - f64 px = prev_vis_zone->end_px; - prev_vis_zone->end_px = FloorF64(px); - visual_zone_start_px = CeilF64(px); - } - - // f64 visual_zone_end_px = MaxF64(visual_zone_end_ns / profiler->ns_per_px, visual_zone_start_px + min_zone_width_px); - f64 visual_zone_end_px = visual_zone_end_ns / profiler->ns_per_px; - // f64 visual_zone_end_px = visual_zone_end_ns / profiler->ns_per_px - 1; - - - // visual_zone_start_px = FloorF64(visual_zone_start_px); - // visual_zone_end_px = CeilF64(visual_zone_end_px); - - - b32 is_root_zone = zone == zone_track->root_zone; - b32 should_collapse_zone = (zone_elapsed_ns / profiler->ns_per_px) <= zone_collapse_threshold_px && !is_root_zone; - - // Push children to bfs queue - if (!should_collapse_zone && visual_zone_end_ns >= view_start_ns && visual_zone_start_ns <= view_end_ns) + // Process child zones { + VisZone *left_vis = 0; b32 reached_end_of_view = 0; - for (V_ZoneChunk *chunk = zone->first_chunk; chunk && !reached_end_of_view; chunk = chunk->next) + for (V_ZoneChunk *chunk = parent->first_chunk; chunk && !reached_end_of_view; chunk = chunk->next) { i64 chunk_start_ns = chunk->zones[0].start_ns; i64 chunk_end_ns = MinI64(chunk->zones[chunk->count - 1].end_ns, frame->time_ns); @@ -5876,75 +5823,100 @@ void V_TickForever(WaveLaneCtx *lane) // TODO: Binary search to find start for (u64 chunk_zone_idx = 0; chunk_zone_idx < chunk->count && !reached_end_of_view; ++chunk_zone_idx) { - V_Zone *child = &chunk->zones[chunk_zone_idx]; - if (child->start_ns > view_end_ns) + V_Zone *zone = &chunk->zones[chunk_zone_idx]; + if (zone->start_ns > view_end_ns) { reached_end_of_view = 1; } else { - BfsZone *child_bfs = PushStruct(frame->arena, BfsZone); - child_bfs->zone = child; - SllQueuePush(first_bfs_zone, last_bfs_zone, child_bfs); + i64 zone_start_ns = zone->start_ns; + i64 zone_end_ns = MinI64(zone->end_ns, frame->time_ns); + i64 zone_elapsed_ns = zone_end_ns - zone_start_ns; + i64 visual_zone_start_ns = MaxI64(zone_start_ns, profiler->view_ns); + i64 visual_zone_end_ns = MinI64(zone_end_ns, profiler->view_ns + view_range_len_ns); + + f64 visual_zone_start_px = visual_zone_start_ns / profiler->ns_per_px; + f64 visual_zone_end_px = visual_zone_end_ns / profiler->ns_per_px; + + { + visual_zone_end_px = MaxF64(visual_zone_end_px, visual_zone_start_px + min_zone_width_px); + { + f32 overshoot = MaxF32(visual_zone_end_px - parent_vis->end_px, 0); + visual_zone_start_px -= overshoot; + visual_zone_end_px -= overshoot; + } + visual_zone_start_px = MaxF64(visual_zone_start_px, parent_vis->start_px); + if (left_vis) + { + visual_zone_start_px = MaxF64(visual_zone_start_px, left_vis->start_px); + } + } + + b32 should_collapse_zone = (visual_zone_end_px - visual_zone_start_px) <= zone_collapse_threshold_px; + + // Push vis zone + { + String zone_name = zone->name; + u64 zone_id = zone->id; + Vec4 zone_color = zone->color; + + // b32 should_collapse_zone = visual_zone_len_px <= zone_collapse_threshold_px; + // b32 should_collapse_zone = 0; + + // if (visual_zone_start_ns > view_end_ns) + // { + // reached_end_of_view = 1; + // } + + if (visual_zone_end_ns >= view_start_ns && visual_zone_start_ns <= view_end_ns) + { + VisZone *vis_zone = 0; + if ( + should_collapse_zone && + left_vis && + left_vis->collapsed_count > 0 && + ((zone_start_ns - left_vis->end_ns) / profiler->ns_per_px) < zone_collapse_threshold_px + ) + { + vis_zone = left_vis; + } + else + { + vis_zone = PushStruct(frame->arena, VisZone); + vis_zone->zone = zone; + vis_zone->parent = parent_vis; + vis_zone->start_ns = zone_start_ns; + vis_zone->start_px = visual_zone_start_px; + vis_zone->name = zone_name; + vis_zone->id = zone_id; + } + + SllQueuePush(vis_track->first_zone, vis_track->last_zone, vis_zone); + vis_zone->end_px = visual_zone_end_px; + vis_zone->end_ns = zone_end_ns; + vis_zone->color = zone_color; + vis_zone->depth = zone->depth; + vis_track->rows_count = MaxU32(vis_track->rows_count, vis_zone->depth); + + if (should_collapse_zone) + { + vis_zone->collapsed_count += zone->total_descendents_count + 1; + } + + left_vis = vis_zone; + + if (!should_collapse_zone) + { + SllQueuePushN(first_bfs_vis_zone, last_bfs_vis_zone, vis_zone, next_bfs); + } + } + } } } } } } - - // Push vis zone - if (!is_root_zone) - { - String zone_name = zone->name; - u64 zone_id = zone->id; - Vec4 zone_color = zone->color; - - // b32 should_collapse_zone = visual_zone_len_px <= zone_collapse_threshold_px; - // b32 should_collapse_zone = 0; - - // if (visual_zone_start_ns > view_end_ns) - // { - // reached_end_of_view = 1; - // } - - if (visual_zone_end_ns >= view_start_ns && visual_zone_start_ns <= view_end_ns) - { - VisZone *vis_zone = 0; - if ( - should_collapse_zone && - prev_vis_zone && - prev_vis_zone->collapsed_count > 0 && - prev_zone_parent == zone->parent && - ((zone_start_ns - prev_vis_zone->end_ns) / profiler->ns_per_px) < zone_collapse_threshold_px - ) - { - vis_zone = prev_vis_zone; - } - else - { - vis_zone = PushStruct(frame->arena, VisZone); - vis_zone->start_ns = zone_start_ns; - vis_zone->start_px = visual_zone_start_px; - vis_zone->name = zone_name; - vis_zone->id = zone_id; - } - - SllQueuePush(vis_track->first_zone, vis_track->last_zone, vis_zone); - vis_zone->end_px = visual_zone_end_px; - vis_zone->end_ns = zone_end_ns; - vis_zone->color = zone_color; - vis_zone->depth = zone->depth; - vis_track->rows_count = MaxU32(vis_track->rows_count, vis_zone->depth); - - if (should_collapse_zone) - { - vis_zone->collapsed_count += zone->total_descendents_count + 1; - } - - prev_vis_zone = vis_zone; - prev_zone_parent = zone->parent; - } - } } } } @@ -5970,6 +5942,9 @@ void V_TickForever(WaveLaneCtx *lane) main_color_unsampled.g *= 0.85; main_color_unsampled.b *= 0.85; + Vec4 collapsed_line_color = SrgbFromHsv(64, 1, 0.5); + Vec4 collapsed_text_color = SrgbFromHsv(64, 1, 0.75); + // main_color_sampled.g += 0.05; UI_SetNext(Parent, vis_ui_box); @@ -6091,6 +6066,7 @@ void V_TickForever(WaveLaneCtx *lane) f64 zone_offset_px = zone->start_px - view_start_px; f64 zone_len_px = zone->end_px - zone->start_px; + Vec2 zone_pos = VEC2(zone_offset_px, 0); UI_Size zone_width = UI_Px(zone_len_px, 1); @@ -6099,34 +6075,99 @@ void V_TickForever(WaveLaneCtx *lane) zone_color_bd = MulVec4(zone_color_bd, 0.65); zone_color_bd.a = 1; - zone_color_bd = LerpSrgb(zone_color_bd, Color_White, zone_hovered); Vec4 zone_text_color = UI_Top(TextColor); zone_text_color.a *= 0.75; + Vec4 zone_line_color = Zi; + // b32 is_collapsed = zone->is_collapsed; - b32 is_collapsed = zone->collapsed_count > 1; - UI_Size collapsed_line_size = UI_Fnt(0.1, 1); + b32 is_collapsed = zone->collapsed_count > 0; + // b32 is_collapsed = zone->collapsed_count > 0 || zone_len_px <= min_zone_width_px; + + // UI_Size collapsed_line_size = UI_Px(2, 1); + UI_Size collapsed_line_size = UI_Px(1.5, 1); // Vec4 collapsed_text_color = theme.col.positive; - Vec4 collapsed_line_color = theme.col.negative; + // Vec4 collapsed_line_color = theme.col.negative; + // Vec4 collapsed_line_color = SrgbFromHsv(TweakFloat("RAAAAAAAAAH H", 100, 0, 360), TweakFloat("RAAAAAAAAAH S", 0.50, 0, 1), TweakFloat("RAAAAAAAAAH V", 1.00, 0, 1)); + // Vec4 collapsed_line_color = Color_Black; // Vec4 collapsed_line_color = theme.col.hint; - Vec4 collapsed_text_color = theme.col.positive; - // Vec4 collapsed_line_color = collapsed_text_color; - collapsed_text_color = LerpSrgb(collapsed_text_color, Color_White, zone_hovered); - collapsed_line_color = LerpSrgb(collapsed_line_color, Color_White, zone_hovered); + // Vec4 collapsed_text_color = theme.col.positive; + // Vec4 collapsed_text_color = SrgbFromHsv(TweakFloat("RAAAAAAAAAH H", 100, 0, 360), TweakFloat("RAAAAAAAAAH S", 0.50, 0, 1), TweakFloat("RAAAAAAAAAH V", 1.00, 0, 1)); + + // Vec4 collapsed_line_color = SrgbFromHsv(32, 1, 0.5); + // Vec4 collapsed_text_color = SrgbFromHsv(32, 1, 1); + + // Vec4 collapsed_line_color = SrgbFromHsv(64, 1, 0.5); + // Vec4 collapsed_text_color = SrgbFromHsv(64, 1, 0.75); + + // collapsed_text_color = LerpSrgb(collapsed_text_color, Color_White, zone_hovered); + // collapsed_line_color = LerpSrgb(collapsed_line_color, Color_White, zone_hovered); + + + + String zone_text = zone->name; if (is_collapsed) { - zone_text = StringF(frame->arena, "%F", FmtUint(zone->collapsed_count)); + zone_text = Zstr; + if (zone->collapsed_count > 1) + { + zone_text = StringF(frame->arena, "%F", FmtUint(zone->collapsed_count)); + } zone_text_color = collapsed_text_color; + zone_line_color = collapsed_line_color; + // zone_color = VEC4(0, 0, 0, 0); // zone_color = VEC4(1, 0, 1, 1); // zone_color = VEC4(0.15, 0.15, 0.15, 0.5); - zone_color = VEC4(0.20, 0.20, 0.20, 0.5); + // zone_color = VEC4(0.20, 0.20, 0.20, 0.5); + + + zone_color = VEC4(0.25, 0.25, 0.25, 0.5); + + + // if (zone->collapsed_count > 1) + // { + // zone_color = VEC4(0.25, 0.25, 0.25, 0.5); + // } + // else + // { + // zone_color = Color_White; + // } + + + + // zone_color = VEC4(0.4, 0.4, 0.4, 0.5); zone_color_bd = VEC4(0, 0, 0, 0); + + // zone_color = LerpSrgb(zone_color, Color_Transparent, zone_hovered); + } + zone_color_bd = LerpSrgb(zone_color_bd, Color_White, zone_hovered * !is_collapsed); + zone_text_color = LerpSrgb(zone_text_color, Color_White, zone_hovered); + zone_line_color = LerpSrgb(zone_line_color, Color_White, zone_hovered); + + + f32 collapsed_zones_per_px = zone->collapsed_count / zone_len_px; + // f32 zag_intensity = 50 / collapsed_zones_per_px; + // zag_intensity = MaxF32(zag_intensity, 5); + + // f32 top_zag_information_density = 10; + f32 top_zag_information_density = zone_collapse_threshold_px; + f32 zag_intensity = SmoothstepF32(0, top_zag_information_density, collapsed_zones_per_px); + // f32 zag_intensity = TweakFloat("RAAAAAAAAAAAAAH", 1, 0, 1); + + f32 period_max = 20; + f32 period_min = 5; + f32 zag_period = LerpF32(period_max, period_min, zag_intensity); + + f32 amplitude_max = UI_Top(FontSize) * 0.15; + f32 amplitude_min = UI_Top(FontSize) * 0.05; + f32 zag_amplitude = LerpF32(amplitude_max, amplitude_min, zag_intensity); + UI_SetNext(Width, zone_width); UI_SetNext(Height, UI_Grow(1, 0)); UI_SetNext(BackgroundColor, zone_color); @@ -6134,41 +6175,48 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetNext(BorderSize, 1); UI_SetNext(FloatingPos, zone_pos); UI_SetNext(ChildAlignment, UI_Region_Center); - UI_SetNext(Flags, UI_BoxFlag_Floating | UI_BoxFlag_DontClampFloatingX | UI_BoxFlag_DontClampFloatingY | UI_BoxFlag_CaptureMouse | UI_BoxFlag_Scissor); + UI_SetNext( + Flags, + UI_BoxFlag_Floating | + UI_BoxFlag_DontClampFloatingX | + UI_BoxFlag_DontClampFloatingY | + UI_BoxFlag_CaptureMouse | + UI_BoxFlag_Scissor + ); UI_SetNext(Parent, zone_row_box); UI_SetDF(OrFlags, UI_Top(OrFlags) | (UI_BoxFlag_DontTruncateText * !!(is_collapsed))) - UI_SetDF(OmitFlags, UI_Top(OmitFlags) | (UI_BoxFlag_Scissor * !!(is_collapsed))) + // UI_SetDF(OmitFlags, UI_Top(OmitFlags) | (UI_BoxFlag_Scissor * !!(is_collapsed))) + // UI_SetDF(ZagPeriod, UI_Top(FontSize) * 1) + // UI_SetDF(ZagPeriod, (collapsed_zones_per_px * UI_Top(FontSize)) * 0.1) + // UI_SetDF(ZagPeriod, collapsed_zones_per_px / (UI_Top(FontSize) * 1)) + UI_SetDF(ZagPeriod, zag_period) + UI_SetDF(ZagThickness, 1.5) + UI_SetDF(ZagRoundness, 0) + UI_SetDF(ZagAmplitude, zag_amplitude) UI_SetDF(Parent, UI_BuildRowEx(zone_box)) { // Left collapsed lines if (is_collapsed) { - // Vertical line - { - UI_SetDF(Opacity, 1.0 - zone_hovered) - UI_SetNext(BackgroundColor, collapsed_line_color); - UI_SetNext(Width, collapsed_line_size); - UI_SetNext(Height, UI_Grow(1, 0)); - UI_BuildBox(); - } + // // Vertical line + // { + // UI_SetDF(Opacity, 1.0 - zone_hovered) + // UI_SetNext(BackgroundColor, collapsed_line_color); + // UI_SetNext(Width, collapsed_line_size); + // UI_SetNext(Height, UI_Grow(1, 0)); + // UI_BuildBox(); + // } - // Horizontal line - UI_SetDF(Parent, UI_BuildColumn()) + // Zag { - UI_BuildSpacer(UI_Grow(1, 0), Axis_Y); - UI_SetNext(Width, UI_Grow(1, 0)); - UI_SetNext(Height, collapsed_line_size); - // UI_SetNext(Anchor, UI_Region_Center); - UI_SetNext(BackgroundColor, collapsed_line_color); + UI_SetNext(ZagColor, zone_line_color); UI_BuildBox(); - - UI_BuildSpacer(UI_Grow(1, 0), Axis_Y); } } // Zone name - if (zone_len_px > zone_collapse_threshold_px * 3) + // if (zone_len_px > zone_collapse_threshold_px * 3) { if (is_collapsed) { @@ -6189,29 +6237,22 @@ void V_TickForever(WaveLaneCtx *lane) // Right collapsed lines if (is_collapsed) { - // Horizontal line - // UI_SetNext(Flags, UI_BoxFlag_Floating); - // UI_SetDF(Opacity, 0.25) - UI_SetDF(Parent, UI_BuildColumn()) + // Zag { - UI_BuildSpacer(UI_Grow(1, 0), Axis_Y); - UI_SetNext(Width, UI_Grow(1, 0)); - UI_SetNext(Height, collapsed_line_size); - // UI_SetNext(Anchor, UI_Region_Center); - UI_SetNext(BackgroundColor, collapsed_line_color); - UI_BuildBox(); - - UI_BuildSpacer(UI_Grow(1, 0), Axis_Y); - } - - // Vertical line - { - UI_SetNext(BackgroundColor, collapsed_line_color); - UI_SetNext(Width, collapsed_line_size); - UI_SetNext(Height, UI_Grow(1, 0)); + UI_SetNext(ZagColor, zone_line_color); UI_BuildBox(); } + + // // Vertical line + // { + // UI_SetDF(Opacity, 1.0 - zone_hovered) + // UI_SetNext(BackgroundColor, collapsed_line_color); + // UI_SetNext(Width, collapsed_line_size); + // UI_SetNext(Height, UI_Grow(1, 0)); + // UI_SetNext(Anchor, UI_Region_Right); + // UI_BuildBox(); + // } } } } @@ -6347,10 +6388,9 @@ void V_TickForever(WaveLaneCtx *lane) UI_SetDF(Parent, UI_BuildRow()) { UI_SetNext(TextColor, theme.col.hint); - // UI_BuildLabelF("Collapsed zones"); - UI_BuildLabelF("Multiple zones"); + UI_BuildLabelF("Zones too small to display"); - UI_SetNext(TextColor, theme.col.positive); + UI_SetNext(TextColor, collapsed_text_color); UI_BuildLabelF(" (%F)", FmtUint(zone->collapsed_count)); } } @@ -6408,39 +6448,6 @@ void V_TickForever(WaveLaneCtx *lane) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ////////////////////////////// //- Build notifications diff --git a/src/ui/ui_core.c b/src/ui/ui_core.c index 362f7780..8e60e2fd 100644 --- a/src/ui/ui_core.c +++ b/src/ui/ui_core.c @@ -489,6 +489,11 @@ UI_Key UI_BuildBoxEx(UI_Key semantic_key) n->cmd.box.sprite_span = UI_Top(SpriteSpan); n->cmd.box.sprite_seq = UI_Top(SpriteSeq); n->cmd.box.misc = UI_Top(Misc); + n->cmd.box.zag_color = UI_Top(ZagColor); + n->cmd.box.zag_period = UI_Top(ZagPeriod); + n->cmd.box.zag_amplitude = UI_Top(ZagAmplitude); + n->cmd.box.zag_thickness = UI_Top(ZagThickness); + n->cmd.box.zag_roundness = UI_Top(ZagRoundness); } ++frame->cmds_count; SllQueuePush(frame->first_cmd_node, frame->last_cmd_node, n); @@ -1831,10 +1836,10 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) final_tint_lin.a *= box->solved_opacity; Vec4 final_border_color_lin = LinearFromSrgb(box->desc.border_color); - final_border_color_lin.a *= box->solved_opacity; + + Vec4 final_zag_lin = LinearFromSrgb(box->desc.zag_color); Vec4 final_text_color_lin = LinearFromSrgb(box->desc.text_color); - final_text_color_lin.a *= box->desc.opacity; final_text_color_lin = MulVec4Vec4(final_text_color_lin, final_tint_lin); f32 alpha_cull_threshold = 0.0025; @@ -1851,7 +1856,8 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) !SPR_IsSheetKeyNil(box->desc.sprite_sheet) || (AnyBit(box->desc.flags, UI_BoxFlag_DrawText) && raw_run.ready) || final_tint_lin.a * box->desc.background_color.a >= alpha_cull_threshold || - final_tint_lin.a * box->desc.border_color.a >= alpha_cull_threshold + final_tint_lin.a * box->desc.border_color.a >= alpha_cull_threshold || + (box->desc.zag_thickness > 0 && final_tint_lin.a * final_zag_lin.a >= alpha_cull_threshold) ); should_upload_box = should_upload_box && (!IsRng2Empty(IntersectRng2(box->screen_rect, box->solved_scissor))); should_upload_text = should_upload_text && should_upload_box && final_text_color_lin.a > alpha_cull_threshold; @@ -1879,6 +1885,11 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync) rect->tr_rounding = box->rounding_tr; rect->br_rounding = box->rounding_br; rect->bl_rounding = box->rounding_bl; + rect->zag_lin = final_zag_lin; + rect->zag_period = box->desc.zag_period; + rect->zag_amplitude = box->desc.zag_amplitude; + rect->zag_thickness = box->desc.zag_thickness; + rect->zag_roundness = box->desc.zag_roundness; if (!G_IsRefNil(box->raw_texture)) { rect->tex = box->raw_texture; diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 7393f900..9fcd6595 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -152,6 +152,11 @@ Enum(UI_DebugBreakFlag) X(BackgroundTexture, G_TextureRef) \ X(BackgroundTextureSliceUv, Rng2) \ X(Misc, f64) \ + X(ZagColor, Vec4) \ + X(ZagPeriod, f32) \ + X(ZagAmplitude, f32) \ + X(ZagThickness, f32) \ + X(ZagRoundness, f32) \ /* --------------------------------------------- */ \ /* --------------- Virtual styles -------------- */ \ /* --------------------------------------------- */ \ @@ -290,6 +295,11 @@ Struct(UI_BoxDesc) SPR_SpanKey sprite_span; i64 sprite_seq; f64 misc; + Vec4 zag_color; + f32 zag_period; + f32 zag_amplitude; + f32 zag_thickness; + f32 zag_roundness; }; Struct(UI_Cmd) diff --git a/src/ui/ui_gpu.g b/src/ui/ui_gpu.g index 835c9d9c..66f4e0ac 100644 --- a/src/ui/ui_gpu.g +++ b/src/ui/ui_gpu.g @@ -20,6 +20,7 @@ VertexShader(UI_DRectVS, UI_DRectPSInput) result.base_background_premul = Premul(rect.background_lin); result.base_border_premul = Premul(rect.border_lin); result.tint_premul = Premul(rect.tint_lin); + result.zag_premul = Premul(rect.zag_lin); result.debug_premul = Premul(rect.debug_lin); result.rect_uv = rect_uv; result.tex_uv = tex_uv; @@ -77,6 +78,33 @@ PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input) background_premul = tex.SampleLevel(sampler, input.tex_uv, 0); background_premul.rgb *= background_premul.a; } + + //- Blend zig-zag color + if (rect.zag_thickness > 0 && input.zag_premul.a != 0) + { + f32 zag_strength = 0; + { + f32 period = rect.zag_period; + f32 amplitude = rect.zag_amplitude; + f32 thickness = rect.zag_thickness; + f32 roundness = rect.zag_roundness; + { + f32 center_y = (p1.y - p0.y) * 0.5f; + f32 z = 0; + { + f32 x = p.x / period; + f32 tri_wave = abs(frac(x) * 2 - 1) * 2 - 1; + f32 sin_wave = sin(x * Tau); + z = lerp(tri_wave, sin_wave, roundness); + } + f32 y = center_y + z * amplitude; + f32 d = abs((p.y - p0.y) - y); + f32 smoothness = 1; + zag_strength = 1.0 - smoothstep(thickness - smoothness, thickness + smoothness, d); + } + } + background_premul = lerp(background_premul, input.zag_premul, zag_strength); + } } //- Compute border dist diff --git a/src/ui/ui_gpu.gh b/src/ui/ui_gpu.gh index 1400d698..b2922136 100644 --- a/src/ui/ui_gpu.gh +++ b/src/ui/ui_gpu.gh @@ -7,6 +7,7 @@ Struct(UI_DRectPSInput) Vec4 Semantic(base_background_premul); Vec4 Semantic(base_border_premul); Vec4 Semantic(tint_premul); + Vec4 Semantic(zag_premul); Vec4 Semantic(debug_premul); Vec2 Semantic(rect_uv); Vec2 Semantic(tex_uv); diff --git a/src/ui/ui_shared.cgh b/src/ui/ui_shared.cgh index fcc3f449..6b07aa63 100644 --- a/src/ui/ui_shared.cgh +++ b/src/ui/ui_shared.cgh @@ -25,6 +25,12 @@ Struct(UI_GpuRect) f32 tr_rounding; f32 br_rounding; f32 bl_rounding; + + Vec4 zag_lin; + f32 zag_period; + f32 zag_amplitude; + f32 zag_thickness; + f32 zag_roundness; }; ////////////////////////////////////////////////////////////