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:
authorBastien Montagne <montagne29@wanadoo.fr>2017-05-17 13:34:06 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2017-05-17 13:34:06 +0300
commit3c799ba8013405142430d7e20c272fe92457852d (patch)
treeca2a9aa891492b522f7ed32ce4a59142ffce7731 /source/blender/gpu
parent11c167ff763528dd0c3a5487f1dc3a49bcabef1a (diff)
DwM: Armature: Add distance outline and wire drawing of envelope bones.
This is not complete, it does not implement 3D solid drawing of envelope bones. 2D wire is hence always drawn for now. Some notes: I did not try to implement the 'capsule' approach suggested by @fclem, because: 1. I spent enough time on this already, and finally got something working. 2. I managed to get rid of geometry shader completely. 3. Current approach allows us to use same shader for distance outline and envelope wire. It's working fine, except for one glitch - superpositions of envelope outlines do not work as expected, not sure what's wrong here, tried to disable zbuff, enable GL_BLEND, no luck so far... I think we need our own 'background' drawpass to get them working (also to avoid them drawing over the wire lines).
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/CMakeLists.txt1
-rw-r--r--source/blender/gpu/GPU_shader.h2
-rw-r--r--source/blender/gpu/intern/gpu_shader.c4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_vert.glsl98
4 files changed, 105 insertions, 0 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 5d5ea179376..0a76f5da2ba 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -171,6 +171,7 @@ data_to_c_simple(shaders/gpu_shader_instance_camera_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_distance_line_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_bone_envelope_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC)
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 3f761cadfc2..076ca08cf6e 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -168,6 +168,8 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE,
GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR,
+ GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE,
+
GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
} GPUBuiltinShader;
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index d9228b42599..62f787b72ab 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -92,6 +92,7 @@ extern char datatoc_gpu_shader_instance_camera_vert_glsl[];
extern char datatoc_gpu_shader_instance_distance_line_vert_glsl[];
extern char datatoc_gpu_shader_instance_edges_variying_color_geom_glsl[];
extern char datatoc_gpu_shader_instance_edges_variying_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_bone_envelope_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundline_geom_glsl[];
@@ -786,6 +787,9 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR] = { datatoc_gpu_shader_instance_edges_variying_color_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl,
datatoc_gpu_shader_instance_edges_variying_color_geom_glsl},
+
+ [GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE] = { datatoc_gpu_shader_instance_bone_envelope_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl },
};
if (builtin_shaders[shader] == NULL) {
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_vert.glsl
new file mode 100644
index 00000000000..da0d14cd2af
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_vert.glsl
@@ -0,0 +1,98 @@
+
+
+/* This shader takes a 2D shape, puts it in 3D Object space such that is stays aligned with view and bone,
+ * and scales head/tail/distance according to per-instance attributes
+ * (and 'role' of current vertex, encoded in zw input, head or tail, and inner or outer for distance outline).
+ * It is used for both the distance outline drawing, and the wire version of envelope bone. */
+
+
+uniform mat4 ViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat4 ObjectModelMatrix;
+
+
+/* ---- Instanciated Attribs ---- */
+in vec4 pos; /* z encodes head (== 0.0f), tail (== 1.0f) or in-between; w encodes inner (0.0f) or outer border. */
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec4 color;
+
+in float radius_head;
+in float radius_tail;
+in float distance;
+
+
+flat out vec4 finalColor;
+
+
+void main()
+{
+ /* We get head/tail in object space. */
+ mat4 bone_mat = InstanceModelMatrix;
+ vec4 head = bone_mat * vec4(0.0f, 0.0f, 0.0f, 1.0f);
+ vec4 tail = bone_mat * vec4(0.0f, 1.0f, 0.0f, 1.0f);
+
+ /* We generate our XY axes in object space, Y axis being aligned with bone in view space. */
+ mat4 obview_mat = ViewMatrix * ObjectModelMatrix;
+ mat4 iobview_mat = inverse(obview_mat);
+
+ vec4 view_bone_vec = obview_mat * normalize(tail - head);
+ view_bone_vec.z = 0.0f;
+ if (length(view_bone_vec.xy) <= 1e-5f) {
+ /* A bit weak, but will do the job for now.
+ * Ideally we could compute head/tail radius in view space, and take larger one... */
+ if (view_bone_vec.x > view_bone_vec.y) {
+ view_bone_vec.x = 1e-5f;
+ }
+ else {
+ view_bone_vec.y = 1e-5f;
+ }
+ }
+ vec3 bone_axis_y = normalize((iobview_mat * view_bone_vec).xyz);
+ vec3 bone_axis_x = normalize(cross(bone_axis_y, iobview_mat[2].xyz));
+
+ /* Where does this comes from???? Don't know why, but is mandatory anyway... :/ */
+ float size = 2.0f;
+
+ head.xyz *= size;
+ tail.xyz *= size;
+
+ float head_fac = pos.z; // == 0: head; == 1: tail; in-between: along bone.
+ bool do_distance_offset = (pos.w != 0.0f);
+
+ vec2 xy_pos = pos.xy;
+ vec4 ob_pos;
+
+ vec4 ob_bone_origin;
+ float radius;
+
+ /* head */
+ if (head_fac <= 0.0f) {
+ radius = radius_head;
+ ob_bone_origin = head;
+ }
+ /* tail */
+ else if (head_fac >= 1.0f) {
+ radius = radius_tail;
+ ob_bone_origin = tail;
+ }
+ /* Body of the bone */
+#if 0 /* Note: not used currently! */
+ else {
+ float tail_fac = 1.0f - head_fac;
+ radius = radius_head * head_fac + radius_tail * tail_fac;
+ ob_bone_origin = head * head_fac + tail * tail_fac;
+ }
+#endif
+
+ if (do_distance_offset) {
+ radius += distance;
+ }
+
+ xy_pos = xy_pos * radius * size;
+
+ ob_pos = ob_bone_origin + vec4(bone_axis_x * xy_pos.x + bone_axis_y * xy_pos.y, 1.0f);
+ gl_Position = ProjectionMatrix * obview_mat * ob_pos;
+ finalColor = color;
+}