View3D Grid: fix imperial grid drawing
authormano-wii <germano.costa@ig.com.br>
Mon, 19 Aug 2019 14:49:07 +0000 (11:49 -0300)
committermano-wii <germano.costa@ig.com.br>
Mon, 19 Aug 2019 15:05:57 +0000 (12:05 -0300)
This is a step to finish the D4325 and fix the T61286.
Currently the grid is highlighted in steps of 10 out of 10, which is wrong for the imperial units as seen in `buImperialLenDef`.
The idea of the code is to pass the steps of the grid already dimensioned as a uniform.

Another important thing to note is that subdivisions now only affect the grid without unity.
This matches the 2.7x Blender versions.

No performance loss (almost no gain too).

Reviewers: fclem

Subscribers: zlsa, rl.amorato

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

release/scripts/startup/bl_ui/space_view3d.py
source/blender/draw/intern/draw_common.h
source/blender/draw/modes/object_mode.c
source/blender/draw/modes/shaders/common_globals_lib.glsl
source/blender/draw/modes/shaders/object_grid_frag.glsl
source/blender/draw/modes/shaders/object_grid_vert.glsl
source/blender/editors/include/ED_view3d.h
source/blender/editors/space_view3d/view3d_draw.c

index 8bb211052dac0b71d91c9cc2cb8bfc2546e514ba..9b9623eaa603e0a1c5bf7f79f90ba9b448c87d90 100644 (file)
@@ -5354,6 +5354,8 @@ class VIEW3D_PT_overlay_guides(Panel):
         layout = self.layout
 
         view = context.space_data
+        scene = context.scene
+
         overlay = view.overlay
         shading = view.shading
         display_all = overlay.show_overlays
@@ -5381,6 +5383,8 @@ class VIEW3D_PT_overlay_guides(Panel):
                 (overlay.show_ortho_grid and grid_active)
             )
             sub.prop(overlay, "grid_scale", text="Scale")
+            sub = sub.row(align=True)
+            sub.active = scene.unit_settings.system == 'NONE'
             sub.prop(overlay, "grid_subdivisions", text="Subdivisions")
 
         sub = split.column()
index 05d7bafa00d2e42f03eea6c46dba4bf9289db2bb..52b94689679d284f3e6d3e6ee9c04b0c4066d19d 100644 (file)
@@ -113,7 +113,6 @@ typedef struct GlobalsUboStorage {
   /* Pack individual float at the end of the buffer to avoid alignment errors */
   float sizeLightCenter, sizeLightCircle, sizeLightCircleShadow;
   float sizeVertex, sizeEdge, sizeEdgeFix, sizeFaceDot;
-  float gridDistance, gridResolution, gridSubdivisions, gridScale;
 
   float pad_globalsBlock;
 } GlobalsUboStorage;
index 87fc74f1f7218f58309fd94846ed1f9cdeb5dd8d..06e5b52151470094e1e23b7f3c60ec32d99295e1 100644 (file)
@@ -332,7 +332,7 @@ static struct {
 
   OBJECT_Shaders sh_data[GPU_SHADER_CFG_LEN];
 
-  float grid_settings[5];
+  float grid_distance;
   float grid_mesh_size;
   int grid_flag;
   float grid_axes[3];
@@ -340,6 +340,7 @@ static struct {
   int zneg_flag;
   float zplane_axes[3];
   float inv_viewport_size[2];
+  float grid_steps[8];
   bool draw_grid;
   /* Temp buffer textures */
   struct GPUTexture *outlines_depth_tx;
@@ -559,8 +560,6 @@ static void OBJECT_engine_init(void *vedata)
     View3D *v3d = draw_ctx->v3d;
     Scene *scene = draw_ctx->scene;
     RegionView3D *rv3d = draw_ctx->rv3d;
-    float grid_scale = ED_view3d_grid_scale(scene, v3d, NULL);
-    float grid_res;
 
     const bool show_axis_x = (v3d->gridflag & V3D_SHOW_X) != 0;
     const bool show_axis_y = (v3d->gridflag & V3D_SHOW_Y) != 0;
@@ -576,21 +575,6 @@ static void OBJECT_engine_init(void *vedata)
 
     /* if perps */
     if (winmat[3][3] == 0.0f) {
-      float fov;
-      float viewvecs[2][4] = {
-          {1.0f, -1.0f, -1.0f, 1.0f},
-          {-1.0f, 1.0f, -1.0f, 1.0f},
-      };
-
-      /* convert the view vectors to view space */
-      for (int i = 0; i < 2; i++) {
-        mul_m4_v4(wininv, viewvecs[i]);
-        mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* perspective divide */
-      }
-
-      fov = angle_v3v3(viewvecs[0], viewvecs[1]) / 2.0f;
-      grid_res = fabsf(tanf(fov)) / grid_scale;
-
       e_data.grid_flag = (1 << 4); /* XY plane */
       if (show_axis_x) {
         e_data.grid_flag |= SHOW_AXIS_X;
@@ -603,14 +587,6 @@ static void OBJECT_engine_init(void *vedata)
       }
     }
     else {
-      if (rv3d->view != RV3D_VIEW_USER) {
-        /* Allow 3 more subdivisions. */
-        grid_scale /= powf(v3d->gridsubdiv, 3);
-      }
-
-      float viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
-      grid_res = viewdist / grid_scale;
-
       if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) {
         e_data.draw_grid = show_ortho_grid;
         e_data.grid_flag = PLANE_YZ | SHOW_AXIS_Y | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK;
@@ -688,12 +664,7 @@ static void OBJECT_engine_init(void *vedata)
       dist = v3d->clip_end;
     }
 
-    e_data.grid_settings[0] = dist / 2.0f;     /* gridDistance */
-    e_data.grid_settings[1] = grid_res;        /* gridResolution */
-    e_data.grid_settings[2] = grid_scale;      /* gridScale */
-    e_data.grid_settings[3] = v3d->gridsubdiv; /* gridSubdiv */
-    e_data.grid_settings[4] = (v3d->gridsubdiv > 1) ? 1.0f / logf(v3d->gridsubdiv) :
-                                                      0.0f; /* 1/log(gridSubdiv) */
+    e_data.grid_distance = dist / 2.0f; /* gridDistance */
 
     if (winmat[3][3] == 0.0f) {
       e_data.grid_mesh_size = dist;
@@ -702,6 +673,8 @@ static void OBJECT_engine_init(void *vedata)
       float viewdist = 1.0f / min_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
       e_data.grid_mesh_size = viewdist * dist;
     }
+
+    ED_view3d_grid_steps(scene, v3d, rv3d, e_data.grid_steps);
   }
 
   copy_v2_v2(e_data.inv_viewport_size, DRW_viewport_size_get());
@@ -1512,10 +1485,10 @@ static void OBJECT_cache_init(void *vedata)
     DRWShadingGroup *grp = DRW_shgroup_create(sh_data->grid, psl->grid);
     DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1);
     DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1);
-    DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 1);
+    DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2);
+    DRW_shgroup_uniform_float(grp, "gridDistance", &e_data.grid_distance, 1);
     DRW_shgroup_uniform_float_copy(grp, "lineKernel", grid_line_size);
     DRW_shgroup_uniform_float_copy(grp, "meshSize", e_data.grid_mesh_size);
-    DRW_shgroup_uniform_float(grp, "gridOneOverLogSubdiv", &e_data.grid_settings[4], 1);
     DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
     DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
     DRW_shgroup_call(grp, geom, NULL);
@@ -1525,6 +1498,7 @@ static void OBJECT_cache_init(void *vedata)
     DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.grid_axes, 1);
     DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
     DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+    DRW_shgroup_uniform_float(grp, "gridSteps", e_data.grid_steps, ARRAY_SIZE(e_data.grid_steps));
     DRW_shgroup_call(grp, geom, NULL);
 
     grp = DRW_shgroup_create(sh_data->grid, psl->grid);
index f75ef06b6d9cdf7c98f887a21d5d0558b7efae3f..e559224eb9e59b3adca9da11ecd2c84287b7a302 100644 (file)
@@ -75,11 +75,6 @@ layout(std140) uniform globalsBlock
   float sizeEdgeFix;
   float sizeFaceDot;
 
-  float gridDistance;
-  float gridResolution;
-  float gridSubdivisions;
-  float gridScale;
-
   float pad_globalsBlock;
 };
 
index a20f12efd932efcd338813644582a3b63e89035d..751d839eb79aae60f500ac81e17592df925701c4 100644 (file)
@@ -9,21 +9,19 @@ in vec3 local_pos;
 out vec4 FragColor;
 
 uniform vec3 planeAxes;
-uniform vec4 gridSettings;
+uniform vec3 screenVecs[2];
+uniform float gridDistance;
 uniform float meshSize;
 uniform float lineKernel = 0.0;
-uniform float gridOneOverLogSubdiv;
 uniform sampler2D depthBuffer;
 
-#define gridDistance gridSettings.x
-#define gridResolution gridSettings.y
-#define gridScale gridSettings.z
-#define gridSubdiv gridSettings.w
-
 #define cameraPos (ViewMatrixInverse[3].xyz)
 
 uniform int gridFlag;
 
+#define STEPS_LEN 8
+uniform float gridSteps[STEPS_LEN] = float[](0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0, 10000.0);
+
 #define AXIS_X (1 << 0)
 #define AXIS_Y (1 << 1)
 #define AXIS_Z (1 << 2)
@@ -73,10 +71,14 @@ vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size)
                           axes_domain - (line_size + lineKernel));
 }
 
+#define linearstep(p0, p1, v) (clamp(((v) - (p0)) / abs((p1) - (p0)), 0.0, 1.0))
+
 void main()
 {
   vec3 wPos = local_pos * meshSize;
-  vec3 fwidthPos = fwidth(wPos);
+  vec3 dFdxPos = dFdx(wPos);
+  vec3 dFdyPos = dFdy(wPos);
+  vec3 fwidthPos = abs(dFdxPos) + abs(dFdyPos);
   wPos += cameraPos * planeAxes;
 
   float dist, fade;
@@ -116,15 +118,54 @@ void main()
   }
 
   if ((gridFlag & GRID) != 0) {
-    float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv;
+    /* Using `max(dot(dFdxPos, screenVecs[0]), dot(dFdyPos, screenVecs[1]))`
+     * would be more accurate, but not really necessary. */
+    float grid_res = dot(dFdxPos, screenVecs[0]);
 
-    float blend = fract(-max(grid_res, 0.0));
-    float lvl = floor(grid_res);
+    /* The gride begins to appear when it comprises 4 pixels */
+    grid_res *= 4;
 
     /* from biggest to smallest */
-    float scaleA = gridScale * pow(gridSubdiv, max(lvl - 1.0, 0.0));
-    float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0));
-    float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0));
+    vec4 scale;
+#if 0
+    int step_id = 0;
+    scale[0] = 0.0;
+    scale[1] = gridSteps[0];
+    while (scale[1] < grid_res && step_id != STEPS_LEN - 1) {
+      scale[0] = scale[1];
+      scale[1] = gridSteps[++step_id];
+    }
+    scale[2] = gridSteps[min(step_id + 1, STEPS_LEN - 1)];
+    scale[3] = gridSteps[min(step_id + 2, STEPS_LEN - 1)];
+#else
+    /* For more efficiency, unroll the loop above. */
+    if (gridSteps[0] > grid_res) {
+      scale = vec4(0.0, gridSteps[0], gridSteps[1], gridSteps[2]);
+    }
+    else if (gridSteps[1] > grid_res) {
+      scale = vec4(gridSteps[0], gridSteps[1], gridSteps[2], gridSteps[3]);
+    }
+    else if (gridSteps[2] > grid_res) {
+      scale = vec4(gridSteps[1], gridSteps[2], gridSteps[3], gridSteps[4]);
+    }
+    else if (gridSteps[3] > grid_res) {
+      scale = vec4(gridSteps[2], gridSteps[3], gridSteps[4], gridSteps[5]);
+    }
+    else if (gridSteps[4] > grid_res) {
+      scale = vec4(gridSteps[3], gridSteps[4], gridSteps[5], gridSteps[6]);
+    }
+    else if (gridSteps[5] > grid_res) {
+      scale = vec4(gridSteps[4], gridSteps[5], gridSteps[6], gridSteps[7]);
+    }
+    else if (gridSteps[6] > grid_res) {
+      scale = vec4(gridSteps[5], gridSteps[6], gridSteps[7], gridSteps[7]);
+    }
+    else {
+      scale = vec4(gridSteps[6], gridSteps[7], gridSteps[7], gridSteps[7]);
+    }
+#endif
+    float blend = 1.0 - linearstep(scale[0], scale[1], grid_res);
+    blend = blend * blend * blend;
 
     vec2 grid_pos, grid_fwidth;
     if ((gridFlag & PLANE_XZ) != 0) {
@@ -140,9 +181,9 @@ void main()
       grid_fwidth = fwidthPos.xy;
     }
 
-    float gridA = get_grid(grid_pos, grid_fwidth, scaleA);
-    float gridB = get_grid(grid_pos, grid_fwidth, scaleB);
-    float gridC = get_grid(grid_pos, grid_fwidth, scaleC);
+    float gridA = get_grid(grid_pos, grid_fwidth, scale[1]);
+    float gridB = get_grid(grid_pos, grid_fwidth, scale[2]);
+    float gridC = get_grid(grid_pos, grid_fwidth, scale[3]);
 
     FragColor = colorGrid;
     FragColor.a *= gridA * blend;
index d247967b03aa21b4a19d16e8267a5340f6557d29..496bb011c74deb2826c535e5887b3b631cfa5629 100644 (file)
@@ -3,14 +3,8 @@
  * ClĂ©ment Foucault */
 
 uniform vec3 planeAxes;
-uniform vec4 gridSettings;
 uniform float meshSize;
 
-#define gridDistance gridSettings.x
-#define gridResolution gridSettings.y
-#define gridScale gridSettings.z
-#define gridSubdiv gridSettings.w
-
 uniform int gridFlag;
 
 #define cameraPos (ViewMatrixInverse[3].xyz)
index 67dfb184d197f617796785e22f1c0003bddfcf69..56661b992c47349a51abeed2a07d458bdf08a0a4 100644 (file)
@@ -690,6 +690,10 @@ bool ED_view3d_distance_set_from_location(struct RegionView3D *rv3d,
 
 float ED_scene_grid_scale(struct Scene *scene, const char **grid_unit);
 float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit);
+void ED_view3d_grid_steps(struct Scene *scene,
+                          struct View3D *v3d,
+                          struct RegionView3D *rv3d,
+                          float *r_grid_steps);
 float ED_view3d_grid_view_scale(struct Scene *scene,
                                 struct View3D *v3d,
                                 struct RegionView3D *rv3d,
index 6c534ee1b98a4932a0ad5b237b0893efb1b1f620..038d32c4d20b121863d48af4d855d3c41391fa46 100644 (file)
@@ -859,6 +859,51 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
   return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
 }
 
+#define STEPS_LEN 8
+void ED_view3d_grid_steps(Scene *scene,
+                          View3D *v3d,
+                          RegionView3D *rv3d,
+                          float r_grid_steps[STEPS_LEN])
+{
+  const void *usys;
+  int i, len;
+  bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
+  float grid_scale = v3d->grid;
+
+  if (usys) {
+    if (rv3d->view == RV3D_VIEW_USER) {
+      /* Skip steps */
+      len = bUnit_GetBaseUnit(usys) + 1;
+    }
+
+    grid_scale /= scene->unit.scale_length;
+
+    for (i = 0; i < len; i++) {
+      r_grid_steps[i] = (float)bUnit_GetScaler(usys, len - 1 - i) * grid_scale;
+    }
+    for (; i < STEPS_LEN; i++) {
+      /* Fill last slots */
+      r_grid_steps[i] = 10.0f * r_grid_steps[i - 1];
+    }
+  }
+  else {
+    if (rv3d->view != RV3D_VIEW_USER) {
+      /* Allow 3 more subdivisions. */
+      grid_scale /= powf(v3d->gridsubdiv, 3);
+    }
+    int subdiv = 1;
+    for (i = 0;; i++) {
+      r_grid_steps[i] = grid_scale * subdiv;
+
+      if (i == STEPS_LEN - 1) {
+        break;
+      }
+      subdiv *= v3d->gridsubdiv;
+    }
+  }
+}
+#undef STEPS_LEN
+
 /* Simulates the grid scale that is actually viewed.
  * The actual code is seen in `object_grid_frag.glsl` (see `grid_res`).
  * Currently the simulation is only done when RV3D_VIEW_IS_AXIS. */
@@ -867,24 +912,24 @@ float ED_view3d_grid_view_scale(Scene *scene,
                                 RegionView3D *rv3d,
                                 const char **grid_unit)
 {
-  float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
+  float grid_scale;
   if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
     /* Decrease the distance between grid snap points depending on zoom. */
-    float grid_subdiv = v3d->gridsubdiv;
-    if (grid_subdiv > 1) {
-      /* Allow 3 more subdivisions (see OBJECT_engine_init). */
-      grid_scale /= powf(grid_subdiv, 3);
-
-      /* `3.0` was a value obtained by trial and error in order to get
-       * a nice snap distance.*/
-      float grid_res = 3.0 * (rv3d->dist / v3d->lens);
-      float lvl = (logf(grid_res / grid_scale) / logf(grid_subdiv));
-
-      CLAMP_MIN(lvl, 0.0f);
-
-      grid_scale *= pow(grid_subdiv, (int)lvl);
+    /* `0.38` was a value visually obtained in order to get a snap distance
+     * that matches previous versions Blender.*/
+    float min_dist = 0.38f * (rv3d->dist / v3d->lens);
+    float grid_steps[8];
+    ED_view3d_grid_steps(scene, v3d, rv3d, grid_steps);
+    for (int i = 0; i < ARRAY_SIZE(grid_steps); i++) {
+      grid_scale = grid_steps[i];
+      if (grid_scale > min_dist) {
+        break;
+      }
     }
   }
+  else {
+    grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
+  }
 
   return grid_scale;
 }