[Bf-blender-cvs] [3685347b417] master: Selection: Add conservative rasterization to select really small objects

Clément Foucault noreply at git.blender.org
Tue Feb 4 15:22:08 CET 2020


Commit: 3685347b417259f08060d914b4447d0190a5f57e
Author: Clément Foucault
Date:   Tue Feb 4 15:19:28 2020 +0100
Branches: master
https://developer.blender.org/rB3685347b417259f08060d914b4447d0190a5f57e

Selection: Add conservative rasterization to select really small objects

The conservative depth shader is ~4.5x slower than the normal one as it
uses geometry shader and fragment shader discard.

This patch also includes a hack to also fix the view parallel planar
geometry and the really small wire objects.

For some reason, the conservative raster fix does not work with normal
selection but does with box select.

This is a fix for T63356.

Reviewed By: campbellbarton

Differential Revision: https://developer.blender.org/D6714

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

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/engines/basic/basic_engine.c
M	source/blender/draw/engines/basic/basic_engine.h
A	source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl
A	source/blender/draw/engines/basic/shaders/conservative_depth_geom.glsl
A	source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl
M	source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
M	source/blender/draw/intern/draw_manager.c

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

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 6c55fa7ce30..a74a255045a 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -307,6 +307,10 @@ data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl SRC)
 data_to_c_simple(engines/select/shaders/selection_id_3D_vert.glsl SRC)
 data_to_c_simple(engines/select/shaders/selection_id_frag.glsl SRC)
 
+data_to_c_simple(engines/basic/shaders/conservative_depth_geom.glsl SRC)
+data_to_c_simple(engines/basic/shaders/conservative_depth_vert.glsl SRC)
+data_to_c_simple(engines/basic/shaders/conservative_depth_frag.glsl SRC)
+
 data_to_c_simple(engines/overlay/shaders/antialiasing_frag.glsl SRC)
 data_to_c_simple(engines/overlay/shaders/antialiasing_vert.glsl SRC)
 data_to_c_simple(engines/overlay/shaders/armature_dof_vert.glsl SRC)
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index fcbe227ca1b..79da067095a 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -37,6 +37,12 @@
 
 #define BASIC_ENGINE "BLENDER_BASIC"
 
+extern char datatoc_conservative_depth_frag_glsl[];
+extern char datatoc_conservative_depth_vert_glsl[];
+extern char datatoc_conservative_depth_geom_glsl[];
+
+extern char datatoc_common_view_lib_glsl[];
+
 /* *********** LISTS *********** */
 
 /* GPUViewport.storage
@@ -61,6 +67,7 @@ typedef struct BASIC_Data {
 typedef struct BASIC_Shaders {
   /* Depth Pre Pass */
   struct GPUShader *depth;
+  struct GPUShader *depth_conservative;
 } BASIC_Shaders;
 
 /* *********** STATIC *********** */
@@ -84,6 +91,22 @@ static void basic_engine_init(void *UNUSED(vedata))
   /* Depth prepass */
   if (!sh_data->depth) {
     sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg);
+
+    const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+    sh_data->depth_conservative = GPU_shader_create_from_arrays({
+        .vert = (const char *[]){sh_cfg->lib,
+                                 datatoc_common_view_lib_glsl,
+                                 datatoc_conservative_depth_vert_glsl,
+                                 NULL},
+        .geom = (const char *[]){sh_cfg->lib,
+                                 datatoc_common_view_lib_glsl,
+                                 datatoc_conservative_depth_geom_glsl,
+                                 NULL},
+        .frag = (const char *[]){datatoc_common_view_lib_glsl,
+                                 datatoc_conservative_depth_frag_glsl,
+                                 NULL},
+        .defs = (const char *[]){sh_cfg->def, NULL},
+    });
   }
 }
 
@@ -91,6 +114,7 @@ static void basic_cache_init(void *vedata)
 {
   BASIC_PassList *psl = ((BASIC_Data *)vedata)->psl;
   BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl;
+  DRWShadingGroup *grp;
 
   const DRWContextState *draw_ctx = DRW_context_state_get();
   BASIC_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
@@ -106,12 +130,18 @@ static void basic_cache_init(void *vedata)
     DRWState infront_state = (DRW_state_is_select() && (i == 1)) ? DRW_STATE_IN_FRONT_SELECT : 0;
     DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
 
+    GPUShader *sh = DRW_state_is_select() ? sh_data->depth_conservative : sh_data->depth;
+
     DRW_PASS_CREATE(psl->depth_pass[i], state | clip_state | infront_state);
-    stl->g_data->depth_shgrp[i] = DRW_shgroup_create(sh_data->depth, psl->depth_pass[i]);
+    stl->g_data->depth_shgrp[i] = grp = DRW_shgroup_create(sh, psl->depth_pass[i]);
+    DRW_shgroup_uniform_vec2(grp, "sizeViewport", DRW_viewport_size_get(), 1);
+    DRW_shgroup_uniform_vec2(grp, "sizeViewportInv", DRW_viewport_invert_size_get(), 1);
 
     state |= DRW_STATE_CULL_BACK;
     DRW_PASS_CREATE(psl->depth_pass_cull[i], state | clip_state | infront_state);
-    stl->g_data->depth_shgrp_cull[i] = DRW_shgroup_create(sh_data->depth, psl->depth_pass_cull[i]);
+    stl->g_data->depth_shgrp_cull[i] = grp = DRW_shgroup_create(sh, psl->depth_pass_cull[i]);
+    DRW_shgroup_uniform_vec2(grp, "sizeViewport", DRW_viewport_size_get(), 1);
+    DRW_shgroup_uniform_vec2(grp, "sizeViewportInv", DRW_viewport_invert_size_get(), 1);
   }
 }
 
@@ -197,7 +227,10 @@ static void basic_draw_scene(void *vedata)
 
 static void basic_engine_free(void)
 {
-  /* all shaders are builtin */
+  for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) {
+    BASIC_Shaders *sh_data = &e_data.sh_data[i];
+    DRW_SHADER_FREE_SAFE(sh_data->depth_conservative);
+  }
 }
 
 static const DrawEngineDataSize basic_data_size = DRW_VIEWPORT_DATA_SIZE(BASIC_Data);
@@ -219,23 +252,4 @@ DrawEngineType draw_engine_basic_type = {
     NULL,
 };
 
-/* Note: currently unused, we may want to register so we can see this when debugging the view. */
-
-RenderEngineType DRW_engine_viewport_basic_type = {
-    NULL,
-    NULL,
-    BASIC_ENGINE,
-    N_("Basic"),
-    RE_INTERNAL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    &draw_engine_basic_type,
-    {NULL, NULL, NULL},
-};
-
 #undef BASIC_ENGINE
diff --git a/source/blender/draw/engines/basic/basic_engine.h b/source/blender/draw/engines/basic/basic_engine.h
index a32467786de..d17f1c24c37 100644
--- a/source/blender/draw/engines/basic/basic_engine.h
+++ b/source/blender/draw/engines/basic/basic_engine.h
@@ -24,6 +24,5 @@
 #define __BASIC_ENGINE_H__
 
 extern DrawEngineType draw_engine_basic_type;
-extern RenderEngineType DRW_engine_viewport_basic_type;
 
 #endif /* __BASIC_ENGINE_H__ */
diff --git a/source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl b/source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl
new file mode 100644
index 00000000000..cedb0059794
--- /dev/null
+++ b/source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl
@@ -0,0 +1,5 @@
+
+void main()
+{
+  /* Passthrough shader. */
+}
\ No newline at end of file
diff --git a/source/blender/draw/engines/basic/shaders/conservative_depth_geom.glsl b/source/blender/draw/engines/basic/shaders/conservative_depth_geom.glsl
new file mode 100644
index 00000000000..fc5ea221348
--- /dev/null
+++ b/source/blender/draw/engines/basic/shaders/conservative_depth_geom.glsl
@@ -0,0 +1,59 @@
+
+/* Adaptation of Conservative Rasterization
+ * from GPU Gems 2
+ * Using method 2.
+ *
+ * Actual final implementation does not do conservative rasterization and only
+ * avoids triangles producing no fragments.
+ */
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices = 3) out;
+
+RESOURCE_ID_VARYING
+
+uniform vec2 sizeViewport;
+uniform vec2 sizeViewportInv;
+
+void main()
+{
+  /* Compute plane normal in ndc space. */
+  vec3 pos0 = gl_in[0].gl_Position.xyz / gl_in[0].gl_Position.w;
+  vec3 pos1 = gl_in[1].gl_Position.xyz / gl_in[1].gl_Position.w;
+  vec3 pos2 = gl_in[2].gl_Position.xyz / gl_in[2].gl_Position.w;
+  vec3 plane = normalize(cross(pos1 - pos0, pos2 - pos0));
+  /* Compute NDC bound box. */
+  vec4 bbox = vec4(min(min(pos0.xy, pos1.xy), pos2.xy), max(max(pos0.xy, pos1.xy), pos2.xy));
+  /* Convert to pixel space. */
+  bbox = (bbox * 0.5 + 0.5) * sizeViewport.xyxy;
+  /* Detect failure cases where triangles would produce no fragments. */
+  bvec2 is_subpixel = lessThan(bbox.zw - bbox.xy, vec2(1.0));
+  /* View aligned triangle. */
+  const float threshold = 0.00001;
+  bool is_coplanar = abs(plane.z) < threshold;
+
+  for (int i = 0; i < 3; i++) {
+    gl_Position = gl_in[i].gl_Position;
+    if (all(is_subpixel)) {
+      vec2 ofs = (i == 0) ? vec2(-1.0) : ((i == 1) ? vec2(2.0, -1.0) : vec2(-1.0, 2.0));
+      /* HACK: Fix cases where the triangle is too small make it cover at least one pixel. */
+      gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ofs;
+    }
+    /* Test if the triangle is almost parralele with the view to avoid precision issues. */
+    else if (any(is_subpixel) || is_coplanar) {
+      /* HACK: Fix cases where the triangle is Parallel to the view by deforming it slightly. */
+      vec2 ofs = (i == 0) ? vec2(-1.0) : ((i == 1) ? vec2(1.0, -1.0) : vec2(1.0));
+      gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ofs;
+    }
+    else {
+      /* Triangle expansion should happen here, but we decide to not implement it for
+       * depth precision & performance reasons. */
+    }
+
+#ifdef USE_WORLD_CLIP_PLANES
+    world_clip_planes_set_clip_distance(gl_in[i].gl_ClipDistance);
+#endif
+    EmitVertex();
+  }
+  EndPrimitive();
+}
\ No newline at end of file
diff --git a/source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl b/source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl
new file mode 100644
index 00000000000..c55a3211ff2
--- /dev/null
+++ b/source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl
@@ -0,0 +1,17 @@
+
+RESOURCE_ID_VARYING
+
+in vec3 pos;
+
+void main()
+{
+  GPU_INTEL_VERTEX_SHADER_WORKAROUND
+  PASS_RESOURCE_ID
+
+  vec3 world_pos = point_object_to_world(pos);
+  gl_Position = point_world_to_ndc(world_pos);
+
+#ifdef USE_WORLD_CLIP_PLANES
+  world_clip_planes_calc_clip_distance(world_pos);
+#endif
+}
diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
index a2fa82d151e..4d705a4ee2b 100644
--- a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
@@ -148,6 +148,12 @@ void main()
     edgeStart = vec2(-1.0);
   }
 
+#ifdef SELECT_EDGES
+  /* HACK: to avoid loosing sub pixel object in selections, we add a bit of randomness to the
+   * wire to at least create one fragment that will pass the occlusion query. */
+  gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexID % 2 == 0) ? -1.0 : 1.0);
+#endif
+
 #ifdef USE_WORLD_CLIP_PLANES
   world_clip_planes_calc_clip_distance(wpos);
 #endif
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 7397490d406..3dc775f92c4 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list