From 8abc315a23750cd26c0de36d0e85dde71c93ed78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 22 Mar 2017 21:28:59 +0100 Subject: [PATCH] Object Mode Engine: New grid drawing. Move the grid drawing to the Object mode engine and implement a new infinite grid. Everything is done but it needs better parameters to be intuitive. --- source/blender/draw/CMakeLists.txt | 2 + source/blender/draw/intern/DRW_render.h | 3 +- source/blender/draw/intern/draw_common.c | 13 +++ source/blender/draw/intern/draw_common.h | 9 ++ source/blender/draw/intern/draw_manager.c | 6 +- source/blender/draw/modes/object_mode.c | 56 +++++++++++- .../draw/modes/shaders/object_grid_frag.glsl | 87 +++++++++++++++++++ .../draw/modes/shaders/object_grid_vert.glsl | 19 ++++ 8 files changed, 189 insertions(+), 6 deletions(-) create mode 100644 source/blender/draw/modes/shaders/object_grid_frag.glsl create mode 100644 source/blender/draw/modes/shaders/object_grid_vert.glsl diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 0f635a3578a..1c44064b38e 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -119,6 +119,8 @@ data_to_c_simple(modes/shaders/edit_normals_geom.glsl SRC) data_to_c_simple(modes/shaders/object_outline_resolve_frag.glsl SRC) data_to_c_simple(modes/shaders/object_outline_expand_frag.glsl SRC) data_to_c_simple(modes/shaders/object_outline_detect_frag.glsl SRC) +data_to_c_simple(modes/shaders/object_grid_frag.glsl SRC) +data_to_c_simple(modes/shaders/object_grid_vert.glsl SRC) list(APPEND INC ) diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index a9987dc251c..3aabb92be79 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -230,7 +230,8 @@ DRWPass *DRW_pass_create(const char *name, DRWState state); /* Viewport */ typedef enum { DRW_MAT_PERS, - DRW_MAT_WIEW, + DRW_MAT_VIEW, + DRW_MAT_VIEWINV, DRW_MAT_WIN, } DRWViewportMatrixType; diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index d56c1569c45..bbdbf39256b 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -65,6 +65,19 @@ void DRW_globals_update(void) UI_GetThemeColor4fv(TH_VNORMAL, ts.colorVNormal); UI_GetThemeColor4fv(TH_LNORMAL, ts.colorLNormal); UI_GetThemeColor4fv(TH_FACE_DOT, ts.colorFaceDot); + UI_GetThemeColor4fv(TH_BACK, ts.colorBackground); + + /* Grid */ + UI_GetThemeColorShade4fv(TH_GRID, 10, ts.colorGrid); + /* emphasise division lines lighter instead of darker, if background is darker than grid */ + UI_GetThemeColorShade4fv(TH_GRID, + (ts.colorGrid[0] + ts.colorGrid[1] + ts.colorGrid[2] + 0.12 > + ts.colorBackground[0] + ts.colorBackground[1] + ts.colorBackground[2]) + ? 20 : -10, ts.colorGridEmphasise); + /* Grid Axis */ + UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_X, 0.5f, -10, ts.colorGridAxisX); + UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_Y, 0.5f, -10, ts.colorGridAxisY); + UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_Z, 0.5f, -10, ts.colorGridAxisZ); UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, ts.colorDeselect); UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, ts.colorOutline); diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 09d176c2b80..e8e7cf40432 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -68,9 +68,18 @@ typedef struct GlobalsUboStorage { float colorOutline[4]; float colorLampNoAlpha[4]; + float colorBackground[4]; + + float colorGrid[4]; + float colorGridEmphasise[4]; + float colorGridAxisX[4]; + float colorGridAxisY[4]; + float colorGridAxisZ[4]; + /* Pack individual float at the end of the buffer to avoid alignement errors */ float sizeLampCenter, sizeLampCircle, sizeLampCircleShadow; float sizeVertex, sizeEdge, sizeEdgeFix, sizeFaceDot; + float gridDistance, gridResolution, gridSubdivisions, gridScale; } GlobalsUboStorage; /* Keep in sync with globalsBlock in shaders */ diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index fa9090eddcc..2146e53df65 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1330,8 +1330,10 @@ void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type) if (type == DRW_MAT_PERS) copy_m4_m4(mat, rv3d->persmat); - else if (type == DRW_MAT_WIEW) + else if (type == DRW_MAT_VIEW) copy_m4_m4(mat, rv3d->viewmat); + else if (type == DRW_MAT_VIEWINV) + copy_m4_m4(mat, rv3d->viewinv); else if (type == DRW_MAT_WIN) copy_m4_m4(mat, rv3d->winmat); } @@ -1546,7 +1548,7 @@ void DRW_draw_view(const bContext *C) DRW_engines_draw_background(); DRW_draw_callbacks_pre_scene(); - DRW_draw_grid(); + // DRW_draw_grid(); DRW_engines_draw_scene(); DRW_draw_callbacks_post_scene(); diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index 1ef3737aab1..40fabe04049 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -35,6 +35,8 @@ #include "BKE_camera.h" #include "BKE_global.h" +#include "ED_view3d.h" + #include "GPU_shader.h" #include "UI_resources.h" @@ -42,11 +44,15 @@ #include "draw_mode_engines.h" #include "draw_common.h" +extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */ extern GlobalsUboStorage ts; extern char datatoc_object_outline_resolve_frag_glsl[]; extern char datatoc_object_outline_detect_frag_glsl[]; extern char datatoc_object_outline_expand_frag_glsl[]; +extern char datatoc_object_grid_frag_glsl[]; +extern char datatoc_object_grid_vert_glsl[]; +extern char datatoc_common_globals_lib_glsl[]; /* *********** LISTS *********** */ /* keep it under MAX_PASSES */ @@ -62,6 +68,7 @@ typedef struct OBJECT_PassList { struct DRWPass *outlines_fade4; struct DRWPass *outlines_fade5; struct DRWPass *outlines_resolve; + struct DRWPass *grid; struct DRWPass *bone_solid; struct DRWPass *bone_wire; } OBJECT_PassList; @@ -153,6 +160,9 @@ static struct { struct GPUShader *outline_resolve_sh; struct GPUShader *outline_detect_sh; struct GPUShader *outline_fade_sh; + struct GPUShader *grid_sh; + float camera_pos[3]; + float grid_settings[4]; } e_data = {NULL}; /* Engine data */ /* *********** FUNCTIONS *********** */ @@ -187,6 +197,29 @@ static void OBJECT_engine_init(void) if (!e_data.outline_fade_sh) { e_data.outline_fade_sh = DRW_shader_create_fullscreen(datatoc_object_outline_expand_frag_glsl, NULL); } + + if (!e_data.grid_sh) { + e_data.grid_sh = DRW_shader_create_with_lib(datatoc_object_grid_vert_glsl, NULL, + datatoc_object_grid_frag_glsl, + datatoc_common_globals_lib_glsl, NULL); + } + + { + /* Setup camera pos */ + float viewmat[4][4]; + DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEWINV); + copy_v3_v3(e_data.camera_pos, viewmat[3]); + + /* grid settings */ + const bContext *C = DRW_get_context(); + View3D *v3d = CTX_wm_view3d(C); + Scene *scene = CTX_data_scene(C); + + 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 */ + } } static void OBJECT_engine_free(void) @@ -197,6 +230,8 @@ static void OBJECT_engine_free(void) DRW_shader_free(e_data.outline_detect_sh); if (e_data.outline_fade_sh) DRW_shader_free(e_data.outline_fade_sh); + if (e_data.grid_sh) + DRW_shader_free(e_data.grid_sh); } static DRWShadingGroup *shgroup_outline(DRWPass *pass, const float col[4], struct GPUShader *sh) @@ -322,6 +357,20 @@ static void OBJECT_cache_init(void) DRW_shgroup_call_add(grp, quad, NULL); } + { + /* Grid pass */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + psl->grid = DRW_pass_create("Infinite Grid Pass", state); + + struct Batch *quad = DRW_cache_fullscreen_quad_get(); + + DRWShadingGroup *grp = DRW_shgroup_create(e_data.grid_sh, psl->grid); + 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); + } + { /* Solid bones */ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; @@ -814,16 +863,17 @@ static void OBJECT_draw_scene(void) /* reattach */ DRW_framebuffer_texture_attach(fbl->outlines, txl->outlines_depth_tx, 0); - - /* Combine with scene buffer */ DRW_framebuffer_bind(dfbl->default_fb); - DRW_draw_pass(psl->outlines_resolve); /* This needs to be drawn after the oultine */ DRW_draw_pass(psl->bone_wire); DRW_draw_pass(psl->bone_solid); DRW_draw_pass(psl->non_meshes); DRW_draw_pass(psl->ob_center); + DRW_draw_pass(psl->grid); + + /* Combine with scene buffer last */ + DRW_draw_pass(psl->outlines_resolve); } void OBJECT_collection_settings_create(CollectionEngineSettings *ces) diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl new file mode 100644 index 00000000000..e4fba09c80e --- /dev/null +++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl @@ -0,0 +1,87 @@ + +/* Infinite grid + * Clément Foucault */ + +in vec3 wPos; +in float viewDist; + +out vec4 FragColor; + +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 + +#define GRID_LINE_SMOOTH 1.15 + +float grid(vec2 uv, vec2 fwidthUvs, 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); + /* modulate by the absolute rate of change of the uvs + * (make lines have the same width under perspective) */ + grid_domain /= fwidthUvs; + + /* collapse waves and normalize */ + grid_domain.x = min(grid_domain.x, grid_domain.y) / grid_size; + + return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH / grid_size, grid_domain.x); +} + +float axis(float u, float fwidthU, float line_size) +{ + float axis_domain = abs(u); + /* modulate by the absolute rate of change of the uvs + * (make line have the same width under perspective) */ + axis_domain /= fwidthU; + + return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH, axis_domain - line_size); +} + +void main() +{ + vec2 fwidthUvs = fwidth(wPos.xy); + + float blend, lvl, fade; + + /* 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); + fade = 1.0 - smoothstep(0.0, gridDistance, dist - gridDistance); + } + else { + /* todo find a better way */ + blend = 0.0; + lvl = 0.0; + fade = 1.0; + } + + /* 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)); + + float gridA = grid(wPos.xy, fwidthUvs, scaleA); + float gridB = grid(wPos.xy, fwidthUvs, scaleB); + float gridC = grid(wPos.xy, fwidthUvs, scaleC); + + float xAxis = axis(wPos.y, fwidthUvs.y, 0.1); /* Swapped */ + float yAxis = axis(wPos.x, fwidthUvs.x, 0.1); /* Swapped */ + + 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 = 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 new file mode 100644 index 00000000000..ef457c01284 --- /dev/null +++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl @@ -0,0 +1,19 @@ + +/* Infinite grid + * Clément Foucault */ + +uniform mat4 ViewProjectionMatrix; +uniform mat4 ViewMatrix; + +in vec3 pos; + +out vec3 wPos; +out float viewDist; + +void main() +{ + vec3 realPos = pos * 1e3; + gl_Position = ViewProjectionMatrix * vec4(realPos, 1.0); + viewDist = -(ViewMatrix * vec4(realPos, 1.0)).z; + wPos = realPos; +}