From 78d2abd9c16f97be2ab272ee38ba7e398f57a742 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 21 Jan 2019 19:08:42 +1100 Subject: DRW: Support wire overlay clipping --- source/blender/draw/intern/draw_common.c | 8 ++ source/blender/draw/intern/draw_common.h | 2 + source/blender/draw/modes/edit_mesh_mode.c | 28 +++---- source/blender/draw/modes/overlay_mode.c | 85 +++++++++++++++++----- .../shaders/overlay_face_orientation_vert.glsl | 16 ++++ .../modes/shaders/overlay_face_wireframe_geom.glsl | 41 ++++++++--- .../modes/shaders/overlay_face_wireframe_vert.glsl | 15 ++++ 7 files changed, 149 insertions(+), 46 deletions(-) (limited to 'source') diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index 48212757969..250b0a1f1ab 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -298,6 +298,14 @@ void DRW_globals_free(void) } } +void DRW_shgroup_world_clip_planes_from_rv3d(DRWShadingGroup *shgrp, const RegionView3D *rv3d) +{ + int world_clip_planes_len = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; + DRW_shgroup_uniform_vec4(shgrp, "WorldClipPlanes", rv3d->clip[0], world_clip_planes_len); + DRW_shgroup_uniform_int_copy(shgrp, "WorldClipPlanesLen", world_clip_planes_len); + DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); +} + DRWShadingGroup *shgroup_dynlines_flat_color(DRWPass *pass) { GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_FLAT_COLOR); diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index b79902bf4e3..5b55e93af3d 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -125,6 +125,8 @@ BLI_STATIC_ASSERT_ALIGN(GlobalsUboStorage, 16) void DRW_globals_update(void); void DRW_globals_free(void); +void DRW_shgroup_world_clip_planes_from_rv3d(struct DRWShadingGroup *shgrp, const RegionView3D *rv3d); + struct DRWShadingGroup *shgroup_dynlines_flat_color(struct DRWPass *pass); struct DRWShadingGroup *shgroup_dynlines_dashed_uniform_color(struct DRWPass *pass, float color[4]); struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass, float color[4], float *size); diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index dfd4b213c7c..1a3d7fb4cb4 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -174,14 +174,6 @@ static int EDIT_MESH_sh_data_index_from_rv3d(const RegionView3D *rv3d) return 0; } -static void EDIT_MESH_shgroup_world_clip_planes_from_rv3d(DRWShadingGroup *shgrp, const RegionView3D *rv3d) -{ - int world_clip_planes_len = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; - DRW_shgroup_uniform_vec4(shgrp, "WorldClipPlanes", rv3d->clip[0], world_clip_planes_len); - DRW_shgroup_uniform_int_copy(shgrp, "WorldClipPlanesLen", world_clip_planes_len); - DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES); -} - static int EDIT_MESH_sh_index(ToolSettings *tsettings, RegionView3D *rv3d, bool supports_fast_mode) { int result = tsettings->selectmode << 1; @@ -415,7 +407,7 @@ static DRWPass *edit_mesh_create_overlay_pass( DRW_shgroup_state_enable(*r_lverts_shgrp, DRW_STATE_WRITE_DEPTH); DRW_shgroup_state_disable(*r_lverts_shgrp, DRW_STATE_BLEND); if (rv3d->rflag & RV3D_CLIPPING) { - EDIT_MESH_shgroup_world_clip_planes_from_rv3d(*r_lverts_shgrp, rv3d); + DRW_shgroup_world_clip_planes_from_rv3d(*r_lverts_shgrp, rv3d); } *r_verts_shgrp = DRW_shgroup_create(sh_data->overlay_vert, pass); @@ -425,7 +417,7 @@ static DRWPass *edit_mesh_create_overlay_pass( DRW_shgroup_state_enable(*r_verts_shgrp, DRW_STATE_WRITE_DEPTH); DRW_shgroup_state_disable(*r_verts_shgrp, DRW_STATE_BLEND); if (rv3d->rflag & RV3D_CLIPPING) { - EDIT_MESH_shgroup_world_clip_planes_from_rv3d(*r_verts_shgrp, rv3d); + DRW_shgroup_world_clip_planes_from_rv3d(*r_verts_shgrp, rv3d); } } @@ -435,7 +427,7 @@ static DRWPass *edit_mesh_create_overlay_pass( DRW_shgroup_uniform_float(*r_facedot_shgrp, "edgeScale", edge_width_scale, 1); DRW_shgroup_state_enable(*r_facedot_shgrp, DRW_STATE_WRITE_DEPTH); if (rv3d->rflag & RV3D_CLIPPING) { - EDIT_MESH_shgroup_world_clip_planes_from_rv3d(*r_facedot_shgrp, rv3d); + DRW_shgroup_world_clip_planes_from_rv3d(*r_facedot_shgrp, rv3d); } } @@ -454,7 +446,7 @@ static DRWPass *edit_mesh_create_overlay_pass( DRW_shgroup_state_enable(*r_face_shgrp, DRW_STATE_FIRST_VERTEX_CONVENTION); } if (rv3d->rflag & RV3D_CLIPPING) { - EDIT_MESH_shgroup_world_clip_planes_from_rv3d(*r_face_shgrp, rv3d); + DRW_shgroup_world_clip_planes_from_rv3d(*r_face_shgrp, rv3d); } /* Cage geom needs to be offseted to avoid Z-fighting. */ @@ -468,7 +460,7 @@ static DRWPass *edit_mesh_create_overlay_pass( DRW_shgroup_uniform_ivec4(*r_ledges_shgrp, "dataMask", data_mask, 1); DRW_shgroup_uniform_bool_copy(*r_ledges_shgrp, "doEdges", do_edges); if (rv3d->rflag & RV3D_CLIPPING) { - EDIT_MESH_shgroup_world_clip_planes_from_rv3d(*r_ledges_shgrp, rv3d); + DRW_shgroup_world_clip_planes_from_rv3d(*r_ledges_shgrp, rv3d); } return pass; @@ -556,7 +548,7 @@ static void EDIT_MESH_cache_init(void *vedata) DRW_shgroup_uniform_texture(stl->g_data->fweights_shgrp, "colorramp", globals_weight_ramp); DRW_shgroup_uniform_block(stl->g_data->fweights_shgrp, "globalsBlock", globals_ubo); if (rv3d->rflag & RV3D_CLIPPING) { - EDIT_MESH_shgroup_world_clip_planes_from_rv3d(stl->g_data->fweights_shgrp, rv3d); + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fweights_shgrp, rv3d); } } @@ -589,21 +581,21 @@ static void EDIT_MESH_cache_init(void *vedata) DRW_shgroup_uniform_float(stl->g_data->fnormals_shgrp, "normalSize", &size_normal, 1); DRW_shgroup_uniform_vec4(stl->g_data->fnormals_shgrp, "color", ts.colorNormal, 1); if (rv3d->rflag & RV3D_CLIPPING) { - EDIT_MESH_shgroup_world_clip_planes_from_rv3d(stl->g_data->fnormals_shgrp, rv3d); + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fnormals_shgrp, rv3d); } stl->g_data->vnormals_shgrp = DRW_shgroup_create(sh_data->normals, psl->normals); DRW_shgroup_uniform_float(stl->g_data->vnormals_shgrp, "normalSize", &size_normal, 1); DRW_shgroup_uniform_vec4(stl->g_data->vnormals_shgrp, "color", ts.colorVNormal, 1); if (rv3d->rflag & RV3D_CLIPPING) { - EDIT_MESH_shgroup_world_clip_planes_from_rv3d(stl->g_data->vnormals_shgrp, rv3d); + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->vnormals_shgrp, rv3d); } stl->g_data->lnormals_shgrp = DRW_shgroup_create(sh_data->normals_loop, psl->normals); DRW_shgroup_uniform_float(stl->g_data->lnormals_shgrp, "normalSize", &size_normal, 1); DRW_shgroup_uniform_vec4(stl->g_data->lnormals_shgrp, "color", ts.colorLNormal, 1); if (rv3d->rflag & RV3D_CLIPPING) { - EDIT_MESH_shgroup_world_clip_planes_from_rv3d(stl->g_data->lnormals_shgrp, rv3d); + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->lnormals_shgrp, rv3d); } } @@ -639,7 +631,7 @@ static void EDIT_MESH_cache_init(void *vedata) DRW_shgroup_uniform_block(stl->g_data->facefill_occluded_shgrp, "globalsBlock", globals_ubo); DRW_shgroup_uniform_ivec4(stl->g_data->facefill_occluded_shgrp, "dataMask", stl->g_data->data_mask, 1); if (rv3d->rflag & RV3D_CLIPPING) { - EDIT_MESH_shgroup_world_clip_planes_from_rv3d(stl->g_data->facefill_occluded_shgrp, rv3d); + DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->facefill_occluded_shgrp, rv3d); } /* we need a full screen pass to combine the result */ diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c index 274843ac289..2fc4cf3a765 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -65,14 +65,21 @@ typedef struct OVERLAY_PrivateData { bool show_overlays; } OVERLAY_PrivateData; /* Transient data */ -/* *********** STATIC *********** */ -static struct { +#define DEF_WORLD_CLIP_STR "#define USE_WORLD_CLIP_PLANES\n" + +typedef struct OVERLAY_ShaderData { /* Face orientation shader */ struct GPUShader *face_orientation_sh; /* Wireframe shader */ struct GPUShader *select_wireframe_sh; struct GPUShader *face_wireframe_sh; struct GPUShader *face_wireframe_sculpt_sh; +} OVERLAY_ShaderData; + +/* *********** STATIC *********** */ +static struct { + /* 0: normal, 1: clipped. */ + OVERLAY_ShaderData sh_data[2]; } e_data = {NULL}; /* Shaders */ @@ -86,43 +93,62 @@ extern char datatoc_gpu_shader_depth_only_frag_glsl[]; extern struct GlobalsUboStorage ts; /* draw_common.c */ +static int OVERLAY_sh_data_index_from_rv3d(const RegionView3D *rv3d) +{ + if (rv3d->rflag & RV3D_CLIPPING) { + return 1; + } + return 0; +} + /* Functions */ static void overlay_engine_init(void *vedata) { OVERLAY_Data *data = vedata; OVERLAY_StorageList *stl = data->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + OVERLAY_ShaderData *sh_data = &e_data.sh_data[OVERLAY_sh_data_index_from_rv3d(draw_ctx->rv3d)]; + const bool is_clip = (draw_ctx->rv3d->rflag & RV3D_CLIPPING) != 0; + + if (is_clip) { + DRW_state_clip_planes_len_set((draw_ctx->rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6); + } + if (!stl->g_data) { /* Alloc transient pointers */ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); } stl->g_data->ghost_stencil_test = false; - if (!e_data.face_orientation_sh) { + if (!sh_data->face_orientation_sh) { /* Face orientation */ - e_data.face_orientation_sh = DRW_shader_create( + sh_data->face_orientation_sh = DRW_shader_create( datatoc_overlay_face_orientation_vert_glsl, NULL, - datatoc_overlay_face_orientation_frag_glsl, NULL); + datatoc_overlay_face_orientation_frag_glsl, + is_clip ? NULL : DEF_WORLD_CLIP_STR); } - if (!e_data.face_wireframe_sh) { - e_data.select_wireframe_sh = DRW_shader_create( + if (!sh_data->face_wireframe_sh) { + sh_data->select_wireframe_sh = DRW_shader_create( datatoc_overlay_face_wireframe_vert_glsl, datatoc_overlay_face_wireframe_geom_glsl, datatoc_gpu_shader_depth_only_frag_glsl, - "#define SELECT_EDGES\n"); + DEF_WORLD_CLIP_STR "#define SELECT_EDGES\n" + + (is_clip ? 0 : strlen(DEF_WORLD_CLIP_STR))); - e_data.face_wireframe_sh = DRW_shader_create( + sh_data->face_wireframe_sh = DRW_shader_create( datatoc_overlay_face_wireframe_vert_glsl, NULL, datatoc_overlay_face_wireframe_frag_glsl, - NULL); + is_clip ? DEF_WORLD_CLIP_STR : NULL); - e_data.face_wireframe_sculpt_sh = DRW_shader_create( + sh_data->face_wireframe_sculpt_sh = DRW_shader_create( datatoc_overlay_face_wireframe_vert_glsl, datatoc_overlay_face_wireframe_geom_glsl, datatoc_overlay_face_wireframe_frag_glsl, - "#define USE_SCULPT\n"); + DEF_WORLD_CLIP_STR "#define USE_SCULPT\n" + + (is_clip ? 0 : strlen(DEF_WORLD_CLIP_STR))); } } @@ -133,6 +159,10 @@ static void overlay_cache_init(void *vedata) OVERLAY_StorageList *stl = data->stl; OVERLAY_PrivateData *g_data = stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + RegionView3D *rv3d = draw_ctx->rv3d; + OVERLAY_ShaderData *sh_data = &e_data.sh_data[OVERLAY_sh_data_index_from_rv3d(rv3d)]; + const DRWContextState *DCS = DRW_context_state_get(); View3D *v3d = DCS->v3d; @@ -159,7 +189,10 @@ static void overlay_cache_init(void *vedata) DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND; psl->face_orientation_pass = DRW_pass_create("Face Orientation", state); g_data->face_orientation_shgrp = DRW_shgroup_create( - e_data.face_orientation_sh, psl->face_orientation_pass); + sh_data->face_orientation_sh, psl->face_orientation_pass); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_orientation_shgrp, rv3d); + } } { @@ -168,18 +201,27 @@ static void overlay_cache_init(void *vedata) float wire_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f; const bool use_select = (DRW_state_is_select() || DRW_state_is_depth()); - GPUShader *sculpt_wire_sh = use_select ? e_data.select_wireframe_sh : e_data.face_wireframe_sculpt_sh; - GPUShader *face_wires_sh = use_select ? e_data.select_wireframe_sh : e_data.face_wireframe_sh; + GPUShader *sculpt_wire_sh = use_select ? sh_data->select_wireframe_sh : sh_data->face_wireframe_sculpt_sh; + GPUShader *face_wires_sh = use_select ? sh_data->select_wireframe_sh : sh_data->face_wireframe_sh; GPUShader *flat_wires_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); psl->face_wireframe_pass = DRW_pass_create("Face Wires", state); g_data->flat_wires = DRW_shgroup_create(flat_wires_sh, psl->face_wireframe_pass); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(g_data->flat_wires, rv3d); + } g_data->sculpt_wires = DRW_shgroup_create(sculpt_wire_sh, psl->face_wireframe_pass); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(g_data->sculpt_wires, rv3d); + } g_data->face_wires = DRW_shgroup_create(face_wires_sh, psl->face_wireframe_pass); DRW_shgroup_uniform_vec2(g_data->face_wires, "wireStepParam", g_data->wire_step_param, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_wires, rv3d); + } if (!use_select) { DRW_shgroup_uniform_float_copy(g_data->sculpt_wires, "wireSize", wire_size); @@ -192,6 +234,8 @@ static void overlay_cache_init(void *vedata) const float decompress = (0xFF / (float)(0xFF - 0x20)); g_data->wire_step_param[0] = -sharpness * decompress; g_data->wire_step_param[1] = decompress + sharpness * stl->g_data->overlay.wireframe_threshold; + + } } @@ -376,10 +420,13 @@ static void overlay_draw_scene(void *vedata) static void overlay_engine_free(void) { - DRW_SHADER_FREE_SAFE(e_data.face_orientation_sh); - DRW_SHADER_FREE_SAFE(e_data.select_wireframe_sh); - DRW_SHADER_FREE_SAFE(e_data.face_wireframe_sh); - DRW_SHADER_FREE_SAFE(e_data.face_wireframe_sculpt_sh); + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + OVERLAY_ShaderData *sh_data = &e_data.sh_data[sh_data_index]; + GPUShader **sh_data_as_array = (GPUShader **)sh_data; + for (int i = 0; i < (sizeof(OVERLAY_ShaderData) / sizeof(GPUShader *)); i++) { + DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); + } + } } static const DrawEngineDataSize overlay_data_size = DRW_VIEWPORT_DATA_SIZE(OVERLAY_Data); diff --git a/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl index d8a72f28eee..2d025bc65ee 100644 --- a/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl @@ -1,7 +1,23 @@ uniform mat4 ModelViewProjectionMatrix; +uniform mat4 ModelMatrix; + +#ifdef USE_WORLD_CLIP_PLANES +uniform vec4 WorldClipPlanes[6]; +uniform int WorldClipPlanesLen; +#endif + in vec3 pos; void main() { gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + +#ifdef USE_WORLD_CLIP_PLANES + { + vec3 worldPosition = (ModelMatrix * vec4(pos, 1.0)).xyz; + for (int i = 0; i < WorldClipPlanesLen; i++) { + gl_ClipDistance[i] = dot(WorldClipPlanes[i].xyz, worldPosition) + WorldClipPlanes[i].w; + } + } +#endif } diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl index 9249b29436b..2f3acc2a050 100644 --- a/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl @@ -8,6 +8,10 @@ layout(line_strip, max_vertices = 6) out; layout(triangle_strip, max_vertices = 3) out; #endif +#ifdef USE_WORLD_CLIP_PLANES +uniform int WorldClipPlanesLen; +#endif + in float facing_g[]; in float edgeSharpness_g[]; @@ -17,25 +21,44 @@ out vec3 barycentric; flat out vec3 edgeSharpness; #endif +void vert_from_gl_in(int v) +{ + gl_Position = gl_in[v].gl_Position; +#ifdef USE_WORLD_CLIP_PLANES + for (int i = 0; i < WorldClipPlanesLen; i++) { + gl_ClipDistance[i] = gl_in[v].gl_ClipDistance[i]; + } +#endif +} + void main(void) { #ifdef SELECT_EDGES const float edge_select_threshold = 0.3; if (edgeSharpness_g[0] > edge_select_threshold) { - gl_Position = gl_in[0].gl_Position; EmitVertex(); - gl_Position = gl_in[1].gl_Position; EmitVertex(); + vert_from_gl_in(0); + EmitVertex(); + vert_from_gl_in(1); + EmitVertex(); + EndPrimitive(); } if (edgeSharpness_g[1] > edge_select_threshold) { - gl_Position = gl_in[1].gl_Position; EmitVertex(); - gl_Position = gl_in[2].gl_Position; EmitVertex(); + vert_from_gl_in(1); + EmitVertex(); + vert_from_gl_in(2); + EmitVertex(); + EndPrimitive(); } if (edgeSharpness_g[2] > edge_select_threshold) { - gl_Position = gl_in[2].gl_Position; EmitVertex(); - gl_Position = gl_in[0].gl_Position; EmitVertex(); + vert_from_gl_in(2); + EmitVertex(); + vert_from_gl_in(0); + EmitVertex(); + EndPrimitive(); } #else @@ -50,17 +73,17 @@ void main(void) edgeSharpness = vec3(1.0); barycentric = vec3(1.0, 0.0, 0.0); - gl_Position = gl_in[0].gl_Position; + vert_from_gl_in(0); facing = facing_g[0]; EmitVertex(); barycentric = vec3(0.0, 1.0, 0.0); - gl_Position = gl_in[1].gl_Position; + vert_from_gl_in(1); facing = facing_g[1]; EmitVertex(); barycentric = vec3(0.0, 0.0, 1.0); - gl_Position = gl_in[2].gl_Position; + vert_from_gl_in(2); facing = facing_g[2]; EmitVertex(); EndPrimitive(); diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl index d5c2bdeefea..3c3869db7b4 100644 --- a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl @@ -1,9 +1,15 @@ uniform mat4 ModelViewProjectionMatrix; +uniform mat4 ModelMatrix; uniform mat3 NormalMatrix; uniform vec2 wireStepParam; +#ifdef USE_WORLD_CLIP_PLANES +uniform vec4 WorldClipPlanes[6]; +uniform int WorldClipPlanesLen; +#endif + vec3 get_edge_sharpness(vec3 wd) { bvec3 do_edge = greaterThan(wd, vec3(0.0)); @@ -76,6 +82,15 @@ void main() gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); facing = normalize(NormalMatrix * nor).z; + +#ifdef USE_WORLD_CLIP_PLANES + { + vec3 worldPosition = (ModelMatrix * vec4(pos, 1.0)).xyz; + for (int i = 0; i < WorldClipPlanesLen; i++) { + gl_ClipDistance[i] = dot(WorldClipPlanes[i].xyz, worldPosition) + WorldClipPlanes[i].w; + } + } +#endif } #endif /* SELECT_EDGES */ -- cgit v1.2.3