Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/draw/intern/DRW_render.h1
-rw-r--r--source/blender/draw/intern/draw_manager.c3
-rw-r--r--source/blender/draw/modes/object_mode.c37
-rw-r--r--source/blender/draw/modes/shaders/object_grid_frag.glsl41
-rw-r--r--source/blender/draw/modes/shaders/object_grid_vert.glsl9
5 files changed, 76 insertions, 15 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 5c1c978806b..695027c5de6 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -307,6 +307,7 @@ typedef enum {
DRW_MAT_VIEW,
DRW_MAT_VIEWINV,
DRW_MAT_WIN,
+ DRW_MAT_WININV,
} DRWViewportMatrixType;
void DRW_viewport_init(const bContext *C);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index bbe3787dada..11c717a5373 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -2224,6 +2224,9 @@ void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type)
case DRW_MAT_WIN:
copy_m4_m4(mat, rv3d->winmat);
break;
+ case DRW_MAT_WININV:
+ invert_m4_m4(mat, rv3d->winmat);
+ break;
default:
BLI_assert(!"Matrix type invalid");
break;
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index f308021a3c8..735c1173353 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -208,6 +208,7 @@ static struct {
GPUShader *part_prim_sh;
GPUShader *part_axis_sh;
float camera_pos[3];
+ float screenvecs[3][4];
float grid_settings[5];
float grid_mat[4][4];
int grid_flag;
@@ -306,7 +307,8 @@ static void OBJECT_engine_init(void *vedata)
{
/* Grid precompute */
- float viewinvmat[4][4], winmat[4][4], invwinmat[4][4], viewmat[4][4];
+ float invviewmat[4][4], invwinmat[4][4];
+ float viewmat[4][4], winmat[4][4];
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
Scene *scene = draw_ctx->scene;
@@ -321,10 +323,11 @@ static void OBJECT_engine_init(void *vedata)
DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_get(viewinvmat, DRW_MAT_VIEWINV);
+ DRW_viewport_matrix_get(invwinmat, DRW_MAT_WININV);
+ DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV);
/* Setup camera pos */
- copy_v3_v3(e_data.camera_pos, viewinvmat[3]);
+ copy_v3_v3(e_data.camera_pos, invviewmat[3]);
/* if perps */
if (winmat[3][3] == 0.0f) {
@@ -333,13 +336,11 @@ static void OBJECT_engine_init(void *vedata)
{1.0f, -1.0f, -1.0f, 1.0f},
{-1.0f, 1.0f, -1.0f, 1.0f}
};
- /* invert the proj matrix */
- invert_m4_m4(invwinmat, winmat);
/* convert the view vectors to view space */
for (int i = 0; i < 2; i++) {
mul_m4_v4(invwinmat, viewvecs[i]);
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* normalize */
+ mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* perspective divide */
}
fov = angle_v3v3(viewvecs[0], viewvecs[1]) / 2.0f;
@@ -356,6 +357,7 @@ static void OBJECT_engine_init(void *vedata)
e_data.grid_flag |= SHOW_AXIS_Y;
if (show_floor)
e_data.grid_flag |= SHOW_GRID;
+
}
else {
float viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
@@ -393,12 +395,31 @@ static void OBJECT_engine_init(void *vedata)
}
}
+ /* Vectors to recover pixel world position. Fix grid precision issue. */
+ 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;
+ 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;
float zvec[4] = {0.0f, 0.0f, -1.0f, 0.0f};
- mul_m4_v4(viewinvmat, zvec);
+ mul_m4_v4(invviewmat, zvec);
/* z axis : chose the most facing plane */
if (fabsf(zvec[0]) < fabsf(zvec[1])) {
@@ -754,9 +775,11 @@ static void OBJECT_cache_init(void *vedata)
DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1);
DRW_shgroup_uniform_mat4(grp, "ViewProjectionOffsetMatrix", (float *)e_data.grid_mat);
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(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_call_add(grp, quad, mat);
grp = DRW_shgroup_create(e_data.grid_sh, psl->grid);
diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl
index 9b1283e46af..2db5100e1b3 100644
--- a/source/blender/draw/modes/shaders/object_grid_frag.glsl
+++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl
@@ -2,14 +2,14 @@
/* Infinite grid
* Clément Foucault */
-in vec3 wPos;
-
out vec4 FragColor;
uniform mat4 ProjectionMatrix;
uniform vec3 cameraPos;
uniform vec3 eye;
uniform vec4 gridSettings;
+uniform vec2 viewportSize;
+uniform vec4 screenvecs[3];
uniform float gridOneOverLogSubdiv;
#define gridDistance gridSettings.x
@@ -54,8 +54,45 @@ float axis(float u, float fwidthU, float line_size)
return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH, axis_domain - line_size);
}
+vec3 get_floor_pos(vec2 uv)
+{
+ /* if perspective */
+ vec3 camera_vec, camera_pos;
+ vec3 pixel_pos = screenvecs[2].xyz + uv.x * screenvecs[0].xyz + uv.y * screenvecs[1].xyz;
+
+ if (ProjectionMatrix[3][3] == 0.0) {
+ camera_vec = normalize(pixel_pos - cameraPos);
+ camera_pos = cameraPos;
+ }
+ else {
+ camera_vec = normalize(eye);
+ camera_pos = pixel_pos;
+ }
+
+ vec3 plane_normal;
+ if ((gridFlag & PLANE_XZ) > 0) {
+ plane_normal = vec3(0.0, 1.0, 0.0);
+ }
+ else if ((gridFlag & PLANE_YZ) > 0) {
+ plane_normal = vec3(1.0, 0.0, 0.0);
+ }
+ else {
+ plane_normal = vec3(0.0, 0.0, 1.0);
+ }
+
+ float p = -dot(plane_normal, camera_pos) / dot(plane_normal, camera_vec);
+ vec3 plane = camera_pos + camera_vec * p;
+
+ /* fix residual imprecision */
+ vec3 mask = vec3(1.0) - plane_normal;
+ return plane * mask;
+}
+
void main()
{
+ vec2 sPos = gl_FragCoord.xy / viewportSize; /* Screen [0,1] position */
+ vec3 wPos = get_floor_pos(sPos);
+
vec3 fwidthCos = fwidth(wPos);
float dist, fade;
diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl
index 2da8e45c560..2ecbfa8e11f 100644
--- a/source/blender/draw/modes/shaders/object_grid_vert.glsl
+++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl
@@ -22,8 +22,6 @@ uniform int gridFlag;
in vec3 pos;
-out vec3 wPos;
-
void main()
{
vec3 vert_pos, proj_camera_pos;
@@ -47,20 +45,19 @@ void main()
vert_pos *= gridDistance * 2.0;
}
else {
- float viewdist = 1.0f / min(abs(ProjectionMatrix[0][0]), abs(ProjectionMatrix[1][1]));
+ float viewdist = 1.0 / min(abs(ProjectionMatrix[0][0]), abs(ProjectionMatrix[1][1]));
vert_pos *= viewdist * gridDistance * 2.0;
}
- vec3 realPos = proj_camera_pos + vert_pos;
+ vec3 realPos = proj_camera_pos + vert_pos;
/* Used for additional Z axis */
if ((gridFlag & CLIP_Z_POS) > 0) {
realPos.z = max(realPos.z, 0.0);
}
if ((gridFlag & CLIP_Z_NEG) > 0) {
- realPos.z = min(realPos.z, 0.0);
+ realPos.z = min(-realPos.z, 0.0);
}
gl_Position = ViewProjectionOffsetMatrix * vec4(realPos, 1.0);
- wPos = realPos;
}