diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2017-05-18 12:41:59 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2017-05-18 13:13:19 +0300 |
commit | 23f256b24bed34bb25d1d66ec9ba0726f7a71659 (patch) | |
tree | 7dfb39a8a493ff015ac0dae82e07cb6c9795d08f /source/blender/gpu/shaders | |
parent | 5919919955f6ec40f881705e587355d0334c00ea (diff) |
DwM: Armature: add solid envelope bone drawing.
Envelope bones are now pretty much identical to old drawing code.
Note that currently new DwM drawing code does not seem to care about
wire/solid drawing modes at all, guess this is still TODO... For now we
hence just get both wire and solid for envelope bones, this can be
refined later.
Diffstat (limited to 'source/blender/gpu/shaders')
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl new file mode 100644 index 00000000000..f2e562c3b4a --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl @@ -0,0 +1,127 @@ + + +/* 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 ObjectModelMatrix; +uniform mat4 ViewProjectionMatrix; + + +/* ---- Instanciated Attribs ---- */ +in vec4 pos; /* w encodes head (== 0.0f), tail (== 1.0f) or in-between. */ + +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; +in vec4 color; + +in float radius_head; +in float radius_tail; + + +out vec3 normal; +flat out vec4 finalColor; + + +void main() +{ +// gl_Position = ViewProjectionMatrix * ObjectModelMatrix * InstanceModelMatrix * vec4(pos.xyz, 1.0f); +// normal = pos.xyz; +// finalColor = color; +// return; + + /* We get head/tail in object space. */ + vec4 head = InstanceModelMatrix * vec4(0.0f, 0.0f, 0.0f, 1.0f); + vec4 tail = InstanceModelMatrix * vec4(0.0f, 1.0f, 0.0f, 1.0f); + + /* We need rotation from bone mat, but not scaling. */ + mat3 bone_mat = mat3(InstanceModelMatrix); + bone_mat[0] = normalize(bone_mat[0]); + bone_mat[1] = normalize(bone_mat[1]); + bone_mat[2] = normalize(bone_mat[2]); + + mat3 nor_mat = transpose(inverse(mat3(ViewMatrix * ObjectModelMatrix) * bone_mat)); + + /* Where does this comes from???? Don't know why, but is mandatory anyway... :/ */ + const float size = 2.0f; + + head.xyz *= size; + tail.xyz *= size; + + bool head_only = (radius_tail < 0.0f); + bool tail_only = (radius_head < 0.0f); + /* == 0: head; == 1: tail; in-between: along bone. */ + float head_fac = head_only ? 0.0f : (tail_only ? 1.0f : pos.w); + + vec4 ob_pos; + vec4 ob_bone_origin; + float radius; + + /* head */ + if (head_fac <= 0.0f) { + if (!head_only) { + /* We are drawing the body itself, need to adjust start/end positions and radius! */ + vec3 bone_vec = tail.xyz - head.xyz; + float len = length(bone_vec); + + if (len > (radius_head + radius_tail)) { + float fac = (len - radius_head) / len; + radius = fac * radius_head + (1.0f - fac) * radius_tail; + bone_vec /= len; + ob_bone_origin = vec4(head.xyz + bone_vec * radius_head * size, 1.0f); + } + else { + radius = (radius_head + radius_tail) / 2.0f; + ob_bone_origin = (head + tail) / 2.0f; + } + } + else { + radius = radius_head; + ob_bone_origin = head; + } + } + /* tail */ + else if (head_fac >= 1.0f) { + if (!tail_only) { + /* We are drawing the body itself, need to adjust start/end positions and radius! */ + vec3 bone_vec = tail.xyz - head.xyz; + float len = length(bone_vec); + + if (len > (radius_head + radius_tail)) { + float fac = (len - radius_tail) / len; + radius = fac * radius_tail + (1.0f - fac) * radius_head; + bone_vec /= len; + ob_bone_origin = vec4(tail.xyz - bone_vec * radius_tail * size, 1.0f); + } + else { + radius = (radius_head + radius_tail) / 2.0f; + ob_bone_origin = (head + tail) / 2.0f; + } + } + else { + 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 + + /* Yep, since input pos is unit sphere coordinates, it's also our normal. */ + vec3 nor = pos.xyz; + ob_pos = pos * radius * size; + ob_pos.xyz = bone_mat * ob_pos.xyz; + ob_pos.w = 1.0f; + + gl_Position = ViewProjectionMatrix * ObjectModelMatrix * (ob_pos + ob_bone_origin); + normal = normalize(nor_mat * nor); + finalColor = color; +} |