[Bf-blender-cvs] [8c2a6f957ad] blender2.8: Armature: "Raytrace" bones endpoint spheres.

Clément Foucault noreply at git.blender.org
Wed May 2 20:54:37 CEST 2018


Commit: 8c2a6f957ada6cca4b870c094979f9c3e6d43fa7
Author: Clément Foucault
Date:   Fri Apr 27 16:27:47 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB8c2a6f957ada6cca4b870c094979f9c3e6d43fa7

Armature: "Raytrace" bones endpoint spheres.

Here is how it works:
We render a high poly disc that we orient & scale towards the camera so that
it covers the same pixel of the sphere it's supposed to represent.

Then the pixel shader raytrace the sphere (effectively starting from
the poly disc depth) and outputs the depth to gl_FragDepth.

This approach has many benefit:
- high quality obviously: per pixel accurate depth!
- compatible with MSAA: since the sphere horizon is delimited by polygons,
  we get the coverage computed by the rasterizer. However we still gets
  aliasing if the sphere intersect directly other meshes.
- virtually no overdraw: there is no backface to shade but we still get
  overdraw because by little triangle [gpus rasterize pixel by groups of 4].
- allows early depth test: since the poly disc is set at the nearest depth
  we can output, we can use GL_ARB_conservative_depth to enable early depth
  test and discard pixels that are already behind geometry.
- can draw outline pretty easily without geometry shader.

===================================================================

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/intern/draw_armature.c
M	source/blender/draw/intern/draw_cache.c
M	source/blender/draw/intern/draw_common.c
M	source/blender/draw/intern/draw_common.h
A	source/blender/draw/modes/shaders/armature_sphere_frag.glsl
A	source/blender/draw/modes/shaders/armature_sphere_outline_vert.glsl
A	source/blender/draw/modes/shaders/armature_sphere_vert.glsl

===================================================================

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 {
+		

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list