Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-05-08 13:05:06 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-05-08 13:18:35 +0300
commit9a79178c2eb79e724077d38cd2dd964d0b6ca0ea (patch)
tree0af8bc089ad3b7b5f978d700af29503358d21890 /source/blender/draw
parentd8706f54074675f8af83471398d35def0b351484 (diff)
Armature: Add back Stick bone draw type.
The actual code is a bit convoluted but allows good and "pseudo efficient" drawing. (pseudo efficient because rendering instances with that amount of vertices is really inneficient. We should go full procedural but need to have bufferTexture implemented first) But drawing speed is not a bottleneck here and it's already a million time less crappy than the old (2.79) immediate mode method. Instead of drawing actual wires with different width we render a triangle fan batch (containing 3 fans: bone, head, tail) which is then oriented in screen space to the bone direction. We then interpolate a float value accross vertices giving us a nice blend factor to blend the colors and gives us really smooth interpolation inside the bone. The outside edge still being geometry will be antialiased by MSAA if enabled.
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/intern/draw_armature.c74
-rw-r--r--source/blender/draw/intern/draw_cache.c77
-rw-r--r--source/blender/draw/intern/draw_cache.h1
-rw-r--r--source/blender/draw/intern/draw_common.c28
-rw-r--r--source/blender/draw/intern/draw_common.h1
-rw-r--r--source/blender/draw/modes/shaders/armature_stick_frag.glsl13
-rw-r--r--source/blender/draw/modes/shaders/armature_stick_vert.glsl88
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);
+ }
+}