diff options
Diffstat (limited to 'source')
8 files changed, 282 insertions, 76 deletions
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index bb6bc0db00d..a983821f15e 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -524,6 +524,15 @@ MINLINE uint max_uu(uint a, uint b) return (b < a) ? a : b; } +MINLINE unsigned long long min_ulul(unsigned long long a, unsigned long long b) +{ + return (a < b) ? a : b; +} +MINLINE unsigned long long max_ulul(unsigned long long a, unsigned long long b) +{ + return (b < a) ? a : b; +} + MINLINE float min_fff(float a, float b, float c) { return min_ff(min_ff(a, b), c); diff --git a/source/blender/editors/gizmo_library/gizmo_draw_utils.c b/source/blender/editors/gizmo_library/gizmo_draw_utils.c index 8d2aec18451..c6303c197e7 100644 --- a/source/blender/editors/gizmo_library/gizmo_draw_utils.c +++ b/source/blender/editors/gizmo_library/gizmo_draw_utils.c @@ -82,9 +82,35 @@ void wm_gizmo_vec_draw( const float color[4], const float (*verts)[3], uint vert_count, uint pos, uint primitive_type) { immUniformColor4fv(color); - immBegin(primitive_type, vert_count); - for (int i = 0; i < vert_count; i++) { - immVertex3fv(pos, verts[i]); + + if (primitive_type == GPU_PRIM_LINE_LOOP) { + /* Line loop alternative for Metal/Vulkan. */ + immBegin(GPU_PRIM_LINES, vert_count * 2); + immVertex3fv(pos, verts[0]); + for (int i = 1; i < vert_count; i++) { + immVertex3fv(pos, verts[i]); + immVertex3fv(pos, verts[i]); + } + immVertex3fv(pos, verts[0]); + immEnd(); + } + else if (primitive_type == GPU_PRIM_TRI_FAN) { + /* Note(Metal): Tri-fan alternative for Metal. Triangle List is more efficient for small + * primitive counts. */ + int tri_count = vert_count - 2; + immBegin(GPU_PRIM_TRIS, tri_count * 3); + for (int i = 0; i < tri_count; i++) { + immVertex3fv(pos, verts[0]); + immVertex3fv(pos, verts[i + 1]); + immVertex3fv(pos, verts[i + 2]); + } + immEnd(); + } + else { + immBegin(primitive_type, vert_count); + for (int i = 0; i < vert_count; i++) { + immVertex3fv(pos, verts[i]); + } + immEnd(); } - immEnd(); } diff --git a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c index 5e20cc73f1a..b326d6d1859 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c @@ -74,20 +74,21 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz, GPU_viewport_size_get_f(viewport); GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + /* Note(Metal): Prefer 3D coordinate for 2D rendering when using 3D shader. */ + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); /* TODO: other draw styles. */ if (color[3] == 1.0 && fill_alpha == 1.0 && select == false) { immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(color); - imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION); + imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, 1.0f, CIRCLE_RESOLUTION); immUnbindProgram(); immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); immUniform2fv("viewportSize", &viewport[2]); immUniform1f("lineWidth", gz->line_width * U.pixelsize); immUniformColor4fv(color); - imm_draw_circle_wire_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, 1.0f, CIRCLE_RESOLUTION); immUnbindProgram(); } else { @@ -96,7 +97,7 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz, const float fill_color[4] = {UNPACK3(color), fill_alpha * color[3]}; immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); immUniformColor4fv(fill_color); - imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION); + imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, 1.0f, CIRCLE_RESOLUTION); immUnbindProgram(); } @@ -106,7 +107,7 @@ static void button2d_geom_draw_backdrop(const wmGizmo *gz, immUniform2fv("viewportSize", &viewport[2]); immUniform1f("lineWidth", gz->line_width * U.pixelsize); immUniformColor4fv(color); - imm_draw_circle_wire_2d(pos, 0, 0, 1.0f, CIRCLE_RESOLUTION); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, 1.0f, CIRCLE_RESOLUTION); immUnbindProgram(); } } diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c index 4c54aa10c33..e4cb6d149f5 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c @@ -99,7 +99,8 @@ static void cage2d_draw_box_corners(const rctf *r, const float color[3], const float line_width) { - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + /* Note(Metal): Prefer using 3D coordinates with 3D shader, even if rendering 2D gizmo's. */ + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); immUniformColor3fv(color); @@ -112,25 +113,25 @@ static void cage2d_draw_box_corners(const rctf *r, immBegin(GPU_PRIM_LINES, 16); - immVertex2f(pos, r->xmin, r->ymin + margin[1]); - immVertex2f(pos, r->xmin, r->ymin); - immVertex2f(pos, r->xmin, r->ymin); - immVertex2f(pos, r->xmin + margin[0], r->ymin); + immVertex3f(pos, r->xmin, r->ymin + margin[1], 0.0f); + immVertex3f(pos, r->xmin, r->ymin, 0.0f); + immVertex3f(pos, r->xmin, r->ymin, 0.0f); + immVertex3f(pos, r->xmin + margin[0], r->ymin, 0.0f); - immVertex2f(pos, r->xmax, r->ymin + margin[1]); - immVertex2f(pos, r->xmax, r->ymin); - immVertex2f(pos, r->xmax, r->ymin); - immVertex2f(pos, r->xmax - margin[0], r->ymin); + immVertex3f(pos, r->xmax, r->ymin + margin[1], 0.0f); + immVertex3f(pos, r->xmax, r->ymin, 0.0f); + immVertex3f(pos, r->xmax, r->ymin, 0.0f); + immVertex3f(pos, r->xmax - margin[0], r->ymin, 0.0f); - immVertex2f(pos, r->xmax, r->ymax - margin[1]); - immVertex2f(pos, r->xmax, r->ymax); - immVertex2f(pos, r->xmax, r->ymax); - immVertex2f(pos, r->xmax - margin[0], r->ymax); + immVertex3f(pos, r->xmax, r->ymax - margin[1], 0.0f); + immVertex3f(pos, r->xmax, r->ymax, 0.0f); + immVertex3f(pos, r->xmax, r->ymax, 0.0f); + immVertex3f(pos, r->xmax - margin[0], r->ymax, 0.0f); - immVertex2f(pos, r->xmin, r->ymax - margin[1]); - immVertex2f(pos, r->xmin, r->ymax); - immVertex2f(pos, r->xmin, r->ymax); - immVertex2f(pos, r->xmin + margin[0], r->ymax); + immVertex3f(pos, r->xmin, r->ymax - margin[1], 0.0f); + immVertex3f(pos, r->xmin, r->ymax, 0.0f); + immVertex3f(pos, r->xmin, r->ymax, 0.0f); + immVertex3f(pos, r->xmin + margin[0], r->ymax, 0.0f); immEnd(); @@ -440,12 +441,35 @@ static void cage2d_draw_box_interaction(const float color[4], static void imm_draw_point_aspect_2d( uint pos, float x, float y, float rad_x, float rad_y, bool solid) { - immBegin(solid ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, 4); - immVertex2f(pos, x - rad_x, y - rad_y); - immVertex2f(pos, x - rad_x, y + rad_y); - immVertex2f(pos, x + rad_x, y + rad_y); - immVertex2f(pos, x + rad_x, y - rad_y); - immEnd(); + if (solid) { + /* Note(Metal/AMD): Small Triangle-list primitives more optimal for GPU HW than Trianglestrip. + */ + immBegin(GPU_PRIM_TRIS, 6); + immVertex2f(pos, x - rad_x, y - rad_y); + immVertex2f(pos, x - rad_x, y + rad_y); + immVertex2f(pos, x + rad_x, y + rad_y); + + immVertex2f(pos, x - rad_x, y - rad_y); + immVertex2f(pos, x + rad_x, y + rad_y); + immVertex2f(pos, x + rad_x, y - rad_y); + immEnd(); + } + else { + /* Note(Metal/AMD): Small Line-list primitives more optimal for GPU HW than Linestrip. */ + immBegin(GPU_PRIM_LINES, 8); + immVertex2f(pos, x - rad_x, y - rad_y); + immVertex2f(pos, x - rad_x, y + rad_y); + + immVertex2f(pos, x - rad_x, y + rad_y); + immVertex2f(pos, x + rad_x, y + rad_y); + + immVertex2f(pos, x + rad_x, y + rad_y); + immVertex2f(pos, x + rad_x, y - rad_y); + + immVertex2f(pos, x + rad_x, y - rad_y); + immVertex2f(pos, x - rad_x, y - rad_y); + immEnd(); + } } static void cage2d_draw_circle_wire(const rctf *r, @@ -455,7 +479,9 @@ static void cage2d_draw_circle_wire(const rctf *r, const int draw_options, const float line_width) { - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + /* Note(Metal): Prefer using 3D coordinates with 3D shader input, even if rendering 2D gizmo's. + */ + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); immUniformColor3fv(color); @@ -465,17 +491,28 @@ static void cage2d_draw_circle_wire(const rctf *r, immUniform2fv("viewportSize", &viewport[2]); immUniform1f("lineWidth", line_width * U.pixelsize); - immBegin(GPU_PRIM_LINE_LOOP, 4); - immVertex2f(pos, r->xmin, r->ymin); - immVertex2f(pos, r->xmax, r->ymin); - immVertex2f(pos, r->xmax, r->ymax); - immVertex2f(pos, r->xmin, r->ymax); + /* Small 'lines' primitives more efficient for hardware processing than linestrip. */ + immBegin(GPU_PRIM_LINES, 8); + immVertex3f(pos, r->xmin, r->ymin, 0.0f); + immVertex3f(pos, r->xmax, r->ymin, 0.0f); + + immVertex3f(pos, r->xmax, r->ymin, 0.0f); + immVertex3f(pos, r->xmax, r->ymax, 0.0f); + + immVertex3f(pos, r->xmax, r->ymax, 0.0f); + immVertex3f(pos, r->xmin, r->ymax, 0.0f); + + immVertex3f(pos, r->xmin, r->ymax, 0.0f); + immVertex3f(pos, r->xmin, r->ymin, 0.0f); immEnd(); if (transform_flag & ED_GIZMO_CAGE2D_XFORM_FLAG_ROTATE) { - immBegin(GPU_PRIM_LINE_LOOP, 2); - immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax); - immVertex2f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1]); + immBegin(GPU_PRIM_LINES, 4); + immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax, 0.0f); + immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1], 0.0f); + + immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax + margin[1], 0.0f); + immVertex3f(pos, BLI_rctf_cent_x(r), r->ymax, 0.0f); immEnd(); } @@ -485,10 +522,10 @@ static void cage2d_draw_circle_wire(const rctf *r, const float center[2] = {BLI_rctf_cent_x(r), BLI_rctf_cent_y(r)}; immBegin(GPU_PRIM_LINES, 4); - immVertex2f(pos, center[0] - rad[0], center[1] - rad[1]); - immVertex2f(pos, center[0] + rad[0], center[1] + rad[1]); - immVertex2f(pos, center[0] + rad[0], center[1] - rad[1]); - immVertex2f(pos, center[0] - rad[0], center[1] + rad[1]); + immVertex3f(pos, center[0] - rad[0], center[1] - rad[1], 0.0f); + immVertex3f(pos, center[0] + rad[0], center[1] + rad[1], 0.0f); + immVertex3f(pos, center[0] + rad[0], center[1] - rad[1], 0.0f); + immVertex3f(pos, center[0] - rad[0], center[1] + rad[1], 0.0f); immEnd(); } } diff --git a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c index e1f584bf9e4..a76242404ba 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c @@ -96,7 +96,8 @@ static void dial_geom_draw(const float color[4], ED_GIZMO_DIAL_DRAW_FLAG_FILL))); GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + /* Note(Metal): Prefer using 3D coordinates with 3D shader, even if rendering 2D gizmo's. */ + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); if (clip_plane) { immBindBuiltinProgram(filled ? GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR : @@ -114,18 +115,19 @@ static void dial_geom_draw(const float color[4], if (filled) { if (arc_partial_angle == 0.0f) { if (arc_inner_factor == 0.0f) { - imm_draw_circle_fill_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION); + imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, 1.0f, DIAL_RESOLUTION); } else { - imm_draw_disk_partial_fill_2d( - pos, 0, 0, arc_inner_factor, 1.0f, DIAL_RESOLUTION, 0, RAD2DEGF(M_PI * 2)); + imm_draw_disk_partial_fill_3d( + pos, 0.0f, 0.0f, 0.0f, arc_inner_factor, 1.0f, DIAL_RESOLUTION, 0, RAD2DEGF(M_PI * 2)); } } else { float arc_partial_deg = RAD2DEGF((M_PI * 2) - arc_partial_angle); - imm_draw_disk_partial_fill_2d(pos, - 0, - 0, + imm_draw_disk_partial_fill_3d(pos, + 0.0f, + 0.0f, + 0.0f, arc_inner_factor, 1.0f, DIAL_RESOLUTION, @@ -140,15 +142,15 @@ static void dial_geom_draw(const float color[4], immUniform1f("lineWidth", line_width * U.pixelsize); if (arc_partial_angle == 0.0f) { - imm_draw_circle_wire_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, 1.0f, DIAL_RESOLUTION); if (arc_inner_factor != 0.0f) { - imm_draw_circle_wire_2d(pos, 0, 0, arc_inner_factor, DIAL_RESOLUTION); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, arc_inner_factor, DIAL_RESOLUTION); } } else { float arc_partial_deg = RAD2DEGF((M_PI * 2) - arc_partial_angle); - imm_draw_circle_partial_wire_2d( - pos, 0, 0, 1.0, DIAL_RESOLUTION, -arc_partial_deg / 2, arc_partial_deg); + imm_draw_circle_partial_wire_3d( + pos, 0.0f, 0.0f, 0.0f, 1.0f, DIAL_RESOLUTION, -arc_partial_deg / 2, arc_partial_deg); # if 0 if (arc_inner_factor != 0.0f) { BLI_assert(0); @@ -186,7 +188,7 @@ static void dial_ghostarc_draw_helpline(const float angle, immUniformColor4fv(color); immBegin(GPU_PRIM_LINE_STRIP, 2); - immVertex3f(pos, 0.0f, 0, 0.0f); + immVertex3f(pos, 0.0f, 0.0f, 0.0f); immVertex3fv(pos, co_outer); immEnd(); diff --git a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c index 447fe1005a1..5fb1173521a 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c @@ -98,7 +98,8 @@ static void move_geom_draw(const wmGizmo *gz, ED_GIZMO_MOVE_DRAW_FLAG_FILL))); GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + /* Note(Metal): Prefer using 3D coordinates with 3D shader, even if rendering 2D gizmo's. */ + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(filled ? GPU_SHADER_3D_UNIFORM_COLOR : GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); @@ -115,20 +116,20 @@ static void move_geom_draw(const wmGizmo *gz, if (draw_style == ED_GIZMO_MOVE_STYLE_RING_2D) { if (filled) { - imm_draw_circle_fill_2d(pos, 0, 0, radius, DIAL_RESOLUTION); + imm_draw_circle_fill_3d(pos, 0.0f, 0.0f, radius, DIAL_RESOLUTION); } else { - imm_draw_circle_wire_2d(pos, 0, 0, radius, DIAL_RESOLUTION); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, radius, DIAL_RESOLUTION); } } else if (draw_style == ED_GIZMO_MOVE_STYLE_CROSS_2D) { const float radius_diag = M_SQRT1_2 * radius; immBegin(GPU_PRIM_LINES, 4); - immVertex2f(pos, radius_diag, radius_diag); - immVertex2f(pos, -radius_diag, -radius_diag); + immVertex3f(pos, radius_diag, radius_diag, 0.0f); + immVertex3f(pos, -radius_diag, -radius_diag, 0.0f); - immVertex2f(pos, -radius_diag, radius_diag); - immVertex2f(pos, radius_diag, -radius_diag); + immVertex3f(pos, -radius_diag, radius_diag, 0.0f); + immVertex3f(pos, radius_diag, -radius_diag, 0.0f); immEnd(); } else { diff --git a/source/blender/gpu/GPU_immediate_util.h b/source/blender/gpu/GPU_immediate_util.h index 924a735af79..cb7ca877b1d 100644 --- a/source/blender/gpu/GPU_immediate_util.h +++ b/source/blender/gpu/GPU_immediate_util.h @@ -80,6 +80,8 @@ void imm_draw_circle_fill_3d(uint pos, float x, float y, float radius, int nsegm */ void imm_draw_circle_partial_wire_2d( uint pos, float x, float y, float radius, int nsegments, float start, float sweep); +void imm_draw_circle_partial_wire_3d( + uint pos, float x, float y, float z, float radius, int nsegments, float start, float sweep); /** * Draw a filled arc with the given inner and outer radius. @@ -104,6 +106,15 @@ void imm_draw_disk_partial_fill_2d(uint pos, int nsegments, float start, float sweep); +void imm_draw_disk_partial_fill_3d(uint pos, + float x, + float y, + float z, + float rad_inner, + float rad_outer, + int nsegments, + float start, + float sweep); /** * Draw a lined box. diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c index cf8837ab26e..67035853594 100644 --- a/source/blender/gpu/intern/gpu_immediate_util.c +++ b/source/blender/gpu/intern/gpu_immediate_util.c @@ -142,12 +142,27 @@ static void imm_draw_circle(GPUPrimType prim_type, float radius_y, int nsegments) { - immBegin(prim_type, nsegments); - for (int i = 0; i < nsegments; i++) { - const float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments); - immVertex2f(shdr_pos, x + (radius_x * cosf(angle)), y + (radius_y * sinf(angle))); + if (prim_type == GPU_PRIM_LINE_LOOP) { + /* Note(Metal/AMD): For small primitives, line list more efficient than line strip.. */ + immBegin(GPU_PRIM_LINES, nsegments * 2); + + immVertex2f(shdr_pos, x + (radius_x * cosf(0.0f)), y + (radius_y * sinf(0.0f))); + for (int i = 1; i < nsegments; i++) { + const float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments); + immVertex2f(shdr_pos, x + (radius_x * cosf(angle)), y + (radius_y * sinf(angle))); + immVertex2f(shdr_pos, x + (radius_x * cosf(angle)), y + (radius_y * sinf(angle))); + } + immVertex2f(shdr_pos, x + (radius_x * cosf(0.0f)), y + (radius_y * sinf(0.0f))); + immEnd(); + } + else { + immBegin(prim_type, nsegments); + for (int i = 0; i < nsegments; i++) { + const float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments); + immVertex2f(shdr_pos, x + (radius_x * cosf(angle)), y + (radius_y * sinf(angle))); + } + immEnd(); } - immEnd(); } void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float radius, int nsegments) @@ -194,12 +209,42 @@ static void imm_draw_circle_partial(GPUPrimType prim_type, immEnd(); } +static void imm_draw_circle_partial_3d(GPUPrimType prim_type, + uint pos, + float x, + float y, + float z, + float rad, + int nsegments, + float start, + float sweep) +{ + /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ + const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2); + const float angle_end = -(DEG2RADF(sweep) - angle_start); + nsegments += 1; + immBegin(prim_type, nsegments); + for (int i = 0; i < nsegments; i++) { + const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1))); + const float angle_sin = sinf(angle); + const float angle_cos = cosf(angle); + immVertex3f(pos, x + rad * angle_cos, y + rad * angle_sin, z); + } + immEnd(); +} + void imm_draw_circle_partial_wire_2d( uint pos, float x, float y, float radius, int nsegments, float start, float sweep) { imm_draw_circle_partial(GPU_PRIM_LINE_STRIP, pos, x, y, radius, nsegments, start, sweep); } +void imm_draw_circle_partial_wire_3d( + uint pos, float x, float y, float z, float rad, int nsegments, float start, float sweep) +{ + imm_draw_circle_partial_3d(GPU_PRIM_LINE_STRIP, pos, x, y, z, rad, nsegments, start, sweep); +} + static void imm_draw_disk_partial(GPUPrimType prim_type, uint pos, float x, @@ -229,6 +274,36 @@ static void imm_draw_disk_partial(GPUPrimType prim_type, immEnd(); } +static void imm_draw_disk_partial_3d(GPUPrimType prim_type, + uint pos, + float x, + float y, + float z, + float rad_inner, + float rad_outer, + int nsegments, + float start, + float sweep) +{ + /* to avoid artifacts */ + const float max_angle = 3 * 360; + CLAMP(sweep, -max_angle, max_angle); + + /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ + const float angle_start = -(DEG2RADF(start)) + (float)M_PI_2; + const float angle_end = -(DEG2RADF(sweep) - angle_start); + nsegments += 1; + immBegin(prim_type, nsegments * 2); + for (int i = 0; i < nsegments; i++) { + const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1))); + const float angle_sin = sinf(angle); + const float angle_cos = cosf(angle); + immVertex3f(pos, x + rad_inner * angle_cos, y + rad_inner * angle_sin, z); + immVertex3f(pos, x + rad_outer * angle_cos, y + rad_outer * angle_sin, z); + } + immEnd(); +} + void imm_draw_disk_partial_fill_2d(uint pos, float x, float y, @@ -241,16 +316,44 @@ void imm_draw_disk_partial_fill_2d(uint pos, imm_draw_disk_partial( GPU_PRIM_TRI_STRIP, pos, x, y, rad_inner, rad_outer, nsegments, start, sweep); } +void imm_draw_disk_partial_fill_3d(uint pos, + float x, + float y, + float z, + float rad_inner, + float rad_outer, + int nsegments, + float start, + float sweep) +{ + imm_draw_disk_partial_3d( + GPU_PRIM_TRI_STRIP, pos, x, y, z, rad_inner, rad_outer, nsegments, start, sweep); +} static void imm_draw_circle_3D( GPUPrimType prim_type, uint pos, float x, float y, float radius, int nsegments) { - immBegin(prim_type, nsegments); - for (int i = 0; i < nsegments; i++) { - float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments); - immVertex3f(pos, x + radius * cosf(angle), y + radius * sinf(angle), 0.0f); + if (prim_type == GPU_PRIM_LINE_LOOP) { + /* Note(Metal/AMD): For small primitives, line list more efficient than line strip. */ + immBegin(GPU_PRIM_LINES, nsegments * 2); + + immVertex3f(pos, x + radius * cosf(0.0f), y + radius * sinf(0.0f), 0.0f); + for (int i = 1; i < nsegments; i++) { + float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments); + immVertex3f(pos, x + radius * cosf(angle), y + radius * sinf(angle), 0.0f); + immVertex3f(pos, x + radius * cosf(angle), y + radius * sinf(angle), 0.0f); + } + immVertex3f(pos, x + radius * cosf(0.0f), y + radius * sinf(0.0f), 0.0f); + immEnd(); + } + else { + immBegin(prim_type, nsegments); + for (int i = 0; i < nsegments; i++) { + float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments); + immVertex3f(pos, x + radius * cosf(angle), y + radius * sinf(angle), 0.0f); + } + immEnd(); } - immEnd(); } void imm_draw_circle_wire_3d(uint pos, float x, float y, float radius, int nsegments) @@ -270,22 +373,38 @@ void imm_draw_circle_fill_3d(uint pos, float x, float y, float radius, int nsegm void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2) { - immBegin(GPU_PRIM_LINE_LOOP, 4); + /* Note(Metal/AMD): For small primitives, line list more efficient than line-strip. */ + immBegin(GPU_PRIM_LINES, 8); immVertex2f(pos, x1, y1); immVertex2f(pos, x1, y2); + + immVertex2f(pos, x1, y2); immVertex2f(pos, x2, y2); + + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2, y1); + immVertex2f(pos, x2, y1); + immVertex2f(pos, x1, y1); immEnd(); } void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2) { /* use this version when GPUVertFormat has a vec3 position */ - immBegin(GPU_PRIM_LINE_LOOP, 4); + /* Note(Metal/AMD): For small primitives, line list more efficient than line-strip. */ + immBegin(GPU_PRIM_LINES, 8); immVertex3f(pos, x1, y1, 0.0f); immVertex3f(pos, x1, y2, 0.0f); + + immVertex3f(pos, x1, y2, 0.0f); + immVertex3f(pos, x2, y2, 0.0f); + immVertex3f(pos, x2, y2, 0.0f); immVertex3f(pos, x2, y1, 0.0f); + + immVertex3f(pos, x2, y1, 0.0f); + immVertex3f(pos, x1, y1, 0.0f); immEnd(); } |