diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index aef4823b2ee..38bf2aeaf16 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -326,14 +326,12 @@ static struct { GPUShader *lightprobe_grid_sh; GPUShader *loose_points_sh; float camera_pos[3]; - float screenvecs[3][4]; float grid_settings[5]; + float grid_mesh_size; int grid_flag; - float grid_normal[3]; float grid_axes[3]; int zpos_flag; int zneg_flag; - float zplane_normal[3]; float zplane_axes[3]; float inv_viewport_size[2]; bool draw_grid; @@ -565,38 +563,10 @@ static void OBJECT_engine_init(void *vedata) } } - e_data.grid_normal[0] = (float)((e_data.grid_flag & PLANE_YZ) != 0); - e_data.grid_normal[1] = (float)((e_data.grid_flag & PLANE_XZ) != 0); - e_data.grid_normal[2] = (float)((e_data.grid_flag & PLANE_XY) != 0); - e_data.grid_axes[0] = (float)((e_data.grid_flag & (PLANE_XZ | PLANE_XY)) != 0); e_data.grid_axes[1] = (float)((e_data.grid_flag & (PLANE_YZ | PLANE_XY)) != 0); e_data.grid_axes[2] = (float)((e_data.grid_flag & (PLANE_YZ | PLANE_XZ)) != 0); - /* Vectors to recover pixel world position. Fix grid precision issue. */ - /* Using pixel at z = 0.0f in ndc space : gives average precision between - * near and far plane. Note that it might not be the best choice. */ - copy_v4_fl4(e_data.screenvecs[0], 1.0f, -1.0f, 0.0f, 1.0f); - copy_v4_fl4(e_data.screenvecs[1], -1.0f, 1.0f, 0.0f, 1.0f); - copy_v4_fl4(e_data.screenvecs[2], -1.0f, -1.0f, 0.0f, 1.0f); - - for (int i = 0; i < 3; i++) { - /* Doing 2 steps to recover world position of the corners of the frustum. - * Using the inverse perspective matrix is giving very low precision output. */ - mul_m4_v4(invwinmat, e_data.screenvecs[i]); - e_data.screenvecs[i][0] /= e_data.screenvecs[i][3]; /* perspective divide */ - e_data.screenvecs[i][1] /= e_data.screenvecs[i][3]; /* perspective divide */ - e_data.screenvecs[i][2] /= e_data.screenvecs[i][3]; /* perspective divide */ - e_data.screenvecs[i][3] = 1.0f; - /* main instability come from this one */ - /* TODO : to make things even more stable, don't use - * invviewmat and derive vectors from camera properties */ - mul_m4_v4(invviewmat, e_data.screenvecs[i]); - } - - sub_v3_v3(e_data.screenvecs[0], e_data.screenvecs[2]); - sub_v3_v3(e_data.screenvecs[1], e_data.screenvecs[2]); - /* Z axis if needed */ if (((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) && show_axis_z) { e_data.zpos_flag = SHOW_AXIS_Z; @@ -627,10 +597,6 @@ static void OBJECT_engine_init(void *vedata) e_data.zneg_flag |= CLIP_ZPOS; } - e_data.zplane_normal[0] = (float)((e_data.zpos_flag & PLANE_YZ) != 0); - e_data.zplane_normal[1] = (float)((e_data.zpos_flag & PLANE_XZ) != 0); - e_data.zplane_normal[2] = (float)((e_data.zpos_flag & PLANE_XY) != 0); - e_data.zplane_axes[0] = (float)((e_data.zpos_flag & (PLANE_XZ | PLANE_XY)) != 0); e_data.zplane_axes[1] = (float)((e_data.zpos_flag & (PLANE_YZ | PLANE_XY)) != 0); e_data.zplane_axes[2] = (float)((e_data.zpos_flag & (PLANE_YZ | PLANE_XZ)) != 0); @@ -654,6 +620,14 @@ static void OBJECT_engine_init(void *vedata) 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) */ + + if (winmat[3][3] == 0.0f) { + e_data.grid_mesh_size = dist; + } + else { + float viewdist = 1.0f / min_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1])); + e_data.grid_mesh_size = viewdist * dist; + } } copy_v2_v2(e_data.inv_viewport_size, DRW_viewport_size_get()); @@ -1109,21 +1083,18 @@ static void OBJECT_cache_init(void *vedata) /* Create 3 quads to render ordered transparency Z axis */ DRWShadingGroup *grp = DRW_shgroup_create(e_data.grid_sh, psl->grid); DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1); - DRW_shgroup_uniform_vec3(grp, "planeNormal", e_data.zplane_normal, 1); DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1); DRW_shgroup_uniform_vec3(grp, "cameraPos", e_data.camera_pos, 1); - DRW_shgroup_uniform_vec4(grp, "screenvecs[0]", e_data.screenvecs[0], 3); DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 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", globals_ubo); - DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_call_add(grp, geom, mat); grp = DRW_shgroup_create(e_data.grid_sh, psl->grid); DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.grid_flag, 1); - DRW_shgroup_uniform_vec3(grp, "planeNormal", e_data.grid_normal, 1); DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.grid_axes, 1); DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); @@ -1131,7 +1102,6 @@ static void OBJECT_cache_init(void *vedata) grp = DRW_shgroup_create(e_data.grid_sh, psl->grid); DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zpos_flag, 1); - DRW_shgroup_uniform_vec3(grp, "planeNormal", e_data.zplane_normal, 1); DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1); DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl index 35a95e809df..5a2913fc2e2 100644 --- a/source/blender/draw/modes/shaders/object_grid_frag.glsl +++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl @@ -2,16 +2,18 @@ /* Infinite grid * Author: Clément Foucault */ +/* We use the normalized local position to avoid precision + * loss during interpolation. */ +in vec3 local_pos; + out vec4 FragColor; uniform mat4 ProjectionMatrix; uniform vec3 cameraPos; -uniform vec3 planeNormal; uniform vec3 planeAxes; uniform vec3 eye; uniform vec4 gridSettings; -uniform vec2 viewportSize; -uniform vec4 screenvecs[3]; +uniform float meshSize; uniform float lineKernel = 0.0; uniform float gridOneOverLogSubdiv; uniform sampler2D depthBuffer; @@ -70,52 +72,11 @@ vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size) return 1.0 - smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, axes_domain - (line_size + lineKernel)); } -vec3 get_floor_pos(vec2 uv, out vec3 wPos) -{ - vec3 camera_vec, camera_pos, corner_pos; - vec3 floored_pos = planeAxes * floor(screenvecs[2].xyz); - corner_pos = screenvecs[2].xyz - floored_pos; - - vec3 pixel_pos = corner_pos + uv.x * screenvecs[0].xyz + uv.y * screenvecs[1].xyz; - - /* if perspective */ - if (ProjectionMatrix[3][3] == 0.0) { - camera_pos = cameraPos - floored_pos; - camera_vec = normalize(pixel_pos - camera_pos); - } - else { - camera_pos = pixel_pos; - camera_vec = normalize(eye); - } - - float plane_normal_dot_camera_vec = dot(planeNormal, camera_vec); - float p = -dot(planeNormal, camera_pos); - if (plane_normal_dot_camera_vec != 0) { - p /= plane_normal_dot_camera_vec; - } - vec3 plane = camera_pos + camera_vec * p; - - /* fix residual imprecision */ - plane *= planeAxes; - - /* Recover non-offseted world position */ - wPos = plane + floored_pos; - - return plane; -} - void main() { - vec2 sPos = gl_FragCoord.xy / viewportSize; /* Screen [0,1] position */ - - /* To reduce artifacts, use a local version of the positions - * to compute derivatives since they are not position dependent. - * This gets rid of the blocky artifacts. Unfortunately we still - * need the world position for the grid to scale properly from the origin. */ - vec3 gPos, wPos; /* Grid pos., World pos. */ - gPos = get_floor_pos(sPos, wPos); - - vec3 fwidthPos = fwidth(gPos); + vec3 wPos = local_pos * meshSize; + vec3 fwidthPos = fwidth(wPos); + wPos += cameraPos * planeAxes; float dist, fade; /* if persp */ @@ -228,7 +189,7 @@ void main() /* Add a small bias so the grid will always * be on top of a mesh with the same depth. */ float grid_depth = gl_FragCoord.z - 6e-8 - fwidth(gl_FragCoord.z); - float scene_depth = texture(depthBuffer, sPos).r; + float scene_depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r; if ((gridFlag & GRID_BACK) != 0) { fade *= (scene_depth == 1.0) ? 1.0 : 0.0; } diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl index 15b37bb289d..1cf6c49b733 100644 --- a/source/blender/draw/modes/shaders/object_grid_vert.glsl +++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl @@ -5,7 +5,9 @@ uniform mat4 ViewProjectionMatrix; uniform mat4 ProjectionMatrix; uniform vec3 cameraPos; +uniform vec3 planeAxes; uniform vec4 gridSettings; +uniform float meshSize; #define gridDistance gridSettings.x #define gridResolution gridSettings.y @@ -22,42 +24,36 @@ uniform int gridFlag; in vec3 pos; +out vec3 local_pos; + void main() { - vec3 vert_pos, proj_camera_pos; + vec3 vert_pos; /* Project camera pos to the needed plane */ if ((gridFlag & PLANE_XY) != 0) { vert_pos = vec3(pos.x, pos.y, 0.0); - proj_camera_pos = vec3(cameraPos.x, cameraPos.y, 0.0); } else if ((gridFlag & PLANE_XZ) != 0) { vert_pos = vec3(pos.x, 0.0, pos.y); - proj_camera_pos = vec3(cameraPos.x, 0.0, cameraPos.z); } else { vert_pos = vec3(0.0, pos.x, pos.y); - proj_camera_pos = vec3(0.0, cameraPos.y, cameraPos.z); } - /* if persp */ - if (ProjectionMatrix[3][3] == 0.0) { - vert_pos *= gridDistance * 2.0; - } - else { - float viewdist = 1.0 / min(abs(ProjectionMatrix[0][0]), abs(ProjectionMatrix[1][1])); - vert_pos *= viewdist * gridDistance * 2.0; - } + local_pos = vert_pos; - vec3 realPos = proj_camera_pos + vert_pos; + vec3 real_pos = cameraPos * planeAxes + vert_pos * meshSize; /* Used for additional Z axis */ if ((gridFlag & CLIP_Z_POS) != 0) { - realPos.z = clamp(realPos.z, 0.0, 1e30); + real_pos.z = clamp(real_pos.z, 0.0, 1e30); + local_pos.z = clamp(local_pos.z, 0.0, 1.0); } if ((gridFlag & CLIP_Z_NEG) != 0) { - realPos.z = clamp(realPos.z, -1e30, 0.0); + real_pos.z = clamp(real_pos.z, -1e30, 0.0); + local_pos.z = clamp(local_pos.z, -1.0, 0.0); } - gl_Position = ViewProjectionMatrix * vec4(realPos, 1.0); + gl_Position = ViewProjectionMatrix * vec4(real_pos, 1.0); }