View3D Grid: fix imperial grid drawing

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
This commit is contained in:
Germano Cavalcante 2019-08-19 11:49:07 -03:00
parent 3cbf246239
commit 4bf37bafc2
Notes: blender-bot 2023-04-27 15:07:22 +02:00
Referenced by issue #75769, grid subdivisions has stopped working, so grid snapping is no longer effective.
Referenced by issue #70764, Grid subdivisions not working.
Referenced by issue #107274, Crash when trying to frame a big object in ortho view (global-buffer-overflow with imperial Unit System)
8 changed files with 133 additions and 77 deletions

View 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()

View 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;

View 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);

View File

@ -75,11 +75,6 @@ layout(std140) uniform globalsBlock
float sizeEdgeFix;
float sizeFaceDot;
float gridDistance;
float gridResolution;
float gridSubdivisions;
float gridScale;
float pad_globalsBlock;
};

View 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;

View 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)

View 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,

View 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;
}