ogl_beamforming

Ultrasound Beamforming Implemented with OpenGL
git clone anongit@rnpnr.xyz:ogl_beamforming.git
Log | Files | Refs | Feed | Submodules | LICENSE

Commit: a368b6148ec8d0204f8ab5c33ee5356fd8681eac
Parent: d606181dcbd5ce863064b3a9fcd2e3873df9f44b
Author: Randy Palamar
Date:   Mon,  9 Sep 2024 09:48:58 -0600

re-add off_axis_pos and add beamform plane to ui

Diffstat:
Mbeamformer_parameters.h | 3++-
Mshaders/demod.glsl | 2++
Mshaders/hadamard.glsl | 2++
Mshaders/hercules.glsl | 7++++---
Mshaders/uforces.glsl | 2++
Mui.c | 49++++++++++++++++++++++++++++++++++++++++++++++---
6 files changed, 58 insertions(+), 7 deletions(-)

diff --git a/beamformer_parameters.h b/beamformer_parameters.h @@ -31,5 +31,6 @@ typedef struct { f32 focal_depth; /* [m] */ f32 time_offset; /* pulse length correction time [s] */ u32 uforces; /* mode is UFORCES (1) or FORCES (0) */ - f32 _pad[2]; + f32 off_axis_pos; /* [m] Position on screen normal to beamform in 2D HERCULES */ + i32 beamform_plane; /* Plane to Beamform in 2D HERCULES */ } BeamformerParameters; diff --git a/shaders/demod.glsl b/shaders/demod.glsl @@ -29,6 +29,8 @@ layout(std140, binding = 0) uniform parameters { float focal_depth; /* [m] */ float time_offset; /* pulse length correction time [s] */ uint uforces; /* mode is UFORCES (1) or FORCES (0) */ + float off_axis_pos; /* [m] Position on screen normal to beamform in 2D HERCULES */ + int beamform_plane; /* Plane to Beamform in 2D HERCULES */ }; void main() diff --git a/shaders/hadamard.glsl b/shaders/hadamard.glsl @@ -33,6 +33,8 @@ layout(std140, binding = 0) uniform parameters { float focal_depth; /* [m] */ float time_offset; /* pulse length correction time [s] */ uint uforces; /* mode is UFORCES (1) or FORCES (0) */ + float off_axis_pos; /* [m] Position on screen normal to beamform in 2D HERCULES */ + int beamform_plane; /* Plane to Beamform in 2D HERCULES */ }; void main() diff --git a/shaders/hercules.glsl b/shaders/hercules.glsl @@ -25,6 +25,8 @@ layout(std140, binding = 0) uniform parameters { float focal_depth; /* [m] */ float time_offset; /* pulse length correction time [s] */ uint uforces; /* mode is UFORCES (1) or FORCES (0) */ + float off_axis_pos; /* [m] Position on screen normal to beamform in 2D HERCULES */ + int beamform_plane; /* Plane to Beamform in 2D HERCULES */ }; layout(rg32f, location = 1) uniform writeonly image3D u_out_data_tex; @@ -81,9 +83,8 @@ void main() vec4 output_size = abs(output_max_coord - output_min_coord); vec3 image_point = output_min_coord.xyz + voxel * output_size.xyz / out_data_dim.xyz; - /* TODO: off_axis_position */ if (u_volume_export_pass == 0) - image_point.y = 0; + image_point.y = off_axis_pos; /* NOTE: used for constant F# dynamic receive apodization. This is implemented as: * @@ -108,7 +109,7 @@ void main() vec2 sum = vec2(0); vec3 rdist = starting_dist; - int direction = 1 * (u_volume_export_pass ^ 1); + int direction = beamform_plane * (u_volume_export_pass ^ 1); uint ridx = 0; /* NOTE: For Each Acquistion in Raw Data */ for (uint i = 0; i < dec_data_dim.z; i++) { diff --git a/shaders/uforces.glsl b/shaders/uforces.glsl @@ -25,6 +25,8 @@ layout(std140, binding = 0) uniform parameters { float focal_depth; /* [m] */ float time_offset; /* pulse length correction time [s] */ uint uforces; /* mode is UFORCES (1) or FORCES (0) */ + float off_axis_pos; /* [m] Position on screen normal to beamform in 2D HERCULES */ + int beamform_plane; /* Plane to Beamform in 2D HERCULES */ }; layout(rg32f, location = 1) writeonly uniform image3D u_out_data_tex; diff --git a/ui.c b/ui.c @@ -406,6 +406,41 @@ do_text_input_listing(s8 prefix, s8 suffix, BPModifiableValue bmv, BeamformerCtx return r; } +static Rect +do_text_toggle_listing(s8 prefix, s8 text0, s8 text1, i32 *toggle, b32 causes_compute, + BeamformerCtx *ctx, Rect r, v2 mouse, f32 *hover_t) +{ + v2 txt_s; + if (*toggle) txt_s = measure_text(ctx->font, text1); + else txt_s = measure_text(ctx->font, text0); + + Rect edit_rect = { + .pos = {.x = r.pos.x + LISTING_LEFT_COLUMN_WIDTH, .y = r.pos.y}, + .size = {.x = txt_s.w + TEXT_BOX_EXTRA_X, .y = txt_s.h} + }; + + b32 collides = CheckCollisionPointRec(mouse.rl, edit_rect.rl); + if (collides) *hover_t += TEXT_HOVER_SPEED * ctx->dt; + else *hover_t -= TEXT_HOVER_SPEED * ctx->dt; + CLAMP01(*hover_t); + + b32 pressed = IsMouseButtonPressed(MOUSE_BUTTON_LEFT) || IsMouseButtonPressed(MOUSE_BUTTON_RIGHT); + if (collides && (pressed || GetMouseWheelMove())) { + *toggle = !(*toggle); + if (causes_compute) + ctx->flags |= DO_COMPUTE; + } + + Color colour = colour_from_normalized(lerp_v4(FG_COLOUR, HOVERED_COLOUR, *hover_t)); + draw_text(ctx->font, prefix, r.pos, 0, colour_from_normalized(FG_COLOUR)); + draw_text(ctx->font, *toggle? text1: text0, edit_rect.pos, 0, colour); + + r.pos.y += txt_s.h + LISTING_LINE_PAD; + r.size.y -= txt_s.h + LISTING_LINE_PAD; + + return r; +} + static b32 do_text_button(BeamformerCtx *ctx, s8 text, Rect r, v2 mouse, f32 *hover_t) { @@ -458,7 +493,7 @@ draw_settings_ui(BeamformerCtx *ctx, Arena arena, Rect r, v2 mouse) draw_r = do_value_listing(s8("Sampling Frequency:"), s8("[MHz]"), bp->sampling_frequency * 1e-6, ctx->font, arena, draw_r); - static f32 hover_t[11]; + static f32 hover_t[13]; i32 idx = 0; BPModifiableValue bmv; @@ -492,13 +527,21 @@ draw_settings_ui(BeamformerCtx *ctx, Arena arena, Rect r, v2 mouse) draw_r = do_text_input_listing(s8("Max Axial Point:"), s8("[mm]"), bmv, ctx, arena, draw_r, mouse, hover_t + idx++); + bmv = (BPModifiableValue){&bp->off_axis_pos, MV_FLOAT|MV_CAUSES_COMPUTE, 1e3, + .flimits = (v2){.x = -1, .y = 1}}; + draw_r = do_text_input_listing(s8("Off Axis Position:"), s8("[mm]"), bmv, ctx, arena, + draw_r, mouse, hover_t + idx++); + + draw_r = do_text_toggle_listing(s8("Beamform Plane:"), s8("XZ"), s8("YZ"),&bp->beamform_plane, + 1, ctx, draw_r, mouse, hover_t + idx++); + bmv = (BPModifiableValue){&ctx->fsctx.db, MV_FLOAT|MV_GEN_MIPMAPS, 1, .flimits = (v2){.x = -120}}; draw_r = do_text_input_listing(s8("Dynamic Range:"), s8("[dB]"), bmv, ctx, arena, draw_r, mouse, hover_t + idx++); - draw_r.pos.y += 4 * LISTING_LINE_PAD; - draw_r.size.y -= 4 * LISTING_LINE_PAD; + draw_r.pos.y += 2 * LISTING_LINE_PAD; + draw_r.size.y -= 2 * LISTING_LINE_PAD; bmv = (BPModifiableValue){&ctx->export_ctx.volume_dim.x, MV_INT|MV_POWER_OF_TWO, 1, .ilimits = (iv2){.x = 1, .y = 2048}};