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:
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/CMakeLists.txt3
-rw-r--r--source/blender/draw/intern/draw_armature.c10
-rw-r--r--source/blender/draw/intern/draw_cache.c65
-rw-r--r--source/blender/draw/intern/draw_common.c46
-rw-r--r--source/blender/draw/intern/draw_common.h2
-rw-r--r--source/blender/draw/modes/shaders/armature_sphere_frag.glsl74
-rw-r--r--source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl102
-rw-r--r--source/blender/draw/modes/shaders/armature_sphere_vert.glsl79
8 files changed, 380 insertions, 1 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 27daab90234..3ab0ea40990 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -221,6 +221,9 @@ data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_view_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_fxaa_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_fullscreen_vert.glsl SRC)
+data_to_c_simple(modes/shaders/armature_sphere_vert.glsl SRC)
+data_to_c_simple(modes/shaders/armature_sphere_frag.glsl SRC)
+data_to_c_simple(modes/shaders/armature_sphere_outline_vert.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/edit_mesh_overlay_frag.glsl SRC)
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index 195acfb7c1f..756cc3e6992 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -250,8 +250,12 @@ static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4], const float
static void drw_shgroup_bone_point_solid(const float (*bone_mat)[4], const float color[4])
{
if (g_data.bone_point_solid == NULL) {
- struct Gwn_Batch *geom = DRW_cache_bone_point_get();
+#if 0 /* old style geometry sphere */
+ struct Gwn_Batch *geom = DRW_cache_bone_point_get()
g_data.bone_point_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
+#else /* new style raytraced sphere */
+ g_data.bone_point_solid = shgroup_instance_armature_sphere(g_data.pass_bone_solid);
+#endif
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
@@ -261,8 +265,12 @@ static void drw_shgroup_bone_point_solid(const float (*bone_mat)[4], const float
static void drw_shgroup_bone_point_wire(const float (*bone_mat)[4], const float color[4])
{
if (g_data.bone_point_wire == NULL) {
+#if 0 /* old style 3 axis circles */
struct Gwn_Batch *geom = DRW_cache_bone_point_wire_outline_get();
g_data.bone_point_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
+#else /* new style contour outline */
+ g_data.bone_point_wire = shgroup_instance_armature_sphere_outline(g_data.pass_bone_wire);
+#endif
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 439809139c9..587bcac1029 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -2082,6 +2082,7 @@ Gwn_Batch *DRW_cache_bone_envelope_head_wire_outline_get(void)
Gwn_Batch *DRW_cache_bone_point_get(void)
{
if (!SHC.drw_bone_point) {
+#if 0 /* old style geometry sphere */
const int lon_res = 16;
const int lat_res = 8;
const float rad = 0.05f;
@@ -2119,6 +2120,30 @@ Gwn_Batch *DRW_cache_bone_point_get(void)
}
SHC.drw_bone_point = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
+#else
+# define CIRCLE_RESOL 64
+ float v[2];
+ const float radius = 0.05f;
+
+ /* Position Only 2D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, CIRCLE_RESOL);
+
+ for (int a = 0; a < CIRCLE_RESOL; a++) {
+ v[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v);
+ }
+
+ SHC.drw_bone_point = GWN_batch_create_ex(GWN_PRIM_TRI_FAN, vbo, NULL, GWN_BATCH_OWNS_VBO);
+# undef CIRCLE_RESOL
+#endif
}
return SHC.drw_bone_point;
}
@@ -2126,8 +2151,48 @@ Gwn_Batch *DRW_cache_bone_point_get(void)
Gwn_Batch *DRW_cache_bone_point_wire_outline_get(void)
{
if (!SHC.drw_bone_point_wire) {
+#if 0 /* old style geometry sphere */
Gwn_VertBuf *vbo = sphere_wire_vbo(0.05f);
SHC.drw_bone_point_wire = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+#else
+# define CIRCLE_RESOL 64
+ float v0[2], v1[2];
+ const float radius = 0.05f;
+
+ /* Position Only 2D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos0, pos1; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos0 = GWN_vertformat_attr_add(&format, "pos0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ attr_id.pos1 = GWN_vertformat_attr_add(&format, "pos1", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, (CIRCLE_RESOL + 1) * 2);
+
+ v0[0] = radius * sinf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL));
+ v0[1] = radius * cosf((2.0f * M_PI * -1) / ((float)CIRCLE_RESOL));
+
+ unsigned int v = 0;
+ for (int a = 0; a < CIRCLE_RESOL; a++) {
+ v1[0] = radius * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v1[1] = radius * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos0, v , v0);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos0, v , v0);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
+ copy_v2_v2(v0, v1);
+ }
+ v1[0] = 0.0f;
+ v1[1] = radius;
+ GWN_vertbuf_attr_set(vbo, attr_id.pos0, v , v0);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos0, v , v0);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos1, v++, v1);
+
+ SHC.drw_bone_point_wire = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+# undef CIRCLE_RESOL
+#endif
}
return SHC.drw_bone_point_wire;
}
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index 3a2aa970a9b..6d684b1c9fb 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -156,12 +156,17 @@ void DRW_globals_update(void)
/* ********************************* SHGROUP ************************************* */
+extern char datatoc_armature_sphere_vert_glsl[];
+extern char datatoc_armature_sphere_frag_glsl[];
+extern char datatoc_armature_sphere_outline_vert_glsl[];
extern char datatoc_armature_shape_outline_vert_glsl[];
extern char datatoc_armature_shape_outline_geom_glsl[];
extern char datatoc_gpu_shader_flat_color_frag_glsl[];
static struct {
struct GPUShader *shape_outline;
+ struct GPUShader *bone_sphere;
+ struct GPUShader *bone_sphere_outline;
} g_armature_shaders = {NULL};
static struct {
@@ -491,6 +496,47 @@ DRWShadingGroup *shgroup_instance_armature_shape_outline(DRWPass *pass, struct G
return grp;
}
+DRWShadingGroup *shgroup_instance_armature_sphere(DRWPass *pass)
+{
+ if (g_armature_shaders.bone_sphere == NULL) {
+ g_armature_shaders.bone_sphere = DRW_shader_create(
+ datatoc_armature_sphere_vert_glsl, NULL,
+ datatoc_armature_sphere_frag_glsl, NULL);
+ }
+
+ /* TODO own format? */
+ DRW_shgroup_instance_format(g_formats.instance_color, {
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16},
+ {"color" , DRW_ATTRIB_FLOAT, 4}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(g_armature_shaders.bone_sphere,
+ pass, DRW_cache_bone_point_get(), g_formats.instance_color);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_armature_sphere_outline(DRWPass *pass)
+{
+ if (g_armature_shaders.bone_sphere_outline == NULL) {
+ g_armature_shaders.bone_sphere_outline = DRW_shader_create(
+ datatoc_armature_sphere_outline_vert_glsl, NULL,
+ datatoc_gpu_shader_flat_color_frag_glsl, NULL);
+ }
+
+ /* TODO own format? */
+ DRW_shgroup_instance_format(g_formats.instance_color, {
+ {"InstanceModelMatrix", DRW_ATTRIB_FLOAT, 16},
+ {"color" , DRW_ATTRIB_FLOAT, 4}
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(g_armature_shaders.bone_sphere_outline,
+ pass, DRW_cache_bone_point_wire_outline_get(),
+ g_formats.instance_color);
+ DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
+
+ return grp;
+}
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 8b418135342..ad6ab2d89fd 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -122,6 +122,8 @@ struct DRWShadingGroup *shgroup_instance_bone_envelope_wire(struct DRWPass *pass
struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_mball_handles(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_armature_shape_outline(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_instance_armature_sphere(struct DRWPass *pass);
+struct DRWShadingGroup *shgroup_instance_armature_sphere_outline(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_sphere_frag.glsl b/source/blender/draw/modes/shaders/armature_sphere_frag.glsl
new file mode 100644
index 00000000000..66d40e92bce
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_sphere_frag.glsl
@@ -0,0 +1,74 @@
+
+#extension GL_ARB_conservative_depth : enable
+
+uniform mat4 ViewMatrixInverse;
+uniform mat4 ProjectionMatrix;
+
+flat in vec3 solidColor;
+flat in mat4 sphereMatrix;
+in vec3 viewPosition;
+
+#ifdef GL_ARB_conservative_depth
+/* Saves a lot of overdraw! */
+layout(depth_greater) out float gl_FragDepth;
+#endif
+
+out vec4 fragColor;
+
+#define cameraPos ViewMatrixInverse[3].xyz
+
+float get_depth_from_view_z(float z)
+{
+ if (ProjectionMatrix[3][3] == 0.0) {
+ z = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2];
+ }
+ else {
+ z = z * ProjectionMatrix[2][2] / (1.0 - ProjectionMatrix[3][2]);
+ }
+ return z * 0.5 + 0.5;
+}
+
+void main()
+{
+ const float sphere_radius = 0.05;
+
+ bool is_perp = (ProjectionMatrix[3][3] == 0.0);
+ vec3 ray_ori_view = (is_perp) ? vec3(0.0) : viewPosition.xyz;
+ vec3 ray_dir_view = (is_perp) ? viewPosition : vec3(0.0, 0.0, -1.0);
+
+ /* Single matrix mul without branch. */
+ vec4 mul_vec = (is_perp) ? vec4(ray_dir_view, 0.0) : vec4(ray_ori_view, 1.0);
+ vec3 mul_res = (sphereMatrix * mul_vec).xyz;
+
+ /* Reminder :
+ * sphereMatrix[3] is the view space origin in sphere space (sph_ori -> view_ori).
+ * sphereMatrix[2] is the view space Z axis in sphere space. */
+
+ /* convert to sphere local space */
+ vec3 ray_ori = (is_perp) ? sphereMatrix[3].xyz : mul_res;
+ vec3 ray_dir = (is_perp) ? mul_res : -sphereMatrix[2].xyz;
+ float ray_len = length(ray_dir);
+ ray_dir /= ray_len;
+
+ /* Line to sphere intersect */
+ const float sphere_radius_sqr = sphere_radius * sphere_radius;
+ float b = dot(ray_ori, ray_dir);
+ float c = dot(ray_ori, ray_ori) - sphere_radius_sqr;
+ float h = b * b - c;
+ float t = -sqrt(max(0.0, h)) - b;
+
+ /* Compute dot product for lighting */
+ vec3 p = ray_dir * t + ray_ori; /* Point on sphere */
+ vec3 n = normalize(p); /* Normal is just the point in sphere space, normalized. */
+ vec3 l = normalize(sphereMatrix[2].xyz); /* Just the view Z axis in the sphere space. */
+ float col = clamp(dot(n, l), 0.0, 1.0);
+
+ /* 2x2 dither pattern to smooth the lighting. */
+ float dither = (0.5 + dot(vec2(ivec2(gl_FragCoord.xy) & ivec2(1)), vec2(1.0, 2.0))) * 0.25;
+ dither *= (1.0 / 255.0); /* Assume 8bit per color buffer. */
+
+ fragColor = vec4(col * solidColor + dither, 1.0);
+
+ t /= ray_len;
+ gl_FragDepth = get_depth_from_view_z(ray_dir_view.z * t + ray_ori_view.z);
+}
diff --git a/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl
new file mode 100644
index 00000000000..8fe20decdca
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl
@@ -0,0 +1,102 @@
+
+uniform mat4 ViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+uniform float lineThickness = 3.0;
+
+/* ---- Instanciated Attribs ---- */
+in vec2 pos0;
+in vec2 pos1;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec4 color;
+
+flat out vec4 finalColor;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+vec2 compute_dir(vec2 v0, vec2 v1, vec2 c)
+{
+ vec2 dir = normalize(v1 - v0);
+ dir = vec2(dir.y, -dir.x);
+ /* The model matrix can be scaled negativly.
+ * Use projected sphere center to determine
+ * the outline direction. */
+ vec2 cv = c - v0;
+ dir = (dot(dir, cv) > 0.0) ? -dir : dir;
+ return dir;
+}
+
+void main()
+{
+ mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix;
+ mat4 sphereMatrix = inverse(model_view_matrix);
+
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+
+ /* This is the local space camera ray (not normalize).
+ * In perspective mode it's also the viewspace position
+ * of the sphere center. */
+ vec3 cam_ray = (is_persp) ? model_view_matrix[3].xyz : vec3(0.0, 0.0, -1.0);
+ cam_ray = mat3(sphereMatrix) * cam_ray;
+
+ /* Sphere center distance from the camera (persp) in local space. */
+ float cam_dist = length(cam_ray);
+
+ /* Compute view aligned orthonormal space. */
+ vec3 z_axis = cam_ray / cam_dist;
+ vec3 x_axis = normalize(cross(sphereMatrix[1].xyz, z_axis));
+ vec3 y_axis = cross(z_axis, x_axis);
+ float z_ofs = 0.0;
+
+ if (is_persp) {
+ /* For perspective, the projected sphere radius
+ * can be bigger than the center disc. Compute the
+ * max angular size and compensate by sliding the disc
+ * towards the camera and scale it accordingly. */
+ const float half_pi = 3.1415926 * 0.5;
+ const float rad = 0.05;
+ /* Let be (in local space):
+ * V the view vector origin.
+ * O the sphere origin.
+ * T the point on the target circle.
+ * We compute the angle between (OV) and (OT). */
+ float a = half_pi - asin(rad / cam_dist);
+ float cos_b = cos(a);
+ float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0));
+
+ x_axis *= sin_b;
+ y_axis *= sin_b;
+ z_ofs = -rad * cos_b;
+ }
+
+ /* Camera oriented position (but still in local space) */
+ vec3 cam_pos0 = x_axis * pos0.x + y_axis * pos0.y + z_axis * z_ofs;
+ vec3 cam_pos1 = x_axis * pos1.x + y_axis * pos1.y + z_axis * z_ofs;
+
+ vec4 V = model_view_matrix * vec4(cam_pos0, 1.0);
+ vec4 p0 = ProjectionMatrix * V;
+ vec4 p1 = ProjectionMatrix * (model_view_matrix * vec4(cam_pos1, 1.0));
+ vec4 c = ProjectionMatrix * vec4(model_view_matrix[3].xyz, 1.0);
+
+ vec2 ssc = proj(c);
+ vec2 ss0 = proj(p0);
+ vec2 ss1 = proj(p1);
+ vec2 edge_dir = compute_dir(ss0, ss1, ssc);
+
+ bool outer = ((gl_VertexID & 1) == 1);
+
+ vec2 t = lineThickness / viewportSize;
+ t *= (is_persp) ? abs(V.z) : 1.0;
+ t = (outer) ? t : vec2(0.0);
+
+ gl_Position = p0;
+ gl_Position.xy += t * edge_dir;
+
+ finalColor = color;
+}
diff --git a/source/blender/draw/modes/shaders/armature_sphere_vert.glsl b/source/blender/draw/modes/shaders/armature_sphere_vert.glsl
new file mode 100644
index 00000000000..fdd27de0eb1
--- /dev/null
+++ b/source/blender/draw/modes/shaders/armature_sphere_vert.glsl
@@ -0,0 +1,79 @@
+
+uniform mat4 ViewMatrix;
+uniform mat4 ProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec2 pos;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec3 color;
+
+flat out vec3 solidColor;
+flat out mat4 sphereMatrix;
+out vec3 viewPosition;
+
+/* Sphere radius */
+const float rad = 0.05;
+
+void main()
+{
+ mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix;
+ sphereMatrix = inverse(model_view_matrix);
+
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+
+ /* This is the local space camera ray (not normalize).
+ * In perspective mode it's also the viewspace position
+ * of the sphere center. */
+ vec3 cam_ray = (is_persp) ? model_view_matrix[3].xyz : vec3(0.0, 0.0, -1.0);
+ cam_ray = mat3(sphereMatrix) * cam_ray;
+
+ /* Sphere center distance from the camera (persp) in local space. */
+ float cam_dist = length(cam_ray);
+
+ /* Compute view aligned orthonormal space. */
+ vec3 z_axis = cam_ray / cam_dist;
+ vec3 x_axis = normalize(cross(sphereMatrix[1].xyz, z_axis));
+ vec3 y_axis = cross(z_axis, x_axis);
+
+ float z_ofs = -rad - 1e-8; /* offset to the front of the sphere */
+ if (is_persp) {
+ /* For perspective, the projected sphere radius
+ * can be bigger than the center disc. Compute the
+ * max angular size and compensate by sliding the disc
+ * towards the camera and scale it accordingly. */
+ const float half_pi = 3.1415926 * 0.5;
+ /* Let be (in local space):
+ * V the view vector origin.
+ * O the sphere origin.
+ * T the point on the target circle.
+ * We compute the angle between (OV) and (OT). */
+ float a = half_pi - asin(rad / cam_dist);
+ float cos_b = cos(a);
+ float sin_b = sqrt(clamp(1.0 - cos_b * cos_b, 0.0, 1.0));
+#if 1
+ /* Instead of choosing the biggest circle in screenspace,
+ * we choose the nearest with the same angular size. This
+ * permit us to leverage GL_ARB_conservative_depth in the
+ * fragment shader. */
+ float minor = cam_dist - rad;
+ float major = cam_dist - cos_b * rad;
+ float fac = minor / major;
+ sin_b *= fac;
+#else
+ z_ofs = -rad * cos_b;
+#endif
+ x_axis *= sin_b;
+ y_axis *= sin_b;
+ }
+
+ /* Camera oriented position (but still in local space) */
+ vec3 cam_pos = x_axis * pos.x + y_axis * pos.y + z_axis * z_ofs;
+
+ vec4 V = model_view_matrix * vec4(cam_pos, 1.0);
+ gl_Position = ProjectionMatrix * V;
+ viewPosition = V.xyz;
+
+ solidColor = color;
+}