From 3d0d49b442ea6732af65c947faa916d3f4b632e3 Mon Sep 17 00:00:00 2001 From: Juhu <5894800-Juhu_@users.noreply.gitlab.com> Date: Tue, 17 Sep 2024 20:33:37 +0200 Subject: [PATCH] strafehud: implemented faster gradient utilizing only a few polygon vertices --- _hud_common.cfg | 2 +- qcsrc/client/hud/panel/strafehud.qc | 2 +- qcsrc/client/hud/panel/strafehud.qh | 1 + qcsrc/client/hud/panel/strafehud/draw.qc | 95 +++++++++++++++++++++--- qcsrc/client/hud/panel/strafehud/draw.qh | 1 + 5 files changed, 88 insertions(+), 13 deletions(-) diff --git a/_hud_common.cfg b/_hud_common.cfg index 383d9cd85..d6f5648ab 100644 --- a/_hud_common.cfg +++ b/_hud_common.cfg @@ -157,7 +157,7 @@ seta hud_panel_scoreboard_itemstats_showdelay_minpos 0.75 "delay displaying the seta _hud_panel_strafehud_demo "0" "strafehud changes angle during configure" seta hud_panel_strafehud_mode "0" "strafehud mode which controls whether the strafehud is centered at \"0\" = view angle, \"1\" = velocity angle" seta hud_panel_strafehud_range "90" "the angle range up to 360 degrees displayed on the strafehud, \"-1\" = current fov, \"0\" = dynamic (chooses the minimum range required to still see the whole area needed for accelerating)" -seta hud_panel_strafehud_style "2" "\"0\" = no styling, \"1\" = progress bar style for the strafe bar, \"2\" = gradient for the strafe bar" +seta hud_panel_strafehud_style "2" "\"0\" = no styling, \"1\" = progress bar style for the strafe bar, \"2\" = gradient for the strafe bar, \"3\" = fast gradient for the strafe bar (requires linear projection mode)" seta hud_panel_strafehud_unit_show "1" "show units" seta hud_panel_strafehud_bar_preaccel "1" "set to \"1\" to extend the acceleration zone by the strafe meter zone before full acceleration can be achieved" seta hud_panel_strafehud_bar_neutral_color "1 1 1" "color of the strafe meter neutral zone" diff --git a/qcsrc/client/hud/panel/strafehud.qc b/qcsrc/client/hud/panel/strafehud.qc index ec4893bce..2bf08dec2 100644 --- a/qcsrc/client/hud/panel/strafehud.qc +++ b/qcsrc/client/hud/panel/strafehud.qc @@ -416,7 +416,7 @@ void HUD_StrafeHUD() strafe_ratio = (moveangle - absolute_prebestangle) / (absolute_bestangle - absolute_prebestangle); } - if(autocvar_hud_panel_strafehud_style == STRAFEHUD_STYLE_GRADIENT) + if(autocvar_hud_panel_strafehud_style == STRAFEHUD_STYLE_GRADIENT || autocvar_hud_panel_strafehud_style == STRAFEHUD_STYLE_FAST_GRADIENT) currentangle_color = StrafeHUD_MixColors( autocvar_hud_panel_strafehud_angle_neutral_color, currentangle_color, fabs(strafe_ratio)); diff --git a/qcsrc/client/hud/panel/strafehud.qh b/qcsrc/client/hud/panel/strafehud.qh index 1c1a3d934..0ce6cb515 100644 --- a/qcsrc/client/hud/panel/strafehud.qh +++ b/qcsrc/client/hud/panel/strafehud.qh @@ -93,6 +93,7 @@ const int STRAFEHUD_KEYS_BACKWARD = 2; const int STRAFEHUD_STYLE_DRAWFILL = 0; const int STRAFEHUD_STYLE_PROGRESSBAR = 1; const int STRAFEHUD_STYLE_GRADIENT = 2; +const int STRAFEHUD_STYLE_FAST_GRADIENT = 3; const int STRAFEHUD_GRADIENT_NONE = 0; const int STRAFEHUD_GRADIENT_LEFT = 1; diff --git a/qcsrc/client/hud/panel/strafehud/draw.qc b/qcsrc/client/hud/panel/strafehud/draw.qc index 9f94a1bc0..1e5789a8c 100644 --- a/qcsrc/client/hud/panel/strafehud/draw.qc +++ b/qcsrc/client/hud/panel/strafehud/draw.qc @@ -10,14 +10,14 @@ void StrafeHUD_DrawStrafeHUD(float startangle, float offsetangle, vector color, float mirror_offset; float mirror_width; - if(type == STRAFEHUD_STYLE_GRADIENT) + if(type == STRAFEHUD_STYLE_GRADIENT || type == STRAFEHUD_STYLE_FAST_GRADIENT) { projectWidth = true; // must be fully projected for gradients if(gradientType == STRAFEHUD_GRADIENT_NONE) type = STRAFEHUD_STYLE_DRAWFILL; } - if(alpha <= 0 && type != STRAFEHUD_STYLE_GRADIENT || width <= 0) + if(alpha <= 0 && type != STRAFEHUD_STYLE_GRADIENT && type != STRAFEHUD_STYLE_FAST_GRADIENT || width <= 0) return; // how much is hidden by the current hud angle @@ -101,6 +101,7 @@ void StrafeHUD_DrawStrafeHUD(float startangle, float offsetangle, vector color, break; case STRAFEHUD_STYLE_GRADIENT: // gradient style (types: 1 = left, 2 = right, 3 = both) + case STRAFEHUD_STYLE_FAST_GRADIENT: // determine whether the gradient starts in the mirrored or the non-mirrored area int gradient_start; float gradient_offset, gradient_mirror_offset; @@ -129,21 +130,38 @@ void StrafeHUD_DrawStrafeHUD(float startangle, float offsetangle, vector color, gradient_mirror_offset = 0; } - StrafeHUD_DrawGradient( - color, autocvar_hud_panel_strafehud_bar_neutral_color, - mirror_size, original_width, mirror_offset, original_mirror_offset, - alpha, gradient_mirror_offset, gradientType, range); + if(type == STRAFEHUD_STYLE_FAST_GRADIENT && autocvar_hud_panel_strafehud_projection == STRAFEHUD_PROJECTION_LINEAR) + { + StrafeHUD_DrawGradientFast( + color, autocvar_hud_panel_strafehud_bar_neutral_color, + mirror_size, original_width, mirror_offset, alpha, + gradient_mirror_offset, gradientType); + + StrafeHUD_DrawGradientFast( + color, autocvar_hud_panel_strafehud_bar_neutral_color, + size, original_width, offset, alpha, + gradient_offset, gradientType); + } + else + { + StrafeHUD_DrawGradient( + color, autocvar_hud_panel_strafehud_bar_neutral_color, + mirror_size, original_width, mirror_offset, original_mirror_offset, + alpha, gradient_mirror_offset, gradientType, range); - StrafeHUD_DrawGradient( - color, autocvar_hud_panel_strafehud_bar_neutral_color, - size, original_width, offset, original_offset, - alpha, gradient_offset, gradientType, range); + StrafeHUD_DrawGradient( + color, autocvar_hud_panel_strafehud_bar_neutral_color, + size, original_width, offset, original_offset, + alpha, gradient_offset, gradientType, range); + } } } -// FIXME: this is very bad for performance, there should be a better way to draw gradients +// slow gradient, required for projection modes other than linear void StrafeHUD_DrawGradient(vector color1, vector color2, vector size, float original_width, float offset, float original_offset, float alpha, float gradientOffset, int gradientType, float range) { + if(size.x <= 0) return; + float color_ratio, alpha1, alpha2; vector segment_size = size; alpha1 = bound(0, alpha, 1); @@ -176,6 +194,61 @@ void StrafeHUD_DrawGradient(vector color1, vector color2, vector size, float ori } } +// optimized gradient, does not work with projection modes other than linear, decreased visual fidelity +void StrafeHUD_DrawGradientFast(vector color1, vector color2, vector size, float original_width, float offset, float alpha, float gradientOffset, int gradientType) +{ + if(size.x <= 0) return; + + if(gradientType == STRAFEHUD_GRADIENT_BOTH) + { + original_width /= 2; + + vector size1 = size; + size1.x = bound(0, original_width - gradientOffset, size.x); + + vector size2 = size; + size2.x = size.x - size1.x; + + if(size1.x > 0) + StrafeHUD_DrawGradientFast(color1, color2, size1, original_width, offset, alpha, gradientOffset, STRAFEHUD_GRADIENT_LEFT); + + if(size2.x > 0) + StrafeHUD_DrawGradientFast(color1, color2, size2, original_width, offset + size1.x, alpha, max(0, gradientOffset - original_width), STRAFEHUD_GRADIENT_RIGHT); + + return; + } + + float alpha1 = bound(0, alpha, 1); + float alpha2 = bound(0, autocvar_hud_panel_strafehud_bar_neutral_alpha * panel_fg_alpha, 1); + if((alpha1 + alpha2) == 0) return; + + float ratio1 = gradientOffset / original_width; + if(gradientType == STRAFEHUD_GRADIENT_LEFT) + ratio1 = 1 - ratio1; + + float ratio2 = (gradientOffset + size.x) / original_width; + if(gradientType == STRAFEHUD_GRADIENT_LEFT) + ratio2 = 1 - ratio2; + + vector origin = HUD_Shift(panel_pos); + offset = HUD_ScaleX(offset); + size = HUD_Scale(size); + + R_BeginPolygon("", DRAWFLAG_NORMAL, true); + R_PolygonVertex(origin + eX * offset, '0 0 0', color1, alpha1 * (1 - ratio1)); + R_PolygonVertex(origin + eX * offset + eY * size.y, '0 0 0', color1, alpha1 * (1 - ratio1)); + R_PolygonVertex(origin + eX * (offset + size.x) + eY * size.y, '0 0 0', color1, alpha1 * (1 - ratio2)); + R_PolygonVertex(origin + eX * (offset + size.x), '0 0 0', color1, alpha1 * (1 - ratio2)); + R_EndPolygon(); + + R_BeginPolygon("", DRAWFLAG_NORMAL, true); + R_PolygonVertex(origin + eX * offset, '0 0 0', color2, alpha2 * ratio1); + R_PolygonVertex(origin + eX * offset + eY * size.y, '0 0 0', color2, alpha2 * ratio1); + R_PolygonVertex(origin + eX * (offset + size.x) + eY * size.y, '0 0 0', color2, alpha2 * ratio2); + R_PolygonVertex(origin + eX * (offset + size.x), '0 0 0', color2, alpha2 * ratio2); + R_EndPolygon(); +} + // draw the strafe arrows (inspired by drawspritearrow() in common/mutators/mutator/waypoints/waypointsprites.qc) void StrafeHUD_DrawStrafeArrow(vector origin, float size, vector color, float alpha, bool flipped, float connection_width) { diff --git a/qcsrc/client/hud/panel/strafehud/draw.qh b/qcsrc/client/hud/panel/strafehud/draw.qh index 1f366a20f..b3ec1a26e 100644 --- a/qcsrc/client/hud/panel/strafehud/draw.qh +++ b/qcsrc/client/hud/panel/strafehud/draw.qh @@ -3,5 +3,6 @@ void StrafeHUD_DrawStrafeHUD(float, float, vector, float, int, int, bool, float); void StrafeHUD_DrawGradient(vector, vector, vector, float, float, float, float, float, int, float); +void StrafeHUD_DrawGradientFast(vector, vector, vector, float, float, float, float, int); void StrafeHUD_DrawStrafeArrow(vector, float, vector, float, bool, float); bool StrafeHUD_DrawTextIndicator(string, float, vector, float, float, float, int); -- 2.39.2