From 773f3428cfc5212641c59536f56179a58acf318a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 4 Feb 2019 22:28:39 +0100 Subject: Edit Mesh: Add workaround for system that does not support wide lines This adds a new geometry shader (specific to edit mesh for now) that reproduces the effect of glLineWidth > 1.0, since this is not supported on all platform. This fix could be generalized to other shaders later. --- source/blender/draw/CMakeLists.txt | 1 + source/blender/draw/modes/edit_mesh_mode.c | 23 ++++++-- .../draw/modes/shaders/edit_mesh_overlay_geom.glsl | 64 ++++++++++++++++++++++ .../draw/modes/shaders/edit_mesh_overlay_vert.glsl | 51 +++++++++++------ 4 files changed, 118 insertions(+), 21 deletions(-) create mode 100644 source/blender/draw/modes/shaders/edit_mesh_overlay_geom.glsl (limited to 'source') diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index b3e643dafdb..1b7c2a15cc3 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -270,6 +270,7 @@ data_to_c_simple(modes/shaders/armature_dof_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_common_lib.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_vert.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_geom.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_mix_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_frag.glsl SRC) diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index d9c60115e14..bd4a1e85ca8 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -23,7 +23,7 @@ #include "DRW_engine.h" #include "DRW_render.h" -#include "GPU_shader.h" +#include "GPU_extensions.h" #include "DNA_mesh_types.h" #include "DNA_view3d_types.h" @@ -51,6 +51,7 @@ extern char datatoc_paint_weight_frag_glsl[]; extern char datatoc_edit_mesh_overlay_common_lib_glsl[]; extern char datatoc_edit_mesh_overlay_frag_glsl[]; extern char datatoc_edit_mesh_overlay_vert_glsl[]; +extern char datatoc_edit_mesh_overlay_geom_glsl[]; extern char datatoc_edit_mesh_overlay_mix_frag_glsl[]; extern char datatoc_edit_mesh_overlay_facefill_vert_glsl[]; extern char datatoc_edit_mesh_overlay_facefill_frag_glsl[]; @@ -192,6 +193,12 @@ static void EDIT_MESH_engine_init(void *vedata) }); char *lib = BLI_string_joinN(world_clip_lib_or_empty, datatoc_common_globals_lib_glsl, datatoc_edit_mesh_overlay_common_lib_glsl); + const bool use_geom_shader = GPU_max_line_width() <= 2.0f; + const char *geom_sh_code[] = {lib, datatoc_edit_mesh_overlay_geom_glsl, NULL}; + if (!use_geom_shader) { + geom_sh_code[0] = NULL; + } + const char *use_geom_def = use_geom_shader ? "#define USE_GEOM_SHADER\n" : ""; sh_data->overlay_face = DRW_shader_create_from_arrays({ .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, .frag = (const char *[]){datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL}, @@ -200,17 +207,20 @@ static void EDIT_MESH_engine_init(void *vedata) sh_data->overlay_edge = DRW_shader_create_from_arrays({ .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, .frag = (const char *[]){lib, datatoc_edit_mesh_overlay_frag_glsl, NULL}, - .defs = (const char *[]){world_clip_def_or_empty, "#define EDGE\n", NULL}, + .defs = (const char *[]){world_clip_def_or_empty, use_geom_def, "#define EDGE\n", NULL}, + .geom = (use_geom_shader) ? geom_sh_code : NULL, }); sh_data->overlay_edge_flat = DRW_shader_create_from_arrays({ .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL}, - .defs = (const char *[]){world_clip_def_or_empty, "#define EDGE\n", "#define FLAT\n", NULL}, + .defs = (const char *[]){world_clip_def_or_empty, use_geom_def, "#define EDGE\n", "#define FLAT\n", NULL}, + .geom = (use_geom_shader) ? geom_sh_code : NULL, }); sh_data->overlay_edge_deco = DRW_shader_create_from_arrays({ .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL}, - .defs = (const char *[]){world_clip_def_or_empty, "#define EDGE_DECORATION\n", "#define FLAT\n", NULL}, + .defs = (const char *[]){world_clip_def_or_empty, use_geom_def, "#define EDGE_DECORATION\n", "#define FLAT\n", NULL}, + .geom = (use_geom_shader) ? geom_sh_code : NULL, }); sh_data->overlay_vert = DRW_shader_create_from_arrays({ .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL}, @@ -305,7 +315,6 @@ static DRWPass *edit_mesh_create_overlay_pass( grp = *r_face_shgrp = DRW_shgroup_create(face_sh, 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_float(grp, "faceAlphaMod", face_alpha, 1); DRW_shgroup_uniform_float(grp, "edgeScale", edge_width_scale, 1); DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1); @@ -322,6 +331,8 @@ static DRWPass *edit_mesh_create_overlay_pass( /* Edges */ grp = *r_edge_deco_shgrp = DRW_shgroup_create(edge_deco_sh, 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_vec2(grp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1); DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1); DRW_shgroup_uniform_bool_copy(grp, "doEdges", do_edges); DRW_shgroup_uniform_float_copy(grp, "ofs", depth_ofs); @@ -336,6 +347,8 @@ static DRWPass *edit_mesh_create_overlay_pass( grp = *r_edge_shgrp = DRW_shgroup_create(edge_sh, 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_vec2(grp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1); DRW_shgroup_uniform_float(grp, "edgeScale", edge_width_scale, 1); DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1); DRW_shgroup_uniform_bool_copy(grp, "doEdges", do_edges); diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom.glsl new file mode 100644 index 00000000000..66792b61fb7 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom.glsl @@ -0,0 +1,64 @@ + +layout(lines) in; +layout(triangle_strip, max_vertices = 4) out; + +uniform vec2 viewportSize; +uniform vec2 viewportSizeInv; + +in VertexData { + vec4 finalColor; +#if defined(EDGE) && !defined(FLAT) + int selectOveride; +#endif +} v[]; + +#ifdef FLAT +# define interp_col flat +#else +# define interp_col +#endif + +interp_col out vec4 finalColor; +#if defined(EDGE) && !defined(FLAT) +flat out int selectOveride; +#endif + +void do_vertex(const int i, vec2 offset) +{ + finalColor = v[i].finalColor; +#if defined(EDGE) && !defined(FLAT) + selectOveride = v[0].selectOveride; +#endif + gl_Position = gl_in[i].gl_Position; + gl_Position.xy += offset * gl_Position.w; + EmitVertex(); +} + +void main() +{ + vec2 ss_pos[2]; + ss_pos[0] = gl_in[0].gl_Position.xy / gl_in[0].gl_Position.w; + ss_pos[1] = gl_in[1].gl_Position.xy / gl_in[1].gl_Position.w; + + vec2 line = ss_pos[0] - ss_pos[1]; + + vec3 edge_ofs = sizeEdge * 2.0 * viewportSizeInv.xyy * vec3(1.0, 1.0, 0.0); + +#ifdef EDGE_DECORATION + edge_ofs *= 3.0; + + if (finalColor.a == 0.0) { + return; + } +#endif + + bool horizontal = abs(line.x) > abs(line.y); + edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz; + + do_vertex(0, edge_ofs.xy); + do_vertex(0, -edge_ofs.xy); + do_vertex(1, edge_ofs.xy); + do_vertex(1, -edge_ofs.xy); + + EndPrimitive(); +} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl index e27e1d01750..bc25ff17e74 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl @@ -17,13 +17,32 @@ in vec4 norAndFlag; # define vnor norAndFlag.xyz #endif -#ifdef FLAT -flat out vec4 finalColor; +#ifdef USE_GEOM_SHADER +# define qual_col +# define qual_sel #else -out vec4 finalColor; -# ifdef EDGE -flat out int selectOveride; +# ifdef FLAT +# define qual_col flat out +# else +# define qual_col out # endif +# define qual_sel flat out +#endif + +#ifdef USE_GEOM_SHADER +out VertexData { +#endif + +qual_col vec4 finalColor; +#if defined(EDGE) && !defined(FLAT) +qual_sel int selectOveride; +#endif + +#ifdef USE_GEOM_SHADER +} v; +# define v(a) v.a +#else +# define v(a) a #endif void main() @@ -41,7 +60,7 @@ void main() ivec4 m_data = data & dataMask; #if defined(VERT) - finalColor = EDIT_MESH_vertex_color(m_data.y); + v(finalColor) = EDIT_MESH_vertex_color(m_data.y); gl_PointSize = sizeVertex * 2.0; gl_Position.z -= 3e-5 * ((ProjectionMatrix[3][3] == 0.0) ? 1.0 : 0.0); /* Make selected and active vertex always on top. */ @@ -54,23 +73,23 @@ void main() #elif defined(EDGE) # ifdef FLAT - finalColor = EDIT_MESH_edge_color_inner(m_data.y); + v(finalColor) = EDIT_MESH_edge_color_inner(m_data.y); # else - finalColor = EDIT_MESH_edge_vertex_color(m_data.y); - selectOveride = (m_data.y & EDGE_SELECTED); + v(finalColor) = EDIT_MESH_edge_vertex_color(m_data.y); + v(selectOveride) = (m_data.y & EDGE_SELECTED); # endif #elif defined(EDGE_DECORATION) float crease = float(m_data.z) / 255.0; float bweight = float(m_data.w) / 255.0; - finalColor = EDIT_MESH_edge_color_outer(m_data.y, m_data.x, crease, bweight); + v(finalColor) = EDIT_MESH_edge_color_outer(m_data.y, m_data.x, crease, bweight); #elif defined(FACE) - finalColor = EDIT_MESH_face_color(m_data.x); - finalColor.a *= faceAlphaMod; + v(finalColor) = EDIT_MESH_face_color(m_data.x); + v(finalColor).a *= faceAlphaMod; #elif defined(FACEDOT) - finalColor = EDIT_MESH_facedot_color(norAndFlag.w); + v(finalColor) = EDIT_MESH_facedot_color(norAndFlag.w); /* Bias Facedot Z position in clipspace. */ gl_Position.z -= 0.00035; gl_PointSize = sizeFaceDot; @@ -87,12 +106,12 @@ void main() float facing = dot(view_vec, view_normal); facing = 1.0 - abs(facing) * 0.3; - finalColor = mix(colorEditMeshMiddle, finalColor, facing); - finalColor.a = 1.0; + v(finalColor) = mix(colorEditMeshMiddle, v(finalColor), facing); + v(finalColor).a = 1.0; # if defined(EDGE) && !defined(FLAT) /* Hack to blend color in pixel shader in case of overide. */ - finalColor.a = facing; + v(finalColor).a = facing; # endif #endif -- cgit v1.2.3