diff options
Diffstat (limited to 'source/blender/draw')
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_armature.c | 74 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.c | 77 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.h | 1 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_common.c | 28 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_common.h | 1 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/armature_stick_frag.glsl | 13 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/armature_stick_vert.glsl | 88 |
8 files changed, 280 insertions, 4 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 53d46575a62..71285d7ba04 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -236,6 +236,8 @@ data_to_c_simple(modes/shaders/armature_shape_solid_vert.glsl SRC) data_to_c_simple(modes/shaders/armature_shape_solid_frag.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/armature_stick_vert.glsl SRC) +data_to_c_simple(modes/shaders/armature_stick_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_geom_tri.glsl SRC) diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index 1a2ff70624b..efbf1143c16 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -82,6 +82,7 @@ static struct { DRWShadingGroup *bone_box_wire; DRWShadingGroup *bone_box_outline; DRWShadingGroup *bone_wire_wire; + DRWShadingGroup *bone_stick; DRWShadingGroup *bone_envelope_solid; DRWShadingGroup *bone_envelope_distance; DRWShadingGroup *bone_envelope_wire; @@ -181,6 +182,20 @@ static void drw_shgroup_bone_wire_wire(const float (*bone_mat)[4], const float c DRW_shgroup_call_dynamic_add(g_data.bone_wire_wire, final_bonemat, color); } +static void drw_shgroup_bone_stick( + const float (*bone_mat)[4], + const float col_wire[4], const float col_bone[4], const float col_head[4], const float col_tail[4]) +{ + if (g_data.bone_stick == NULL) { + g_data.bone_stick = shgroup_instance_bone_stick(g_data.passes.bone_wire); + } + float final_bonemat[4][4], tail[4]; + mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat); + add_v3_v3v3(tail, final_bonemat[3], final_bonemat[1]); + DRW_shgroup_call_dynamic_add(g_data.bone_stick, final_bonemat[3], tail, col_wire, col_bone, col_head, col_tail); +} + + /* Envelope */ static void drw_shgroup_bone_envelope_distance( const float (*bone_mat)[4], @@ -1192,11 +1207,62 @@ static void draw_bone_envelope( } static void draw_bone_line( - EditBone *UNUSED(eBone), bPoseChannel *UNUSED(pchan), bArmature *UNUSED(arm), - const int UNUSED(boneflag), const short UNUSED(constflag), - const int UNUSED(select_id)) + EditBone *eBone, bPoseChannel *pchan, bArmature *arm, + const int boneflag, const short constflag, const int select_id) { - /* work in progress -- fclem */ + const float *col_bone = get_bone_solid_with_consts_color(eBone, pchan, arm, boneflag, constflag); + const float *col_wire = get_bone_wire_color(eBone, pchan, arm, boneflag, constflag); + const float no_display[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + const float *col_head = no_display; + const float *col_tail = col_bone; + + if (eBone) { + if (eBone->flag & BONE_TIPSEL) { + col_tail = g_theme.vertex_select_color; + } + if (boneflag & BONE_SELECTED) { + col_bone = g_theme.edge_select_color; + } + col_wire = g_theme.wire_color; + } + + /* Draw root point if we are not connected and parent are not hidden */ + if ((BONE_FLAG(eBone, pchan) & BONE_CONNECTED) == 0) { + if (eBone && !(eBone->parent && !EBONE_VISIBLE(arm, eBone->parent))) { + col_head = (eBone->flag & BONE_ROOTSEL) ? g_theme.vertex_select_color : col_bone; + } + else if (pchan) { + Bone *bone = pchan->bone; + if (!(bone->parent && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) { + col_head = col_bone; + } + } + } + + if (g_theme.const_color != NULL) { + col_wire = no_display; /* actually shrink the display. */ + col_bone = col_head = col_tail = g_theme.const_color; + } + + if (select_id == -1) { + /* Not in selection mode, draw everything at once. */ + drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, col_bone, col_head, col_tail); + } + else { + /* In selection mode, draw bone, root and tip separatly. */ + DRW_select_load_id(select_id | BONESEL_BONE); + drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, col_bone, no_display, no_display); + + if (col_head[3] > 0.0f) { + DRW_select_load_id(select_id | BONESEL_ROOT); + drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, no_display, col_head, no_display); + } + + DRW_select_load_id(select_id | BONESEL_TIP); + drw_shgroup_bone_stick(BONE_VAR(eBone, pchan, disp_mat), col_wire, no_display, no_display, col_tail); + + DRW_select_load_id(-1); + } } static void draw_bone_wire( diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 1a4a9be00bd..2366fa556b9 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -88,6 +88,7 @@ static struct DRWShapeCache { Gwn_Batch *drw_bone_envelope_outline; Gwn_Batch *drw_bone_point; Gwn_Batch *drw_bone_point_wire; + Gwn_Batch *drw_bone_stick; Gwn_Batch *drw_bone_arrows; Gwn_Batch *drw_camera; Gwn_Batch *drw_camera_frame; @@ -2104,6 +2105,82 @@ Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void) return SHC.drw_bone_point_wire; } +/* keep in sync with armature_stick_vert.glsl */ +#define COL_WIRE (1 << 0) +#define COL_HEAD (1 << 1) +#define COL_TAIL (1 << 2) +#define COL_BONE (1 << 3) + +#define POS_HEAD (1 << 4) +#define POS_TAIL (1 << 5) +#define POS_BONE (1 << 6) + +Gwn_Batch *DRW_cache_bone_stick_get(void) +{ + if (!SHC.drw_bone_stick) { +#define CIRCLE_RESOL 12 + unsigned int v = 0; + unsigned int flag; + const float radius = 2.0f; /* head/tail radius */ + float pos[2]; + + /* Position Only 2D format */ + static Gwn_VertFormat format = { 0 }; + static struct { uint pos, flag; } attr_id; + if (format.attrib_ct == 0) { + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + attr_id.flag = GWN_vertformat_attr_add(&format, "flag", GWN_COMP_U32, 1, GWN_FETCH_INT); + } + + const unsigned int vcount = (CIRCLE_RESOL + 1) * 2 + 6; + + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(vbo, vcount); + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init_ex(&elb, GWN_PRIM_TRI_FAN, (CIRCLE_RESOL + 2) * 2 + 6 + 2, vcount, true); + + /* head/tail points */ + for (int i = 0; i < 2; ++i) { + /* center vertex */ + copy_v2_fl(pos, 0.0f); + flag = (i == 0) ? POS_HEAD : POS_TAIL; + flag |= (i == 0) ? COL_HEAD : COL_TAIL; + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, pos); + GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag); + GWN_indexbuf_add_generic_vert(&elb, v++); + /* circle vertices */ + flag |= COL_WIRE; + for (int a = 0; a < CIRCLE_RESOL; a++) { + pos[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + pos[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, pos); + GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag); + GWN_indexbuf_add_generic_vert(&elb, v++); + } + /* Close the circle */ + GWN_indexbuf_add_generic_vert(&elb, v - CIRCLE_RESOL); + + GWN_indexbuf_add_primitive_restart(&elb); + } + + /* Bone rectangle */ + pos[0] = 0.0f; + for (int i = 0; i < 6; ++i) { + pos[1] = (i == 0 || i == 3) ? 0.0f : ((i < 3) ? 1.0f : -1.0f); + flag = ((i < 2 || i > 4) ? POS_HEAD : POS_TAIL) | + ((i == 0 || i == 3) ? 0 : COL_WIRE) | COL_BONE | POS_BONE; + GWN_vertbuf_attr_set(vbo, attr_id.pos, v, pos); + GWN_vertbuf_attr_set(vbo, attr_id.flag, v, &flag); + GWN_indexbuf_add_generic_vert(&elb, v++); + } + + SHC.drw_bone_stick = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, GWN_indexbuf_build(&elb), GWN_BATCH_OWNS_VBO); +#undef CIRCLE_RESOL + } + return SHC.drw_bone_stick; +} + static void set_bone_axis_vert( Gwn_VertBuf *vbo, uint axis, uint pos, uint col, unsigned int *v, const float *a, const float *p, const float *c) diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 22a5588599f..18bff56920e 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -105,6 +105,7 @@ struct Gwn_Batch *DRW_cache_bone_envelope_outline_get(void); struct Gwn_Batch *DRW_cache_bone_envelope_head_wire_outline_get(void); struct Gwn_Batch *DRW_cache_bone_point_get(void); struct Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void); +struct Gwn_Batch *DRW_cache_bone_stick_get(void); struct Gwn_Batch *DRW_cache_bone_arrows_get(void); /* Meshes */ diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index 2c606aa57d7..ba5e04df512 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -165,6 +165,8 @@ extern char datatoc_armature_shape_solid_vert_glsl[]; extern char datatoc_armature_shape_solid_frag_glsl[]; extern char datatoc_armature_shape_outline_vert_glsl[]; extern char datatoc_armature_shape_outline_geom_glsl[]; +extern char datatoc_armature_stick_vert_glsl[]; +extern char datatoc_armature_stick_frag_glsl[]; extern char datatoc_gpu_shader_flat_color_frag_glsl[]; extern char datatoc_object_mball_handles_vert_glsl[]; @@ -178,6 +180,7 @@ static struct { struct GPUShader *bone_envelope_outline; struct GPUShader *bone_sphere; struct GPUShader *bone_sphere_outline; + struct GPUShader *bone_stick; struct GPUShader *mball_handles; } g_shaders = {NULL}; @@ -194,6 +197,7 @@ static struct { struct Gwn_VertFormat *instance_distance_lines; struct Gwn_VertFormat *instance_spot; struct Gwn_VertFormat *instance_bone; + struct Gwn_VertFormat *instance_bone_stick; struct Gwn_VertFormat *instance_bone_outline; struct Gwn_VertFormat *instance_bone_envelope; struct Gwn_VertFormat *instance_bone_envelope_distance; @@ -638,6 +642,30 @@ DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass) return grp; } +DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass) +{ + if (g_shaders.bone_stick == NULL) { + g_shaders.bone_stick = DRW_shader_create( + datatoc_armature_stick_vert_glsl, NULL, + datatoc_armature_stick_frag_glsl, NULL); + } + + DRW_shgroup_instance_format(g_formats.instance_bone_stick, { + {"boneStart", DRW_ATTRIB_FLOAT, 3}, + {"boneEnd" , DRW_ATTRIB_FLOAT, 3}, + {"wireColor", DRW_ATTRIB_FLOAT, 4}, /* TODO port theses to uchar color */ + {"boneColor", DRW_ATTRIB_FLOAT, 4}, + {"headColor", DRW_ATTRIB_FLOAT, 4}, + {"tailColor", DRW_ATTRIB_FLOAT, 4} + }); + + DRWShadingGroup *grp = DRW_shgroup_instance_create(g_shaders.bone_stick, + pass, DRW_cache_bone_stick_get(), + g_formats.instance_bone_stick); + DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); + + return grp; +} /* ******************************************** COLOR UTILS *********************************************** */ diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 8730be54d93..dca92188ca7 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -124,6 +124,7 @@ struct DRWShadingGroup *shgroup_instance_bone_shape_outline(struct DRWPass *pass struct DRWShadingGroup *shgroup_instance_bone_shape_solid(struct DRWPass *pass, struct Gwn_Batch *geom); struct DRWShadingGroup *shgroup_instance_bone_sphere_outline(struct DRWPass *pass); struct DRWShadingGroup *shgroup_instance_bone_sphere_solid(struct DRWPass *pass); +struct DRWShadingGroup *shgroup_instance_bone_stick(struct DRWPass *pass); int DRW_object_wire_theme_get( struct Object *ob, struct ViewLayer *view_layer, float **r_color); diff --git a/source/blender/draw/modes/shaders/armature_stick_frag.glsl b/source/blender/draw/modes/shaders/armature_stick_frag.glsl new file mode 100644 index 00000000000..d03cf4c0366 --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_stick_frag.glsl @@ -0,0 +1,13 @@ + +noperspective in float colorFac; +flat in vec4 finalWireColor; +flat in vec4 finalInnerColor; + +out vec4 fragColor; + +void main() +{ + float fac = smoothstep(1.0, 0.2, colorFac); + fragColor.rgb = mix(finalInnerColor.rgb, finalWireColor.rgb, fac); + fragColor.a = 1.0; +} diff --git a/source/blender/draw/modes/shaders/armature_stick_vert.glsl b/source/blender/draw/modes/shaders/armature_stick_vert.glsl new file mode 100644 index 00000000000..eb14239bc6f --- /dev/null +++ b/source/blender/draw/modes/shaders/armature_stick_vert.glsl @@ -0,0 +1,88 @@ + +uniform mat4 ProjectionMatrix; +uniform mat4 ViewProjectionMatrix; +uniform mat4 ViewMatrix; +uniform vec2 viewportSize; + +/* ---- Instanciated Attribs ---- */ +in vec2 pos; /* bone aligned screen space */ +in uint flag; + +#define COL_WIRE (1u << 0u) +#define COL_HEAD (1u << 1u) +#define COL_TAIL (1u << 2u) +#define COL_BONE (1u << 3u) + +#define POS_HEAD (1u << 4u) +#define POS_TAIL (1u << 5u) /* UNUSED */ +#define POS_BONE (1u << 6u) + +/* ---- Per instance Attribs ---- */ +in vec3 boneStart; +in vec3 boneEnd; +in vec4 wireColor; /* alpha encode if we do wire. If 0.0 we dont. */ +in vec4 boneColor; /* alpha encode if we do bone. If 0.0 we dont. */ +in vec4 headColor; /* alpha encode if we do head. If 0.0 we dont. */ +in vec4 tailColor; /* alpha encode if we do tail. If 0.0 we dont. */ + +#define do_wire (wireColor.a > 0.0) +#define is_head ((flag & POS_HEAD) != 0u) +#define is_bone ((flag & POS_BONE) != 0u) + +noperspective out float colorFac; +flat out vec4 finalWireColor; +flat out vec4 finalInnerColor; + +uniform float stickSize = 5.0; /* might be dependant on DPI setting in the future. */ + +/* project to screen space */ +vec2 proj(vec4 pos) +{ + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +} + +void main() +{ + finalInnerColor = ((flag & COL_HEAD) != 0u) ? headColor : tailColor; + finalInnerColor = ((flag & COL_BONE) != 0u) ? boneColor : finalInnerColor; + finalWireColor = (do_wire) ? wireColor : finalInnerColor; + /* Make the color */ + colorFac = ((flag & COL_WIRE) == 0u) ? ((flag & COL_BONE) != 0u) ? 1.0 : 2.0 : 0.0; + + vec4 v0 = ViewMatrix * vec4(boneStart, 1.0); + vec4 v1 = ViewMatrix * vec4(boneEnd, 1.0); + + /* Clip the bone to the camera origin plane (not the clip plane) + * to avoid glitches if one end is behind the camera origin (in persp). */ + const float clip_dist = -1e-7; /* hardcoded, -1e-8 is giving gliches. */ + vec3 bvec = v1.xyz - v0.xyz; + vec3 clip_pt = v0.xyz + bvec * ((v0.z - clip_dist) / -bvec.z); + if (v0.z > clip_dist) { + v0.xyz = clip_pt; + } + else if (v1.z > clip_dist) { + v1.xyz = clip_pt; + } + + vec4 p0 = ProjectionMatrix * v0; + vec4 p1 = ProjectionMatrix * v1; + + float h = (is_head) ? p0.w : p1.w; + + vec2 x_screen_vec = normalize(proj(p1) - proj(p0) + 1e-8); + vec2 y_screen_vec = vec2(x_screen_vec.y, -x_screen_vec.x); + + /* 2D screen aligned pos at the point */ + vec2 vpos = pos.x * x_screen_vec + pos.y * y_screen_vec; + vpos *= (ProjectionMatrix[3][3] == 0.0) ? h : 1.0; + vpos *= (do_wire) ? 1.0 : 0.5; + + if (finalInnerColor.a > 0.0) { + gl_Position = (is_head) ? p0 : p1; + gl_Position.xy += stickSize * (vpos / viewportSize); + gl_Position.z += (is_bone) ? 0.0 : 1e-6; /* Avoid Z fighting of head/tails. */ + } + else { + gl_Position = vec4(0.0); + } +} |