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:
-rw-r--r--source/blender/draw/intern/draw_armature.c12
-rw-r--r--source/blender/draw/intern/draw_cache.c44
-rw-r--r--source/blender/draw/modes/shaders/armature_envelope_vert.glsl84
3 files changed, 29 insertions, 111 deletions
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index 5a3c03d5be2..ec2751d661b 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -189,12 +189,6 @@ static void drw_shgroup_bone_envelope_distance(
head_sphere[3] += *distance;
tail_sphere[3] = *radius_tail;
tail_sphere[3] += *distance;
-
- /* Shader transform is nicer if tail is the biggest. */
- if (*radius_head > *radius_tail) {
- swap_v4_v4(head_sphere, tail_sphere);
- }
-
DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, head_sphere, tail_sphere, color, final_bonemat[0]);
}
}
@@ -232,12 +226,6 @@ static void drw_shgroup_bone_envelope(
/* Draw Body */
float tmp_sphere[4];
float len = len_v3v3(tail_sphere, head_sphere);
-
- /* Shader transform is nicer if tail is the biggest. */
- if (*radius_head > *radius_tail) {
- swap_v4_v4(head_sphere, tail_sphere);
- }
-
float fac_head = (len - head_sphere[3]) / len;
float fac_tail = (len - tail_sphere[3]) / len;
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index aa21bb7214a..be4c1783aff 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -85,7 +85,6 @@ static struct DRWShapeCache {
Gwn_Batch *drw_bone_box_wire;
Gwn_Batch *drw_bone_wire_wire;
Gwn_Batch *drw_bone_envelope;
- Gwn_Batch *drw_bone_envelope_distance;
Gwn_Batch *drw_bone_envelope_outline;
Gwn_Batch *drw_bone_point;
Gwn_Batch *drw_bone_point_wire;
@@ -1881,20 +1880,18 @@ Gwn_Batch *DRW_cache_bone_wire_wire_outline_get(void)
* Note that here we only encode head/tail in forth component of the vector. */
static void benv_lat_lon_to_co(const float lat, const float lon, float r_nor[3])
{
- /* Poles are along Y axis. */
r_nor[0] = sinf(lat) * cosf(lon);
- r_nor[1] = -cosf(lat);
- r_nor[2] = sinf(lat) * sinf(lon);
+ r_nor[1] = sinf(lat) * sinf(lon);
+ r_nor[2] = cosf(lat);
}
Gwn_Batch *DRW_cache_bone_envelope_solid_get(void)
{
if (!SHC.drw_bone_envelope) {
const int lon_res = 24;
- const int lat_res = 16;
+ const int lat_res = 24;
const float lon_inc = 2.0f * M_PI / lon_res;
const float lat_inc = M_PI / lat_res;
- const float eps = 0.02f;
unsigned int v_idx = 0;
static Gwn_VertFormat format = { 0 };
@@ -1905,14 +1902,16 @@ Gwn_Batch *DRW_cache_bone_envelope_solid_get(void)
/* Vertices */
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, ((lat_res + 1) * 2) * lon_res * 2);
+ GWN_vertbuf_data_alloc(vbo, ((lat_res + 1) * 2) * lon_res * 1);
- float lon = lon_inc;
+ float lon = 0.0f;
for (int i = 0; i < lon_res; i++, lon += lon_inc) {
float lat = 0.0f;
float co1[4], co2[4];
co1[3] = co2[3] = 0.0f;
+ /* Note: the poles are duplicated on purpose, to restart the strip. */
+
/* 1st sphere */
for (int j = 0; j < lat_res; j++, lat += lat_inc) {
benv_lat_lon_to_co(lat, lon, co1);
@@ -1921,36 +1920,13 @@ Gwn_Batch *DRW_cache_bone_envelope_solid_get(void)
GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
}
- /* Need to close the sphere, but add a small gap to be able
- * to distinguish the verts in the vertex shader. */
- benv_lat_lon_to_co(M_PI - eps, lon, co1);
- benv_lat_lon_to_co(M_PI - eps, lon + lon_inc, co2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
-
- /* Add some precision to the middle part */
- // co1[3] = co2[3] = 0.5f;
- // co1[1] = co2[1] = 0.0f;
- // GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
- // GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
- /* 2nd sphere */
- co1[3] = co2[3] = 1.0f;
+ /* Closing the loop */
+ benv_lat_lon_to_co(M_PI, lon, co1);
+ benv_lat_lon_to_co(M_PI, lon + lon_inc, co2);
- /* Need to open the sphere */
- benv_lat_lon_to_co(eps, lon, co1);
- benv_lat_lon_to_co(eps, lon + lon_inc, co2);
GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
-
- lat = lat_inc;
- for (int j = 1; j < lat_res + 1; j++, lat += lat_inc) {
- benv_lat_lon_to_co(lat, lon, co1);
- benv_lat_lon_to_co(lat, lon + lon_inc, co2);
-
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, co2);
- }
}
SHC.drw_bone_envelope = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
diff --git a/source/blender/draw/modes/shaders/armature_envelope_vert.glsl b/source/blender/draw/modes/shaders/armature_envelope_vert.glsl
index fbce8ca69dd..6de842fdcb2 100644
--- a/source/blender/draw/modes/shaders/armature_envelope_vert.glsl
+++ b/source/blender/draw/modes/shaders/armature_envelope_vert.glsl
@@ -1,4 +1,5 @@
+uniform mat4 ViewMatrix;
uniform mat4 ViewMatrixInverse;
uniform mat4 ViewProjectionMatrix;
@@ -15,80 +16,33 @@ in vec3 xAxis;
flat out vec4 finalColor;
out vec3 normalView;
-struct Bone { vec3 p1, vec; float r1, rdif, vec_rsq, h_bias, h_scale; };
-
-float sdf_bone(vec3 p, Bone b)
-{
- /* Simple capsule sdf with a minor touch and optimisations. */
- vec3 pa = p - b.p1;
- float h = dot(pa, b.vec) * b.vec_rsq;
- h = h * b.h_scale + b.h_bias; /* comment this line for sharp transition. */
- h = clamp(h, 0.0, 1.0);
- return length(pa - b.vec * h) - (b.r1 + b.rdif * h);
-}
-
void main()
{
- /* Raytracing against cone need a parametric definition of the cone
- * using axis, angle and apex. But if both sphere are nearly the same
- * size, the apex become ill defined, and so does the angle.
- * So to circumvent this, we use the numerical solution: raymarching.
- * But due to the the cost of raymarching per pixel, we choose to use it
- * to position vertices from a VBO with the distance field.
- * The nice thing is that we start the raymarching really near the surface
- * so we actually need very few iterations to get a good result. */
+ vec3 bone_vec = tailSphere.xyz - headSphere.xyz;
+ float bone_len = max(1e-8, sqrt(dot(bone_vec, bone_vec)));
+ float bone_lenrcp = 1.0 / bone_len;
+ float sinb = (tailSphere.w - headSphere.w) * bone_lenrcp;
- Bone b;
- /* Precompute everything we can to speedup iterations. */
- b.p1 = headSphere.xyz;
- b.r1 = headSphere.w;
- b.rdif = tailSphere.w - headSphere.w;
- b.vec = tailSphere.xyz - headSphere.xyz;
- float vec_lsq = max(1e-8, dot(b.vec, b.vec));
- b.vec_rsq = 1.0 / vec_lsq;
- float sinb = (tailSphere.w - headSphere.w) * b.vec_rsq;
- float ofs1 = sinb * headSphere.w;
- float ofs2 = sinb * tailSphere.w;
- b.h_scale = 1.0 - ofs1 + ofs2;
- b.h_bias = ofs1 * b.h_scale;
-
- /* Radius for the initial position */
- float rad = b.r1 + b.rdif * pos.w;
-
- float vec_len = sqrt(vec_lsq);
- vec3 y_axis = b.vec / max(1e-8, vec_len);
+ vec3 y_axis = bone_vec * bone_lenrcp;
vec3 z_axis = normalize(cross(xAxis, -y_axis));
- vec3 x_axis = cross(y_axis, -z_axis); /* cannot trust xAxis to be orthogonal. */
-
- vec3 sp = pos.xyz * rad;
- if (pos.w == 1.0) {
- /* Prevent tail sphere to cover the head sphere if head is really big. */
- sp.y = max(sp.y, -(vec_len - headSphere.w));
- sp.y += vec_len; /* Position tail on the Bone axis. */
- }
+ vec3 x_axis = cross(y_axis, z_axis); /* cannot trust xAxis to be orthogonal. */
- /* p is vertex position in world space */
- vec3 p = mat3(x_axis, y_axis, z_axis) * sp;
- p += headSphere.xyz;
+ vec3 sp, nor;
+ nor = sp = pos.xyz;
- /* push vert towards the capsule boundary */
- vec3 dir = vec3(normalize(pos.xz + 1e-8), 0.0);
- dir = mat3(x_axis, y_axis, z_axis) * dir.xzy;
+ /* In bone space */
+ bool is_head = (pos.z < -sinb);
+ sp *= (is_head) ? headSphere.w : tailSphere.w;
+ sp.z += (is_head) ? 0.0 : bone_len;
- /* Signed distance field gives us the distance to the surface.
- * Use a few iteration for precision. */
- p = p - dir * sdf_bone(p, b);
- p = p - dir * sdf_bone(p, b);
- p = p - dir * sdf_bone(p, b);
- p = p - dir * sdf_bone(p, b);
- p = p - dir * sdf_bone(p, b);
+ /* Convert to world space */
+ mat3 bone_mat = mat3(x_axis, y_axis, z_axis);
+ sp = bone_mat * sp.xzy + headSphere.xyz;
+ nor = bone_mat * nor.xzy;
- const float eps = 0.0005;
- normalView.x = sdf_bone(p + ViewMatrixInverse[0].xyz * eps, b);
- normalView.y = sdf_bone(p + ViewMatrixInverse[1].xyz * eps, b);
- normalView.z = sdf_bone(p + ViewMatrixInverse[2].xyz * eps, b);
+ normalView = mat3(ViewMatrix) * nor;
- gl_Position = ViewProjectionMatrix * vec4(p, 1.0);
+ gl_Position = ViewProjectionMatrix * vec4(sp, 1.0);
finalColor = color;
}