From 3e6ebdd2a6b5b7563e9c45dae3c65ebf7d629544 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 6 Feb 2019 23:19:39 +1100 Subject: DRW: Support edit-curve clipping --- source/blender/draw/modes/edit_curve_mode.c | 95 ++++++++++++++++------ .../shaders/edit_curve_overlay_handle_geom.glsl | 6 ++ .../shaders/edit_curve_overlay_handle_vert.glsl | 10 ++- .../shaders/edit_curve_overlay_loosevert_vert.glsl | 9 +- .../shaders/edit_curve_overlay_normals_vert.glsl | 10 ++- 5 files changed, 96 insertions(+), 34 deletions(-) (limited to 'source/blender/draw/modes') diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c index bb34ce3f1ad..4adf31b9b25 100644 --- a/source/blender/draw/modes/edit_curve_mode.c +++ b/source/blender/draw/modes/edit_curve_mode.c @@ -38,6 +38,7 @@ * Not needed for constant color. */ extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_gpu_shader_cfg_world_clip_lib_glsl[]; extern char datatoc_edit_curve_overlay_loosevert_vert_glsl[]; extern char datatoc_edit_curve_overlay_normals_vert_glsl[]; extern char datatoc_edit_curve_overlay_handle_vert_glsl[]; @@ -75,11 +76,16 @@ typedef struct EDIT_CURVE_Data { /* *********** STATIC *********** */ -static struct { + +typedef struct EDIT_CURVE_Shaders { GPUShader *wire_sh; GPUShader *wire_normals_sh; GPUShader *overlay_edge_sh; /* handles and nurbs control cage */ GPUShader *overlay_vert_sh; +} EDIT_CURVE_Shaders; + +static struct { + EDIT_CURVE_Shaders sh_data[GPU_SHADER_CFG_LEN]; } e_data = {NULL}; /* Engine data */ typedef struct EDIT_CURVE_PrivateData { @@ -100,29 +106,46 @@ typedef struct EDIT_CURVE_PrivateData { * (Optional) */ static void EDIT_CURVE_engine_init(void *UNUSED(vedata)) { - if (!e_data.wire_sh) { - e_data.wire_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + const DRWContextState *draw_ctx = DRW_context_state_get(); + EDIT_CURVE_Shaders *sh_data = &e_data.sh_data[draw_ctx->shader_cfg]; + const bool is_clip = (draw_ctx->rv3d->rflag & RV3D_CLIPPING) != 0; + + if (is_clip) { + DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d); } - if (!e_data.wire_normals_sh) { - e_data.wire_normals_sh = DRW_shader_create( - datatoc_edit_curve_overlay_normals_vert_glsl, NULL, - datatoc_gpu_shader_uniform_color_frag_glsl, NULL); + const char *world_clip_lib_or_empty = is_clip ? datatoc_gpu_shader_cfg_world_clip_lib_glsl : ""; + const char *world_clip_def_or_empty = is_clip ? "#define USE_WORLD_CLIP_PLANES\n" : ""; + + if (!sh_data->wire_sh) { + sh_data->wire_sh = GPU_shader_get_builtin_shader_with_config( + GPU_SHADER_3D_UNIFORM_COLOR, draw_ctx->shader_cfg); } - if (!e_data.overlay_edge_sh) { - e_data.overlay_edge_sh = DRW_shader_create_with_lib( - datatoc_edit_curve_overlay_handle_vert_glsl, - datatoc_edit_curve_overlay_handle_geom_glsl, - datatoc_gpu_shader_3D_smooth_color_frag_glsl, - datatoc_common_globals_lib_glsl, NULL); + if (!sh_data->wire_normals_sh) { + sh_data->wire_normals_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){world_clip_lib_or_empty, datatoc_edit_curve_overlay_normals_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL}, + .defs = (const char *[]){world_clip_def_or_empty, NULL}, + }); } - if (!e_data.overlay_vert_sh) { - e_data.overlay_vert_sh = DRW_shader_create_with_lib( - datatoc_edit_curve_overlay_loosevert_vert_glsl, NULL, - datatoc_gpu_shader_point_varying_color_frag_glsl, - datatoc_common_globals_lib_glsl, NULL); + if (!sh_data->overlay_edge_sh) { + sh_data->overlay_edge_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){world_clip_lib_or_empty, datatoc_edit_curve_overlay_handle_vert_glsl, NULL}, + .geom = (const char *[]){world_clip_lib_or_empty, datatoc_common_globals_lib_glsl, datatoc_edit_curve_overlay_handle_geom_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL}, + .defs = (const char *[]){world_clip_def_or_empty, NULL}, + }); + } + + if (!sh_data->overlay_vert_sh) { + sh_data->overlay_vert_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){world_clip_lib_or_empty, datatoc_common_globals_lib_glsl, datatoc_edit_curve_overlay_loosevert_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL}, + .defs = (const char *[]){world_clip_def_or_empty, NULL}, + }); + } } @@ -134,6 +157,8 @@ static void EDIT_CURVE_cache_init(void *vedata) EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl; const DRWContextState *draw_ctx = DRW_context_state_get(); View3D *v3d = draw_ctx->v3d; + const RegionView3D *rv3d = draw_ctx->rv3d; + EDIT_CURVE_Shaders *sh_data = &e_data.sh_data[draw_ctx->shader_cfg]; if (!stl->g_data) { /* Alloc transient pointers */ @@ -150,24 +175,33 @@ static void EDIT_CURVE_cache_init(void *vedata) "Curve Wire", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE); - grp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass); + grp = DRW_shgroup_create(sh_data->wire_sh, psl->wire_pass); DRW_shgroup_uniform_vec4(grp, "color", G_draw.block.colorWireEdit, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } stl->g_data->wire_shgrp = grp; - grp = DRW_shgroup_create(e_data.wire_normals_sh, psl->wire_pass); + grp = DRW_shgroup_create(sh_data->wire_normals_sh, psl->wire_pass); DRW_shgroup_uniform_vec4(grp, "color", G_draw.block.colorWireEdit, 1); DRW_shgroup_uniform_float_copy(grp, "normalSize", v3d->overlay.normals_length); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } stl->g_data->wire_normals_shgrp = grp; psl->overlay_edge_pass = DRW_pass_create( "Curve Handle Overlay", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); - grp = DRW_shgroup_create(e_data.overlay_edge_sh, psl->overlay_edge_pass); + grp = DRW_shgroup_create(sh_data->overlay_edge_sh, psl->overlay_edge_pass); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1); DRW_shgroup_uniform_bool(grp, "showCurveHandles", &stl->g_data->show_handles, 1); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } stl->g_data->overlay_edge_shgrp = grp; @@ -175,8 +209,11 @@ static void EDIT_CURVE_cache_init(void *vedata) "Curve Vert Overlay", DRW_STATE_WRITE_COLOR | DRW_STATE_POINT); - grp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->overlay_vert_pass); + grp = DRW_shgroup_create(sh_data->overlay_vert_sh, psl->overlay_vert_pass); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d); + } stl->g_data->overlay_vert_shgrp = grp; } } @@ -244,6 +281,8 @@ static void EDIT_CURVE_draw_scene(void *vedata) /* Thoses passes don't write to depth and are AA'ed using other tricks. */ DRW_draw_pass(psl->overlay_edge_pass); DRW_draw_pass(psl->overlay_vert_pass); + + DRW_state_clip_planes_reset(); } /* Cleanup when destroying the engine. @@ -251,9 +290,15 @@ static void EDIT_CURVE_draw_scene(void *vedata) * Mostly used for freeing shaders */ static void EDIT_CURVE_engine_free(void) { - DRW_SHADER_FREE_SAFE(e_data.wire_normals_sh); - DRW_SHADER_FREE_SAFE(e_data.overlay_edge_sh); - DRW_SHADER_FREE_SAFE(e_data.overlay_vert_sh); + for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) { + EDIT_CURVE_Shaders *sh_data = &e_data.sh_data[sh_data_index]; + /* Don't free builtins. */ + sh_data->wire_sh = NULL; + GPUShader **sh_data_as_array = (GPUShader **)sh_data; + for (int i = 0; i < (sizeof(EDIT_CURVE_Shaders) / sizeof(GPUShader *)); i++) { + DRW_SHADER_FREE_SAFE(sh_data_as_array[i]); + } + } } static const DrawEngineDataSize EDIT_CURVE_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_CURVE_Data); diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl index 9000fd7247b..c2ab0ecfd40 100644 --- a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl @@ -19,10 +19,16 @@ void output_line(vec2 offset, vec4 color) gl_Position = gl_in[0].gl_Position; gl_Position.xy += offset * gl_in[0].gl_Position.w; +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); +#endif EmitVertex(); gl_Position = gl_in[1].gl_Position; gl_Position.xy += offset * gl_in[1].gl_Position.w; +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); +#endif EmitVertex(); } diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl index d3f9deedf0c..f92aab3254c 100644 --- a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl @@ -1,7 +1,6 @@ - /* Draw Curve Handles */ - uniform mat4 ModelViewProjectionMatrix; +uniform mat4 ModelMatrix; in vec3 pos; in int data; @@ -10,6 +9,11 @@ flat out int vertFlag; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec4 pos_4d = vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * pos_4d; vertFlag = data; + +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); +#endif } diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl index eb0de41a320..b7ffb56ad30 100644 --- a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl @@ -1,7 +1,6 @@ - /* Draw Curve Vertices */ - uniform mat4 ModelViewProjectionMatrix; +uniform mat4 ModelMatrix; uniform vec2 viewportSize; in vec3 pos; @@ -23,6 +22,10 @@ void main() finalColor = colorVertex; } - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec4 pos_4d = vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * pos_4d; gl_PointSize = sizeVertex * 2.0; +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); +#endif } diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl index 06be402d737..da05d224283 100644 --- a/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl @@ -1,7 +1,6 @@ - /* Draw Curve Normals */ - uniform mat4 ModelViewProjectionMatrix; +uniform mat4 ModelMatrix; uniform float normalSize; in vec3 pos; @@ -19,5 +18,10 @@ void main() final_pos += normalSize * rad * (flip * nor - tan); } - gl_Position = ModelViewProjectionMatrix * vec4(final_pos, 1.0); + vec4 final_pos_4d = vec4(final_pos, 1.0); + gl_Position = ModelViewProjectionMatrix * final_pos_4d; + +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance((ModelMatrix * final_pos_4d).xyz); +#endif } -- cgit v1.2.3