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 | |
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')
-rw-r--r-- | source/blender/gpu/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/gpu/GPU_shader.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader.c | 4 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl | 127 |
4 files changed, 133 insertions, 0 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 0a76f5da2ba..fcd50fa30e6 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -172,6 +172,7 @@ 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_instance_bone_envelope_solid_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 076ca08cf6e..342608032ab 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -169,6 +169,7 @@ typedef enum GPUBuiltinShader { GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR, GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE, + GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID, 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 62f787b72ab..9c6a16dc180 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -93,6 +93,7 @@ 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_instance_bone_envelope_solid_vert_glsl[]; extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[]; extern char datatoc_gpu_shader_3D_groundline_geom_glsl[]; @@ -790,6 +791,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) [GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE] = { datatoc_gpu_shader_instance_bone_envelope_vert_glsl, datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID] = { datatoc_gpu_shader_instance_bone_envelope_solid_vert_glsl, + datatoc_gpu_shader_simple_lighting_frag_glsl }, }; if (builtin_shaders[shader] == NULL) { @@ -806,6 +809,7 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) defines = "#define AXIS_NAME;\n"; break; case GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR: + case GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID: defines = "#define USE_INSTANCE_COLOR;\n"; break; case GPU_SHADER_3D_FLAT_COLOR_U32: 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; +} |