From e764d2b6baff83bc979b461c92a1bda99dd37455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 30 Apr 2018 22:47:40 +0200 Subject: Armature: More work and cleanup on envelope bones drawing. - Draw tail & head sphere with point shader (no needs for another way). - Use the same function for issuing the calls for wire and solid envelope. --- source/blender/draw/CMakeLists.txt | 1 + source/blender/draw/intern/draw_armature.c | 127 +++++++++++++++++++---------- source/blender/draw/intern/draw_cache.c | 2 +- source/blender/draw/intern/draw_common.c | 40 +++++---- source/blender/draw/intern/draw_common.h | 8 +- 5 files changed, 112 insertions(+), 66 deletions(-) diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 3ccbf967b87..0db397433e5 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -226,6 +226,7 @@ data_to_c_simple(modes/shaders/armature_sphere_frag.glsl SRC) data_to_c_simple(modes/shaders/armature_sphere_outline_vert.glsl SRC) data_to_c_simple(modes/shaders/armature_envelope_vert.glsl SRC) data_to_c_simple(modes/shaders/armature_envelope_frag.glsl SRC) +data_to_c_simple(modes/shaders/armature_envelope_outline_vert.glsl SRC) data_to_c_simple(modes/shaders/armature_shape_outline_vert.glsl SRC) data_to_c_simple(modes/shaders/armature_shape_outline_geom.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_frag.glsl SRC) diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index 6b685f07de1..5a3c03d5be2 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -65,6 +65,8 @@ #define BONE_VAR(eBone, pchan, var) ((eBone) ? (eBone->var) : (pchan->var)) #define BONE_FLAG(eBone, pchan) ((eBone) ? (eBone->flag) : (pchan->bone->flag)) +#define PT_DEFAULT_RAD 0.05f /* radius of the point batch. */ + /* For now just match 2.7x where possible. */ // #define USE_SOLID_COLOR @@ -83,7 +85,6 @@ static struct { DRWShadingGroup *bone_envelope_solid; DRWShadingGroup *bone_envelope_distance; DRWShadingGroup *bone_envelope_wire; - DRWShadingGroup *bone_envelope_head_wire; DRWShadingGroup *bone_point_solid; DRWShadingGroup *bone_point_wire; DRWShadingGroup *bone_axes; @@ -121,7 +122,7 @@ static void drw_shgroup_bone_octahedral_wire(const float (*bone_mat)[4], const f struct Gwn_Batch *geom = DRW_cache_bone_octahedral_wire_outline_get(); g_data.bone_octahedral_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom); geom = DRW_cache_bone_octahedral_get(); - g_data.bone_octahedral_outline = shgroup_instance_armature_shape_outline(g_data.pass_bone_outline, geom); + g_data.bone_octahedral_outline = shgroup_instance_bone_shape_outline(g_data.pass_bone_outline, geom); } float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); @@ -147,7 +148,7 @@ static void drw_shgroup_bone_box_wire(const float (*bone_mat)[4], const float co struct Gwn_Batch *geom = DRW_cache_bone_box_wire_outline_get(); g_data.bone_box_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom); geom = DRW_cache_bone_box_get(); - g_data.bone_box_outline = shgroup_instance_armature_shape_outline(g_data.pass_bone_outline, geom); + g_data.bone_box_outline = shgroup_instance_bone_shape_outline(g_data.pass_bone_outline, geom); } float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); @@ -189,24 +190,20 @@ static void drw_shgroup_bone_envelope_distance( tail_sphere[3] = *radius_tail; tail_sphere[3] += *distance; + /* Shader transform is nicer if tail is the biggest. */ + if (*radius_head > *radius_tail) { + swap_v4_v4(head_sphere, tail_sphere); + } + DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, head_sphere, tail_sphere, color, final_bonemat[0]); } } -static void drw_shgroup_bone_envelope_solid( +static void drw_shgroup_bone_envelope( + DRWShadingGroup *point, DRWShadingGroup *capsule, const float (*bone_mat)[4], const float color[4], const float *radius_head, const float *radius_tail) { - if (g_data.bone_envelope_solid == NULL) { - g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.pass_bone_solid); - /* We can have a lot of overdraw if we don't do this. Also envelope are not subject to - * inverted matrix. */ - DRW_shgroup_state_enable(g_data.bone_envelope_solid, DRW_STATE_CULL_BACK); - } - if (g_data.bone_point_solid == NULL) { - g_data.bone_point_solid = shgroup_instance_armature_sphere(g_data.pass_bone_solid); - } - float head_sphere[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sphere[4] = {0.0f, 1.0f, 0.0f, 1.0f}; float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); @@ -218,69 +215,121 @@ static void drw_shgroup_bone_envelope_solid( if (head_sphere[3] < 0.0f) { /* Draw Tail only */ float tmp[4][4] = {{0.0f}}; - tmp[0][0] = tmp[1][1] = tmp[2][2] = tail_sphere[3] / 0.05f; + tmp[0][0] = tmp[1][1] = tmp[2][2] = tail_sphere[3] / PT_DEFAULT_RAD; tmp[3][3] = 1.0f; copy_v3_v3(tmp[3], tail_sphere); - DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, color); + DRW_shgroup_call_dynamic_add(point, tmp, color); } else if (tail_sphere[3] < 0.0f) { /* Draw Head only */ float tmp[4][4] = {{0.0f}}; - tmp[0][0] = tmp[1][1] = tmp[2][2] = head_sphere[3] / 0.05f; + tmp[0][0] = tmp[1][1] = tmp[2][2] = head_sphere[3] / PT_DEFAULT_RAD; tmp[3][3] = 1.0f; copy_v3_v3(tmp[3], head_sphere); - DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, color); + DRW_shgroup_call_dynamic_add(point, tmp, color); } else { /* Draw Body */ float tmp_sphere[4]; float len = len_v3v3(tail_sphere, head_sphere); + + /* Shader transform is nicer if tail is the biggest. */ + if (*radius_head > *radius_tail) { + swap_v4_v4(head_sphere, tail_sphere); + } + float fac_head = (len - head_sphere[3]) / len; float fac_tail = (len - tail_sphere[3]) / len; /* Small epsilon to avoid problem with float precison in shader. */ if (len > (tail_sphere[3] + head_sphere[3]) + 1e-8f) { + copy_v4_v4(tmp_sphere, head_sphere); interp_v4_v4v4(head_sphere, tail_sphere, head_sphere, fac_head); interp_v4_v4v4(tail_sphere, tmp_sphere, tail_sphere, fac_tail); - DRW_shgroup_call_dynamic_add(g_data.bone_envelope_solid, head_sphere, tail_sphere, color, final_bonemat[0]); + DRW_shgroup_call_dynamic_add(capsule, head_sphere, tail_sphere, color, final_bonemat[0]); } else { float tmp[4][4] = {{0.0f}}; float fac = max_ff(fac_head, 1.0f - fac_tail); interp_v4_v4v4(tmp_sphere, tail_sphere, head_sphere, clamp_f(fac, 0.0f, 1.0f)); - tmp[0][0] = tmp[1][1] = tmp[2][2] = tmp_sphere[3] / 0.05f; + tmp[0][0] = tmp[1][1] = tmp[2][2] = tmp_sphere[3] / PT_DEFAULT_RAD; tmp[3][3] = 1.0f; copy_v3_v3(tmp[3], tmp_sphere); - DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, color); + DRW_shgroup_call_dynamic_add(point, tmp, color); } } } +static void drw_shgroup_bone_envelope_solid( + const float (*bone_mat)[4], const float color[4], + const float *radius_head, const float *radius_tail) +{ + if (g_data.bone_envelope_solid == NULL) { + g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.pass_bone_solid); + /* We can have a lot of overdraw if we don't do this. Also envelope are not subject to + * inverted matrix. */ + DRW_shgroup_state_enable(g_data.bone_envelope_solid, DRW_STATE_CULL_BACK); + } + if (g_data.bone_point_solid == NULL) { + g_data.bone_point_solid = shgroup_instance_bone_sphere(g_data.pass_bone_solid); + } + + drw_shgroup_bone_envelope(g_data.bone_point_solid, + g_data.bone_envelope_solid, + bone_mat, color, + radius_head, radius_tail); +} + static void drw_shgroup_bone_envelope_wire( const float (*bone_mat)[4], const float color[4], - const float *radius_head, const float *radius_tail, const float *distance) + const float *radius_head, const float *radius_tail, const float *UNUSED(distance)) { if (g_data.bone_envelope_wire == NULL) { - struct Gwn_Batch *geom = DRW_cache_bone_envelope_wire_outline_get(); - g_data.bone_envelope_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom); + g_data.bone_envelope_wire = shgroup_instance_bone_envelope_outline(g_data.pass_bone_wire); } - float final_bonemat[4][4]; - mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); - DRW_shgroup_call_dynamic_add(g_data.bone_envelope_wire, final_bonemat, color, radius_head, radius_tail, distance); + if (g_data.bone_point_wire == NULL) { + g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.pass_bone_wire); + } + + drw_shgroup_bone_envelope(g_data.bone_point_wire, + g_data.bone_envelope_wire, + bone_mat, color, + radius_head, radius_tail); } static void drw_shgroup_bone_envelope_head_wire( const float (*bone_mat)[4], const float color[4], - const float *radius_head, const float *radius_tail, const float *distance) + const float *radius_head, const float *radius_tail, const float *UNUSED(distance)) { - if (g_data.bone_envelope_head_wire == NULL) { - struct Gwn_Batch *geom = DRW_cache_bone_envelope_head_wire_outline_get(); - g_data.bone_envelope_head_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom); + if (g_data.bone_point_wire == NULL) { + g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.pass_bone_wire); } + + float head_sphere[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sphere[4] = {0.0f, 1.0f, 0.0f, 1.0f}; float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); - DRW_shgroup_call_dynamic_add(g_data.bone_envelope_head_wire, final_bonemat, color, radius_head, radius_tail, distance); + mul_m4_v4(final_bonemat, head_sphere); + mul_m4_v4(final_bonemat, tail_sphere); + head_sphere[3] = *radius_head; + tail_sphere[3] = *radius_tail; + + if (head_sphere[3] < 0.0f) { + /* Draw Tail only */ + float tmp[4][4] = {{0.0f}}; + tmp[0][0] = tmp[1][1] = tmp[2][2] = tail_sphere[3] / PT_DEFAULT_RAD; + tmp[3][3] = 1.0f; + copy_v3_v3(tmp[3], tail_sphere); + DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, color); + } + if (head_sphere[3] > 0.0f) { + /* Draw Head only */ + float tmp[4][4] = {{0.0f}}; + tmp[0][0] = tmp[1][1] = tmp[2][2] = head_sphere[3] / PT_DEFAULT_RAD; + tmp[3][3] = 1.0f; + copy_v3_v3(tmp[3], head_sphere); + DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, color); + } } /* Custom (geometry) */ @@ -313,12 +362,7 @@ static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4], const float static void drw_shgroup_bone_point_solid(const float (*bone_mat)[4], const float color[4]) { if (g_data.bone_point_solid == NULL) { -#if 0 /* old style geometry sphere */ - struct Gwn_Batch *geom = DRW_cache_bone_point_get() - g_data.bone_point_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom); -#else /* new style raytraced sphere */ - g_data.bone_point_solid = shgroup_instance_armature_sphere(g_data.pass_bone_solid); -#endif + g_data.bone_point_solid = shgroup_instance_bone_sphere(g_data.pass_bone_solid); } float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); @@ -328,12 +372,7 @@ static void drw_shgroup_bone_point_solid(const float (*bone_mat)[4], const float static void drw_shgroup_bone_point_wire(const float (*bone_mat)[4], const float color[4]) { if (g_data.bone_point_wire == NULL) { -#if 0 /* old style 3 axis circles */ - struct Gwn_Batch *geom = DRW_cache_bone_point_wire_outline_get(); - g_data.bone_point_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom); -#else /* new style contour outline */ - g_data.bone_point_wire = shgroup_instance_armature_sphere_outline(g_data.pass_bone_wire); -#endif + g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.pass_bone_wire); } float final_bonemat[4][4]; mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index db0f891c730..aa21bb7214a 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -2096,7 +2096,7 @@ Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void) static struct { uint pos0, pos1; } attr_id; if (format.attrib_ct == 0) { attr_id.pos0 = GWN_vertformat_attr_add(&format, "pos0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - attr_id.pos1 = GWN_vertformat_attr_add(&format, "pos1", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.pos1 = GWN_vertformat_attr_add(&format, "pos1", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); } Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index 8697d4c814e..f108b129feb 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -158,9 +158,10 @@ void DRW_globals_update(void) extern char datatoc_armature_sphere_vert_glsl[]; extern char datatoc_armature_sphere_frag_glsl[]; +extern char datatoc_armature_sphere_outline_vert_glsl[]; extern char datatoc_armature_envelope_vert_glsl[]; extern char datatoc_armature_envelope_frag_glsl[]; -extern char datatoc_armature_sphere_outline_vert_glsl[]; +extern char datatoc_armature_envelope_outline_vert_glsl[]; extern char datatoc_armature_shape_outline_vert_glsl[]; extern char datatoc_armature_shape_outline_geom_glsl[]; extern char datatoc_gpu_shader_flat_color_frag_glsl[]; @@ -184,8 +185,7 @@ static struct { struct Gwn_VertFormat *instance_camera; struct Gwn_VertFormat *instance_distance_lines; struct Gwn_VertFormat *instance_spot; - struct Gwn_VertFormat *instance_bone_envelope_wire; - struct Gwn_VertFormat *instance_bone_envelope_solid; + struct Gwn_VertFormat *instance_bone_envelope; struct Gwn_VertFormat *instance_mball_handles; } g_formats = {NULL}; @@ -425,19 +425,25 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom) return grp; } -DRWShadingGroup *shgroup_instance_bone_envelope_wire(DRWPass *pass, struct Gwn_Batch *geom) +DRWShadingGroup *shgroup_instance_bone_envelope_outline(DRWPass *pass) { - GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE); + if (g_armature_shaders.bone_envelope_outline == NULL) { + g_armature_shaders.bone_envelope_outline = DRW_shader_create( + datatoc_armature_envelope_outline_vert_glsl, NULL, + datatoc_gpu_shader_flat_color_frag_glsl, NULL); + } - DRW_shgroup_instance_format(g_formats.instance_bone_envelope_wire, { - {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16}, - {"color" , DRW_ATTRIB_FLOAT, 4}, - {"radius_head" , DRW_ATTRIB_FLOAT, 1}, - {"radius_tail" , DRW_ATTRIB_FLOAT, 1}, - {"distance" , DRW_ATTRIB_FLOAT, 1} + DRW_shgroup_instance_format(g_formats.instance_bone_envelope, { + {"headSphere" , DRW_ATTRIB_FLOAT, 4}, + {"tailSphere" , DRW_ATTRIB_FLOAT, 4}, + {"color" , DRW_ATTRIB_FLOAT, 4}, + {"xAxis" , DRW_ATTRIB_FLOAT, 3} }); - DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_bone_envelope_wire); + DRWShadingGroup *grp = DRW_shgroup_instance_create(g_armature_shaders.bone_envelope_outline, + pass, DRW_cache_bone_envelope_outline_get(), + g_formats.instance_bone_envelope); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); return grp; } @@ -450,7 +456,7 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass) datatoc_armature_envelope_frag_glsl, NULL); } - DRW_shgroup_instance_format(g_formats.instance_bone_envelope_solid, { + DRW_shgroup_instance_format(g_formats.instance_bone_envelope, { {"headSphere" , DRW_ATTRIB_FLOAT, 4}, {"tailSphere" , DRW_ATTRIB_FLOAT, 4}, {"color" , DRW_ATTRIB_FLOAT, 4}, @@ -459,7 +465,7 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass) DRWShadingGroup *grp = DRW_shgroup_instance_create(g_armature_shaders.bone_envelope, pass, DRW_cache_bone_envelope_solid_get(), - g_formats.instance_bone_envelope_solid); + g_formats.instance_bone_envelope); return grp; } @@ -481,7 +487,7 @@ DRWShadingGroup *shgroup_instance_mball_handles(DRWPass *pass, struct Gwn_Batch } /* Only works with batches with adjacency infos. */ -DRWShadingGroup *shgroup_instance_armature_shape_outline(DRWPass *pass, struct Gwn_Batch *geom) +DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass, struct Gwn_Batch *geom) { if (g_armature_shaders.shape_outline == NULL) { g_armature_shaders.shape_outline = DRW_shader_create( @@ -504,7 +510,7 @@ DRWShadingGroup *shgroup_instance_armature_shape_outline(DRWPass *pass, struct G return grp; } -DRWShadingGroup *shgroup_instance_armature_sphere(DRWPass *pass) +DRWShadingGroup *shgroup_instance_bone_sphere(DRWPass *pass) { if (g_armature_shaders.bone_sphere == NULL) { g_armature_shaders.bone_sphere = DRW_shader_create( @@ -524,7 +530,7 @@ DRWShadingGroup *shgroup_instance_armature_sphere(DRWPass *pass) return grp; } -DRWShadingGroup *shgroup_instance_armature_sphere_outline(DRWPass *pass) +DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass) { if (g_armature_shaders.bone_sphere_outline == NULL) { g_armature_shaders.bone_sphere_outline = DRW_shader_create( diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 81974749282..656a4d7303d 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -118,12 +118,12 @@ struct DRWShadingGroup *shgroup_instance_outline(struct DRWPass *pass, struct Gw struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct Gwn_Batch *geom); struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct Gwn_Batch *geom); struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct Gwn_Batch *geom); -struct DRWShadingGroup *shgroup_instance_bone_envelope_wire(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance_bone_envelope_outline(struct DRWPass *pass); struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass); struct DRWShadingGroup *shgroup_instance_mball_handles(struct DRWPass *pass, struct Gwn_Batch *geom); -struct DRWShadingGroup *shgroup_instance_armature_shape_outline(struct DRWPass *pass, struct Gwn_Batch *geom); -struct DRWShadingGroup *shgroup_instance_armature_sphere(struct DRWPass *pass); -struct DRWShadingGroup *shgroup_instance_armature_sphere_outline(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_instance_bone_shape_outline(struct DRWPass *pass, struct Gwn_Batch *geom); +struct DRWShadingGroup *shgroup_instance_bone_sphere(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_instance_bone_sphere_outline(struct DRWPass *pass); int DRW_object_wire_theme_get( struct Object *ob, struct ViewLayer *view_layer, float **r_color); -- cgit v1.2.3