From 2cccffd20b67beecb5743e8871dbda779d1e03f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 13 Feb 2019 18:09:16 +0100 Subject: Wireframe: Add workaround for osx wide wires --- source/blender/draw/modes/overlay_mode.c | 49 +++++++----- .../modes/shaders/overlay_face_wireframe_geom.glsl | 93 ++++++++-------------- .../modes/shaders/overlay_face_wireframe_vert.glsl | 13 ++- 3 files changed, 67 insertions(+), 88 deletions(-) (limited to 'source/blender/draw/modes') diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c index e3e64ba6f22..ea502e176f1 100644 --- a/source/blender/draw/modes/overlay_mode.c +++ b/source/blender/draw/modes/overlay_mode.c @@ -32,6 +32,9 @@ #include "GPU_shader.h" #include "DRW_render.h" +#ifdef __APPLE__ +#define USE_GEOM_SHADER_WORKAROUND +#endif /* Structures */ typedef struct OVERLAY_StorageList { @@ -54,7 +57,6 @@ typedef struct OVERLAY_Data { typedef struct OVERLAY_PrivateData { DRWShadingGroup *face_orientation_shgrp; DRWShadingGroup *face_wires_shgrp; - DRWShadingGroup *sculpt_wires_shgrp; View3DOverlay overlay; float wire_step_param; bool ghost_stencil_test; @@ -67,7 +69,6 @@ typedef struct OVERLAY_Shaders { /* Wireframe shader */ struct GPUShader *select_wireframe; struct GPUShader *face_wireframe; - struct GPUShader *face_wireframe_sculpt; } OVERLAY_Shaders; /* *********** STATIC *********** */ @@ -121,16 +122,21 @@ static void overlay_engine_init(void *vedata) .frag = (const char *[]){datatoc_gpu_shader_depth_only_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, "#define SELECT_EDGES\n", NULL}, }); +#ifdef USE_GEOM_SHADER_WORKAROUND + /* Apple drivers does not support wide wires. Use geometry shader as a workaround. */ sh_data->face_wireframe = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL}, + .geom = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_geom_glsl, NULL}, .frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg_data->def, NULL}, + .defs = (const char *[]){sh_cfg_data->def, "#define USE_GEOM\n", NULL}, }); - sh_data->face_wireframe_sculpt = GPU_shader_create_from_arrays({ +#else + sh_data->face_wireframe = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL}, .frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg_data->def, NULL}, }); +#endif } } @@ -179,8 +185,9 @@ static void overlay_cache_init(void *vedata) { /* Wireframe */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_OFFSET_NEGATIVE; - float wire_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f; + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | + DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_OFFSET_NEGATIVE; + float wire_size = U.pixelsize * 0.5f; float winmat[4][4]; float viewdist = rv3d->dist; @@ -192,27 +199,25 @@ static void overlay_cache_init(void *vedata) const float depth_ofs = bglPolygonOffsetCalc((float *)winmat, viewdist, 1.0f); const bool use_select = (DRW_state_is_select() || DRW_state_is_depth()); - GPUShader *sculpt_wire_sh = use_select ? sh_data->select_wireframe : sh_data->face_wireframe_sculpt; GPUShader *face_wires_sh = use_select ? sh_data->select_wireframe : sh_data->face_wireframe; psl->face_wireframe_pass = DRW_pass_create("Face Wires", state); - g_data->sculpt_wires_shgrp = 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_shgrp, rv3d); - } - g_data->face_wires_shgrp = DRW_shgroup_create(face_wires_sh, psl->face_wireframe_pass); DRW_shgroup_uniform_float(g_data->face_wires_shgrp, "wireStepParam", &g_data->wire_step_param, 1); DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "ofs", depth_ofs); - if (rv3d->rflag & RV3D_CLIPPING) { - DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_wires_shgrp, rv3d); - } - +#ifdef USE_GEOM_SHADER_WORKAROUND + DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "wireSize", wire_size); + DRW_shgroup_uniform_vec2(g_data->face_wires_shgrp, "viewportSize", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_vec2(g_data->face_wires_shgrp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1); +#else if (!use_select) { - DRW_shgroup_uniform_float_copy(g_data->sculpt_wires_shgrp, "wireSize", wire_size); DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "wireSize", wire_size); } +#endif + if (rv3d->rflag & RV3D_CLIPPING) { + DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_wires_shgrp, rv3d); + } g_data->wire_step_param = stl->g_data->overlay.wireframe_threshold - 254.0f / 255.0f; } @@ -312,13 +317,13 @@ static void overlay_cache_populate(void *vedata, Object *ob) geom = DRW_cache_object_face_wireframe_get(ob); if (geom || is_sculpt_mode) { - shgrp = (is_sculpt_mode) ? pd->sculpt_wires_shgrp : pd->face_wires_shgrp; - shgrp = DRW_shgroup_create_sub(shgrp); + shgrp = DRW_shgroup_create_sub(pd->face_wires_shgrp); static float all_wires_param = 10.0f; - DRW_shgroup_uniform_vec2( - shgrp, "wireStepParam", (all_wires) ? - &all_wires_param : &pd->wire_step_param, 1); + DRW_shgroup_uniform_float( + shgrp, "wireStepParam", + (all_wires || is_sculpt_mode) ? &all_wires_param : &pd->wire_step_param, + 1); if (!(DRW_state_is_select() || DRW_state_is_depth())) { DRW_shgroup_stencil_mask(shgrp, stencil_mask); 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 d4d53b7d24d..8f52c4fdf95 100644 --- a/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl @@ -1,85 +1,60 @@ -/* This shader is only used for edge selection & sculpt mode wires (because of indexed drawing). */ +/* This shader is only used for edge selection and OSX workaround for large wires. */ -layout(triangles) in; -#ifdef SELECT_EDGES -layout(line_strip, max_vertices = 6) out; -#else -layout(triangle_strip, max_vertices = 3) out; -#endif +uniform float wireSize; +uniform vec2 viewportSize; +uniform vec2 viewportSizeInv; + +layout(lines) in; +layout(triangle_strip, max_vertices = 4) out; in float facing_g[]; in float edgeSharpness_g[]; #ifndef SELECT_EDGES out float facing; -out vec3 barycentric; -flat out vec3 edgeSharpness; +flat out float edgeSharpness; #endif -void vert_from_gl_in(int v) +void do_vertex(const int i, float coord, vec2 offset) { - gl_Position = gl_in[v].gl_Position; +#ifndef SELECT_EDGES + edgeSharpness = edgeSharpness_g[i]; + facing = facing_g[i]; +#endif + gl_Position = gl_in[i].gl_Position; + /* Multiply offset by 2 because gl_Position range is [-1..1]. */ + gl_Position.xy += offset * 2.0 * gl_Position.w; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[v].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[i].gl_ClipDistance); #endif + EmitVertex(); } -void main(void) +void main() { -#ifdef SELECT_EDGES - const float edge_select_threshold = 0.3; - if (edgeSharpness_g[0] > edge_select_threshold) { - vert_from_gl_in(0); - EmitVertex(); - vert_from_gl_in(1); - EmitVertex(); + 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; - EndPrimitive(); - } + vec2 line = ss_pos[0] - ss_pos[1]; + line = abs(line) * viewportSize; - if (edgeSharpness_g[1] > edge_select_threshold) { - vert_from_gl_in(1); - EmitVertex(); - vert_from_gl_in(2); - EmitVertex(); + float half_size = wireSize; - EndPrimitive(); - } + vec3 edge_ofs = half_size * viewportSizeInv.xyy * vec3(1.0, 1.0, 0.0); - if (edgeSharpness_g[2] > edge_select_threshold) { - vert_from_gl_in(2); - EmitVertex(); - vert_from_gl_in(0); - EmitVertex(); + bool horizontal = line.x > line.y; + edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz; - EndPrimitive(); + if (edgeSharpness_g[0] < 0.0) { + return; } -#else - /* Originally was: - * edgeSharpness = vec3(edgeSharpness_g[0], edgeSharpness_g[1], edgeSharpness_g[2]); - * - * But that strangely does not work for some AMD GPUs. - * However since this code is currently only used for sculpt mode - * and in this mode the `edgeSharpness_g` is not calculated, - * let's simply set all to 1.0. - */ - edgeSharpness = vec3(1.0); - barycentric = vec3(1.0, 0.0, 0.0); - vert_from_gl_in(0); - facing = facing_g[0]; - EmitVertex(); + do_vertex(0, half_size, edge_ofs.xy); + do_vertex(0, -half_size, -edge_ofs.xy); + do_vertex(1, half_size, edge_ofs.xy); + do_vertex(1, -half_size, -edge_ofs.xy); - barycentric = vec3(0.0, 1.0, 0.0); - vert_from_gl_in(1); - facing = facing_g[1]; - EmitVertex(); - - barycentric = vec3(0.0, 0.0, 1.0); - vert_from_gl_in(2); - facing = facing_g[2]; - EmitVertex(); EndPrimitive(); -#endif /* SELECT_EDGES */ } 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 53279a74352..2a328a71366 100644 --- a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl +++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl @@ -7,13 +7,17 @@ uniform mat3 NormalMatrix; uniform float wireStepParam; uniform float ofs; +#ifndef USE_SCULPT float get_edge_sharpness(float wd) { return (wd == 1.0) ? 1.0 : ((wd == 0.0) ? -1.0 : (wd + wireStepParam)); } +#else +float get_edge_sharpness(float wd) { return 1.0; } +#endif /* Geometry shader version */ -#if defined(SELECT_EDGES) || defined(USE_SCULPT) +#if defined(SELECT_EDGES) || defined(USE_GEOM) in vec3 pos; in vec3 nor; @@ -24,12 +28,7 @@ out float edgeSharpness_g; void main() { -# ifndef USE_SCULPT edgeSharpness_g = get_edge_sharpness(wd); -# else - /* TODO approximation using normals. */ - edgeSharpness_g = 1.0; -# endif mat4 projmat = ProjectionMatrix; projmat[3][2] -= ofs; @@ -43,7 +42,7 @@ void main() #endif } -#else /* SELECT_EDGES */ +#else /* USE_GEOM */ in vec3 pos; in vec3 nor; -- cgit v1.2.3