diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-03-25 04:46:23 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-03-25 21:11:01 +0300 |
commit | 0495e689e60c313e039b09468307dcbab2a7ae1c (patch) | |
tree | 6fbac1eb94633bd3e76aca6c4bb78845161f362c /source | |
parent | d2c94c78736e84c1318859c8e902b3ee622fd6f0 (diff) |
New Grid : Feature parity with old grid.
Removed infinite details and went for decreasing details with the distance instead (like the axis aligned ortho view auto sized grid).
Separate drawing of the Z axis into 2 pass (using shading group) to render ordered transparency with the main grid pass.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/modes/object_mode.c | 154 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/object_grid_frag.glsl | 103 | ||||
-rw-r--r-- | source/blender/draw/modes/shaders/object_grid_vert.glsl | 52 |
3 files changed, 264 insertions, 45 deletions
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index bf431a61728..b7bb489ca2b 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -36,6 +36,7 @@ #include "BKE_global.h" #include "ED_view3d.h" +#include "ED_view3d.h" #include "GPU_shader.h" @@ -164,8 +165,24 @@ static struct { float camera_pos[3]; float grid_settings[4]; float grid_mat[4][4]; + int grid_flag; + int zpos_flag; + int zneg_flag; } e_data = {NULL}; /* Engine data */ + +enum { + SHOW_AXIS_X = (1 << 0), + SHOW_AXIS_Y = (1 << 1), + SHOW_AXIS_Z = (1 << 2), + SHOW_GRID = (1 << 3), + PLANE_XY = (1 << 4), + PLANE_XZ = (1 << 5), + PLANE_YZ = (1 << 6), + CLIP_ZPOS = (1 << 7), + CLIP_ZNEG = (1 << 8), +}; + /* *********** FUNCTIONS *********** */ static void OBJECT_engine_init(void) @@ -206,7 +223,20 @@ static void OBJECT_engine_init(void) } { - float viewinvmat[4][4], winmat[4][4], viewmat[4][4]; + /* Grid precompute */ + float viewinvmat[4][4], winmat[4][4], invwinmat[4][4], viewmat[4][4]; + const bContext *C = DRW_get_context(); + View3D *v3d = CTX_wm_view3d(C); + Scene *scene = CTX_data_scene(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + float grid_scale = ED_view3d_grid_scale(scene, v3d, NULL); + float grid_res, offs; + + const bool show_axis_x = v3d->gridflag & V3D_SHOW_X; + const bool show_axis_y = v3d->gridflag & V3D_SHOW_Y; + const bool show_axis_z = v3d->gridflag & V3D_SHOW_Z; + const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR); + DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); DRW_viewport_matrix_get(viewinvmat, DRW_MAT_VIEWINV); @@ -214,29 +244,113 @@ static void OBJECT_engine_init(void) /* Setup camera pos */ copy_v3_v3(e_data.camera_pos, viewinvmat[3]); - /* grid settings */ - const bContext *C = DRW_get_context(); - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); + /* 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} + }; + /* 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 */ + } - e_data.grid_settings[0] = 100.0f; /* gridDistance */ - e_data.grid_settings[1] = 2.0f; /* gridResolution */ - e_data.grid_settings[2] = ED_view3d_grid_scale(scene, v3d, NULL); /* gridScale */ - e_data.grid_settings[3] = v3d->gridsubdiv; /* gridSubdiv */ + fov = angle_v3v3(viewvecs[0], viewvecs[1]) / 2.0f; + grid_res = fabsf(tanf(fov)) / grid_scale; + + /* Grid matrix polygon offset (fix depth fighting) */ + /* see ED_view3d_polygon_offset */ + offs = winmat[3][2] * -0.0025f; - /* Grid matrix polygon offset (fix depth fighting) */ - /* see ED_view3d_polygon_offset */ - float offs; - if (winmat[3][3] > 0.5f) { + e_data.grid_flag = (1 << 4); /* XY plane */ + if (show_axis_x) + e_data.grid_flag |= SHOW_AXIS_X; + if (show_axis_y) + 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])); + grid_res = viewdist / grid_scale; + + /* Grid matrix polygon offset (fix depth fighting) */ + /* see ED_view3d_polygon_offset */ offs = 0.00001f * viewdist; + if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) { + e_data.grid_flag = PLANE_YZ; + e_data.grid_flag |= SHOW_AXIS_Y; + e_data.grid_flag |= SHOW_AXIS_Z; + e_data.grid_flag |= SHOW_GRID; + } + else if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) { + e_data.grid_flag = PLANE_XY; + e_data.grid_flag |= SHOW_AXIS_X; + e_data.grid_flag |= SHOW_AXIS_Y; + e_data.grid_flag |= SHOW_GRID; + } + else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) { + e_data.grid_flag = PLANE_XZ; + e_data.grid_flag |= SHOW_AXIS_X; + e_data.grid_flag |= SHOW_AXIS_Z; + e_data.grid_flag |= SHOW_GRID; + } + else { /* RV3D_VIEW_USER */ + e_data.grid_flag = PLANE_XY; + if (show_axis_x) + e_data.grid_flag |= SHOW_AXIS_X; + if (show_axis_y) + e_data.grid_flag |= SHOW_AXIS_Y; + if (show_floor) + e_data.grid_flag |= SHOW_GRID; + } + } + + /* Z axis if needed */ + if ((rv3d->view == RV3D_VIEW_USER) && 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); + + /* z axis : chose the most facing plane */ + if (fabsf(zvec[0]) > fabsf(zvec[1])) { + e_data.zpos_flag |= (PLANE_XZ | SHOW_AXIS_X); + } + else { + e_data.zpos_flag |= (PLANE_YZ | SHOW_AXIS_Y); + } + + e_data.zneg_flag = e_data.zpos_flag; + + /* Persp : If camera is below floor plane, we switch clipping + * Ortho : If eye vector is looking up, we switch clipping */ + if (((winmat[3][3] == 0.0f) && (e_data.camera_pos[2] > 0.0f)) || + ((winmat[3][3] != 0.0f) && (zvec[2] < 0.0f))) { + e_data.zpos_flag |= CLIP_ZPOS; + e_data.zneg_flag |= CLIP_ZNEG; + } + else { + e_data.zpos_flag |= CLIP_ZNEG; + e_data.zneg_flag |= CLIP_ZPOS; + } } else { - offs = winmat[3][2] * -0.0025f; + e_data.zneg_flag = e_data.zpos_flag = 0; } - winmat[3][2] -= offs; + winmat[3][2] -= offs; mul_m4_m4m4(e_data.grid_mat, winmat, viewmat); + + e_data.grid_settings[0] = v3d->far / 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 */ } } @@ -382,12 +496,22 @@ static void OBJECT_cache_init(void) struct Batch *quad = DRW_cache_fullscreen_quad_get(); + /* 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_mat4(grp, "ViewProjectionOffsetMatrix", (float *)e_data.grid_mat); DRW_shgroup_uniform_vec3(grp, "cameraPos", e_data.camera_pos, 1); DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 1); DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo, 0); DRW_shgroup_call_add(grp, quad, NULL); + + grp = DRW_shgroup_create(e_data.grid_sh, psl->grid); + DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.grid_flag, 1); + DRW_shgroup_call_add(grp, quad, NULL); + + grp = DRW_shgroup_create(e_data.grid_sh, psl->grid); + DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zpos_flag, 1); + DRW_shgroup_call_add(grp, quad, NULL); } { diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl index 0f7be9fea3e..8b890ea8692 100644 --- a/source/blender/draw/modes/shaders/object_grid_frag.glsl +++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl @@ -15,19 +15,29 @@ uniform vec4 gridSettings; #define gridScale gridSettings.z #define gridSubdiv gridSettings.w +uniform int gridFlag; + +#define AXIS_X (1 << 0) +#define AXIS_Y (1 << 1) +#define AXIS_Z (1 << 2) +#define GRID (1 << 3) +#define PLANE_XY (1 << 4) +#define PLANE_XZ (1 << 5) +#define PLANE_YZ (1 << 6) + #define GRID_LINE_SMOOTH 1.15 -float grid(vec2 uv, vec2 fwidthUvs, float grid_size) +float grid(vec3 uv, vec3 fwidthCos, float grid_size) { float half_size = grid_size / 2.0; /* triangular wave pattern, amplitude is [0, grid_size] */ - vec2 grid_domain = abs(mod(uv + half_size, grid_size) - half_size); + vec3 grid_domain = abs(mod(uv + half_size, grid_size) - half_size); /* modulate by the absolute rate of change of the uvs * (make lines have the same width under perspective) */ - grid_domain /= fwidthUvs; + grid_domain /= fwidthCos; /* collapse waves and normalize */ - grid_domain.x = min(grid_domain.x, grid_domain.y) / grid_size; + grid_domain.x = min(grid_domain.x, min(grid_domain.y, grid_domain.z)) / grid_size; return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH / grid_size, grid_domain.x); } @@ -44,43 +54,78 @@ float axis(float u, float fwidthU, float line_size) void main() { - vec2 fwidthUvs = fwidth(wPos.xy); - - float blend, lvl, fade; + vec3 fwidthCos = fwidth(wPos); + float fade, grid_res; /* if persp */ if (ProjectionMatrix[3][3] == 0.0) { float dist = distance(cameraPos, wPos); - float log2dist = -log2(dist / (2.0 * gridDistance)); - - blend = fract(log2dist / gridResolution); - lvl = floor(log2dist / gridResolution); + float dist_norm = dist / (2.0 * gridDistance); + grid_res = log(dist * gridResolution) / log(gridSubdiv); fade = 1.0 - smoothstep(0.0, gridDistance, dist - gridDistance); } else { - /* todo find a better way */ - blend = 0.0; - lvl = 0.0; - fade = 1.0; + float dist = abs(gl_FragCoord.z * 2.0 - 1.0); + grid_res = log(gridResolution) / log(gridSubdiv); + fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5); } - /* from smallest to biggest */ - float scaleA = gridScale * pow(gridSubdiv, min(-lvl + 1.0, 1.0)); - float scaleB = gridScale * pow(gridSubdiv, min(-lvl + 2.0, 1.0)); - float scaleC = gridScale * pow(gridSubdiv, min(-lvl + 3.0, 1.0)); + /* fix division by 0 (log(1) = 0) */ + if (gridSubdiv == 1.0) { + grid_res = 0.0; + } + + if ((gridFlag & GRID) > 0) { + float blend = fract(-max(grid_res, 0.0)); + float lvl = floor(grid_res); - float gridA = grid(wPos.xy, fwidthUvs, scaleA); - float gridB = grid(wPos.xy, fwidthUvs, scaleB); - float gridC = grid(wPos.xy, fwidthUvs, scaleC); + /* from smallest to biggest */ + 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)); - float xAxis = axis(wPos.y, fwidthUvs.y, 0.1); /* Swapped */ - float yAxis = axis(wPos.x, fwidthUvs.x, 0.1); /* Swapped */ + float gridA = grid(wPos, fwidthCos, scaleA); + float gridB = grid(wPos, fwidthCos, scaleB); + float gridC = grid(wPos, fwidthCos, scaleC); - FragColor = vec4(colorGrid.rgb, gridA * blend); - FragColor = mix(FragColor, vec4(mix(colorGrid.rgb, colorGridEmphasise.rgb, blend), 1.0), gridB); - FragColor = mix(FragColor, vec4(colorGridEmphasise.rgb, 1.0), gridC); + FragColor = vec4(colorGrid.rgb, gridA * blend); + FragColor = mix(FragColor, vec4(mix(colorGrid.rgb, colorGridEmphasise.rgb, blend), 1.0), gridB); + FragColor = mix(FragColor, vec4(colorGridEmphasise.rgb, 1.0), gridC); + } + else { + FragColor = vec4(colorGrid.rgb, 0.0); + } + + if ((gridFlag & AXIS_X) > 0) { + float xAxis; + if ((gridFlag & AXIS_Y) > 0) { + xAxis = axis(wPos.y, fwidthCos.y, 0.1); + } + else { + xAxis = axis(wPos.z, fwidthCos.z, 0.1); + } + FragColor = mix(FragColor, colorGridAxisX, xAxis); + } + if ((gridFlag & AXIS_Y) > 0) { + float yAxis; + if ((gridFlag & AXIS_X) > 0) { + yAxis = axis(wPos.x, fwidthCos.x, 0.1); + } + else { + yAxis = axis(wPos.z, fwidthCos.z, 0.1); + } + FragColor = mix(FragColor, colorGridAxisY, yAxis); + } + if ((gridFlag & AXIS_Z) > 0) { + float zAxis; + if ((gridFlag & AXIS_Y) > 0) { + zAxis = axis(wPos.y, fwidthCos.y, 0.1); + } + else { + zAxis = axis(wPos.x, fwidthCos.x, 0.1); + } + FragColor = mix(FragColor, colorGridAxisZ, zAxis); + } - FragColor = mix(FragColor, colorGridAxisX, xAxis); - FragColor = mix(FragColor, colorGridAxisY, yAxis); FragColor.a *= fade; }
\ No newline at end of file diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl index 3c6f0a3bd25..5127bd81474 100644 --- a/source/blender/draw/modes/shaders/object_grid_vert.glsl +++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl @@ -3,6 +3,22 @@ * Clément Foucault */ uniform mat4 ViewProjectionOffsetMatrix; +uniform mat4 ProjectionMatrix; +uniform vec3 cameraPos; +uniform vec4 gridSettings; + +#define gridDistance gridSettings.x +#define gridResolution gridSettings.y +#define gridScale gridSettings.z +#define gridSubdiv gridSettings.w + +uniform int gridFlag; + +#define PLANE_XY (1 << 4) +#define PLANE_XZ (1 << 5) +#define PLANE_YZ (1 << 6) +#define CLIP_Z_POS (1 << 7) +#define CLIP_Z_NEG (1 << 8) in vec3 pos; @@ -10,7 +26,41 @@ out vec3 wPos; void main() { - vec3 realPos = pos * 1e3; + vec3 vert_pos, proj_camera_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.0f / min(abs(ProjectionMatrix[0][0]), abs(ProjectionMatrix[1][1])); + vert_pos *= viewdist * gridDistance * 2.0; + } + + 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); + } + else if ((gridFlag & CLIP_Z_NEG) > 0) { + realPos.z = min(realPos.z, 0.0); + } + gl_Position = ViewProjectionOffsetMatrix * vec4(realPos, 1.0); wPos = realPos; } |