diff options
13 files changed, 303 insertions, 164 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 738efffcd91..be742868cd6 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -269,7 +269,7 @@ 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_tri.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_geom_edge.glsl SRC) -data_to_c_simple(modes/shaders/edit_mesh_overlay_loosevert_vert.glsl SRC) +data_to_c_simple(modes/shaders/edit_mesh_overlay_points_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_facedot_frag.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_facedot_vert.glsl SRC) data_to_c_simple(modes/shaders/edit_mesh_overlay_ghost_clear_vert.glsl SRC) diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 9f0306f32a3..20ead73e0f5 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -2986,7 +2986,8 @@ GPUBatch *DRW_cache_mesh_surface_overlay_get(Object *ob) void DRW_cache_mesh_wire_overlay_get( Object *ob, - GPUBatch **r_tris, GPUBatch **r_ledges, GPUBatch **r_lverts) + GPUBatch **r_tris, GPUBatch **r_ledges, GPUBatch **r_lverts, + struct GPUTexture **r_data_tex) { BLI_assert(ob->type == OB_MESH); @@ -2995,6 +2996,7 @@ void DRW_cache_mesh_wire_overlay_get( *r_tris = DRW_mesh_batch_cache_get_overlay_triangles(me); *r_ledges = DRW_mesh_batch_cache_get_overlay_loose_edges(me); *r_lverts = DRW_mesh_batch_cache_get_overlay_loose_verts(me); + *r_data_tex = DRW_mesh_batch_cache_get_overlay_data_tex(me); } void DRW_cache_mesh_normals_overlay_get( diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 5999dc25338..4860b438bb1 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -128,7 +128,8 @@ struct GPUBatch *DRW_cache_bone_dof_lines_get(void); struct GPUBatch *DRW_cache_mesh_surface_overlay_get(struct Object *ob); void DRW_cache_mesh_wire_overlay_get( struct Object *ob, - struct GPUBatch **r_tris, struct GPUBatch **r_ledges, struct GPUBatch **r_lverts); + struct GPUBatch **r_tris, struct GPUBatch **r_ledges, struct GPUBatch **r_lverts, + struct GPUTexture **r_data_tex); void DRW_cache_mesh_normals_overlay_get( struct Object *ob, struct GPUBatch **r_tris, struct GPUBatch **r_ledges, struct GPUBatch **r_lverts); diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 27272769ec6..575670319d8 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -143,10 +143,12 @@ struct GPUBatch *DRW_mesh_batch_cache_get_fancy_edges(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_edge_detection(struct Mesh *me, bool *r_is_manifold); struct GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles_nor(struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_overlay_verts(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me); +struct GPUTexture *DRW_mesh_batch_cache_get_overlay_data_tex(struct Mesh *me); /* edit-mesh selection (use generic function for faces) */ struct GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(struct Mesh *me, uint select_id_offset); struct GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me, uint select_id_offset); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 3bcf5dd756a..6013c8eef91 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -1617,13 +1617,20 @@ static uchar mesh_render_data_vertex_flag(MeshRenderData *rdata, const BMVert *e } static void add_overlay_tri( - MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data, + MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data, GPUIndexBufBuilder *elb, const uint pos_id, const uint vnor_id, const uint lnor_id, const uint data_id, const BMLoop **bm_looptri, const int base_vert_idx) { uchar fflag; uchar vflag; + for (int i = 0; i < 3; ++i) { + if (!BM_elem_flag_test(bm_looptri[i]->v, BM_ELEM_TAG)) { + BM_elem_flag_enable(bm_looptri[i]->v, BM_ELEM_TAG); + GPU_indexbuf_add_generic_vert(elb, base_vert_idx + i); + } + } + if (vbo_pos) { /* TODO(sybren): deduplicate this and all the other places it's pasted to in this file. */ if (rdata->edit_data && rdata->edit_data->vertexCos) { @@ -1669,7 +1676,7 @@ static void add_overlay_tri( } } static void add_overlay_tri_mapped( - MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data, + MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data, GPUIndexBufBuilder *elb, const uint pos_id, const uint vnor_id, const uint lnor_id, const uint data_id, BMFace *efa, const MLoopTri *mlt, const float poly_normal[3], const int base_vert_idx) { @@ -1694,6 +1701,20 @@ static void add_overlay_tri_mapped( uchar fflag; uchar vflag; + if (elb) { + for (int i = 0; i < 3; ++i) { + const int v_orig = v_origindex[mloop[mlt->tri[i]].v]; + if (v_orig == ORIGINDEX_NONE) { + continue; + } + BMVert *v = BM_vert_at_index(bm, v_orig); + if (!BM_elem_flag_test(v, BM_ELEM_TAG)) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + GPU_indexbuf_add_generic_vert(elb, base_vert_idx + i); + } + } + } + if (vbo_pos) { for (uint i = 0; i < 3; i++) { const float *pos = mvert[mloop[mlt->tri[i]].v].co; @@ -1983,6 +2004,8 @@ typedef struct MeshBatchCache { GPUVertBuf *ed_tri_pos; GPUVertBuf *ed_tri_nor; /* LoopNor, VertNor */ GPUVertBuf *ed_tri_data; + GPUTexture *ed_tri_data_tx; + GPUIndexBuf *ed_tri_verts; GPUVertBuf *ed_ledge_pos; GPUVertBuf *ed_ledge_nor; /* VertNor */ @@ -2212,11 +2235,15 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) GPU_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel); /* Contains select flag */ GPU_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos); GPU_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos); + GPU_INDEXBUF_DISCARD_SAFE(cache->ed_tri_verts); + DRW_TEXTURE_FREE_SAFE(cache->ed_tri_data_tx); GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles); GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_verts); GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_edges); GPU_BATCH_DISCARD_SAFE(cache->overlay_facedots); + GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles_nor); + GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_edges_nor); /* Edit mode selection. */ GPU_BATCH_DISCARD_SAFE(cache->facedot_with_select_id); GPU_BATCH_DISCARD_SAFE(cache->edges_with_select_id); @@ -2313,11 +2340,13 @@ static void mesh_batch_cache_clear(Mesh *me) GPU_VERTBUF_DISCARD_SAFE(cache->ed_lvert_pos); GPU_VERTBUF_DISCARD_SAFE(cache->ed_lvert_nor); GPU_VERTBUF_DISCARD_SAFE(cache->ed_lvert_data); + GPU_INDEXBUF_DISCARD_SAFE(cache->ed_tri_verts); GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles); GPU_BATCH_DISCARD_SAFE(cache->overlay_triangles_nor); GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_verts); GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_edges); GPU_BATCH_DISCARD_SAFE(cache->overlay_loose_edges_nor); + DRW_TEXTURE_FREE_SAFE(cache->ed_tri_data_tx); GPU_BATCH_DISCARD_SAFE(cache->overlay_weight_faces); GPU_BATCH_DISCARD_SAFE(cache->overlay_weight_verts); @@ -3590,10 +3619,14 @@ static void mesh_batch_cache_create_overlay_tri_buffers( MeshRenderData *rdata, MeshBatchCache *cache) { BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI)); + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter; + BMVert *ev; const int tri_len = mesh_render_data_looptri_len_get_maybe_mapped(rdata); const int vbo_len_capacity = tri_len * 3; int vbo_len_used = 0; + int points_len = bm->totvert; /* Positions */ GPUVertBuf *vbo_pos = NULL; @@ -3620,12 +3653,24 @@ static void mesh_batch_cache_create_overlay_tri_buffers( GPU_vertbuf_data_alloc(vbo_data, vbo_len_capacity); } + /* Verts IBO */ + GPUIndexBufBuilder elb, *elbp = NULL; + if (cache->ed_tri_verts == NULL) { + elbp = &elb; + GPU_indexbuf_init(elbp, GPU_PRIM_POINTS, points_len, vbo_len_capacity); + } + + /* Clear tag */ + BM_ITER_MESH(ev, &iter, bm, BM_VERTS_OF_MESH) { + BM_elem_flag_disable(ev, BM_ELEM_TAG); + } + if (rdata->mapped.use == false) { for (int i = 0; i < tri_len; i++) { const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; if (!BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) { add_overlay_tri( - rdata, vbo_pos, vbo_nor, vbo_data, + rdata, vbo_pos, vbo_nor, vbo_data, elbp, attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data, bm_looptri, vbo_len_used); vbo_len_used += 3; @@ -3633,7 +3678,6 @@ static void mesh_batch_cache_create_overlay_tri_buffers( } } else { - BMesh *bm = rdata->edit_bmesh->bm; Mesh *me_cage = rdata->mapped.me_cage; const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me_cage); if (!CustomData_has_layer(&me_cage->pdata, CD_NORMAL)) { @@ -3649,7 +3693,7 @@ static void mesh_batch_cache_create_overlay_tri_buffers( BMFace *efa = BM_face_at_index(bm, p_orig); if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { add_overlay_tri_mapped( - rdata, vbo_pos, vbo_nor, vbo_data, + rdata, vbo_pos, vbo_nor, vbo_data, elbp, attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data, efa, mlt, polynors[mlt->poly], vbo_len_used); vbo_len_used += 3; @@ -3658,6 +3702,10 @@ static void mesh_batch_cache_create_overlay_tri_buffers( } } + if (elbp != NULL) { + cache->ed_tri_verts = GPU_indexbuf_build(elbp); + } + /* Finish */ if (vbo_len_used != vbo_len_capacity) { if (vbo_pos != NULL) { @@ -3670,6 +3718,10 @@ static void mesh_batch_cache_create_overlay_tri_buffers( GPU_vertbuf_data_resize(vbo_data, vbo_len_used); } } + + /* Upload data early because we need to create the texture for it. */ + GPU_vertbuf_use(vbo_data); + cache->ed_tri_data_tx = GPU_texture_create_from_vertbuf(vbo_data); } static void mesh_batch_cache_create_overlay_ledge_buffers( @@ -3876,6 +3928,19 @@ static GPUVertBuf *mesh_batch_cache_get_edit_lvert_pos( return cache->ed_lvert_pos; } +/* Indices */ +static GPUIndexBuf *mesh_batch_cache_get_edit_tri_indices( + MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & MR_DATATYPE_VERT); + + if (cache->ed_tri_verts == NULL) { + mesh_batch_cache_create_overlay_tri_buffers(rdata, cache); + } + + return cache->ed_tri_verts; +} + /* Normal */ static GPUVertBuf *mesh_batch_cache_get_edit_tri_nor( MeshRenderData *rdata, MeshBatchCache *cache) @@ -4902,16 +4967,20 @@ static void mesh_batch_cache_create_overlay_batches(Mesh *me) GPU_batch_vertbuf_add(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_data(rdata, cache)); } + /* Also used for vertices display */ if (cache->overlay_triangles_nor == NULL) { cache->overlay_triangles_nor = GPU_batch_create( - GPU_PRIM_POINTS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL); + GPU_PRIM_POINTS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), + mesh_batch_cache_get_edit_tri_indices(rdata, cache)); GPU_batch_vertbuf_add(cache->overlay_triangles_nor, mesh_batch_cache_get_edit_tri_nor(rdata, cache)); + GPU_batch_vertbuf_add(cache->overlay_triangles_nor, mesh_batch_cache_get_edit_tri_data(rdata, cache)); } if (cache->overlay_loose_edges_nor == NULL) { cache->overlay_loose_edges_nor = GPU_batch_create( GPU_PRIM_POINTS, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL); GPU_batch_vertbuf_add(cache->overlay_loose_edges_nor, mesh_batch_cache_get_edit_ledge_nor(rdata, cache)); + GPU_batch_vertbuf_add(cache->overlay_loose_edges_nor, mesh_batch_cache_get_edit_ledge_data(rdata, cache)); } mesh_render_data_free(rdata); @@ -4928,6 +4997,17 @@ GPUBatch *DRW_mesh_batch_cache_get_overlay_triangles(Mesh *me) return cache->overlay_triangles; } +GPUTexture *DRW_mesh_batch_cache_get_overlay_data_tex(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->ed_tri_data_tx == NULL) { + mesh_batch_cache_create_overlay_batches(me); + } + + return cache->ed_tri_data_tx; +} + GPUBatch *DRW_mesh_batch_cache_get_overlay_loose_edges(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c index aa19769bcac..609d6b2edb6 100644 --- a/source/blender/draw/modes/edit_mesh_mode.c +++ b/source/blender/draw/modes/edit_mesh_mode.c @@ -56,7 +56,7 @@ extern char datatoc_edit_mesh_overlay_frag_glsl[]; extern char datatoc_edit_mesh_overlay_vert_glsl[]; extern char datatoc_edit_mesh_overlay_geom_tri_glsl[]; extern char datatoc_edit_mesh_overlay_geom_edge_glsl[]; -extern char datatoc_edit_mesh_overlay_loosevert_vert_glsl[]; +extern char datatoc_edit_mesh_overlay_points_vert_glsl[]; extern char datatoc_edit_mesh_overlay_facedot_frag_glsl[]; extern char datatoc_edit_mesh_overlay_facedot_vert_glsl[]; extern char datatoc_edit_mesh_overlay_ghost_clear_vert_glsl[]; @@ -68,6 +68,8 @@ extern char datatoc_edit_normals_geom_glsl[]; extern char datatoc_common_globals_lib_glsl[]; extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; +extern char datatoc_gpu_shader_flat_color_frag_glsl[]; +extern char datatoc_gpu_shader_point_varying_color_frag_glsl[]; /* *********** LISTS *********** */ typedef struct EDIT_MESH_PassList { @@ -110,6 +112,7 @@ static struct { GPUShader *overlay_loose_edge_sh_cache[MAX_SHADERS]; GPUShader *overlay_vert_sh; + GPUShader *overlay_lvert_sh; GPUShader *overlay_facedot_sh; GPUShader *overlay_mix_sh; GPUShader *overlay_facefill_sh; @@ -133,11 +136,13 @@ typedef struct EDIT_MESH_PrivateData { DRWShadingGroup *lnormals_shgrp; DRWShadingGroup *face_overlay_shgrp; + DRWShadingGroup *verts_overlay_shgrp; DRWShadingGroup *ledges_overlay_shgrp; DRWShadingGroup *lverts_overlay_shgrp; DRWShadingGroup *facedot_overlay_shgrp; DRWShadingGroup *face_occluded_shgrp; + DRWShadingGroup *verts_occluded_shgrp; DRWShadingGroup *ledges_occluded_shgrp; DRWShadingGroup *lverts_occluded_shgrp; DRWShadingGroup *facedot_occluded_shgrp; @@ -182,7 +187,7 @@ static char *EDIT_MESH_sh_defines(ToolSettings *tsettings, RegionView3D *rv3d, b BLI_dynstr_append(ds, "#define FACE_SELECTION\n"); } - if (!fast_mode) { + if (!fast_mode || looseedge) { BLI_dynstr_append(ds, "#define EDGE_FIX\n"); } @@ -211,9 +216,11 @@ static char *EDIT_MESH_sh_lib(void) return str; } -static GPUShader *EDIT_MESH_ensure_shader(ToolSettings *tsettings, RegionView3D *rv3d, bool fast_mode, bool looseedge) +static GPUShader *EDIT_MESH_ensure_shader( + ToolSettings *tsettings, RegionView3D *rv3d, bool supports_fast_mode, bool looseedge) { - const int index = EDIT_MESH_sh_index(tsettings, rv3d, fast_mode); + const int index = EDIT_MESH_sh_index(tsettings, rv3d, supports_fast_mode); + const int fast_mode = rv3d->rflag & RV3D_NAVIGATING; if (looseedge) { if (!e_data.overlay_loose_edge_sh_cache[index]) { char *defines = EDIT_MESH_sh_defines(tsettings, rv3d, true, true); @@ -235,7 +242,7 @@ static GPUShader *EDIT_MESH_ensure_shader(ToolSettings *tsettings, RegionView3D char *lib = EDIT_MESH_sh_lib(); e_data.overlay_tri_sh_cache[index] = DRW_shader_create_with_lib( datatoc_edit_mesh_overlay_vert_glsl, - datatoc_edit_mesh_overlay_geom_tri_glsl, + fast_mode ? NULL : datatoc_edit_mesh_overlay_geom_tri_glsl, datatoc_edit_mesh_overlay_frag_glsl, lib, defines); @@ -273,10 +280,13 @@ static void EDIT_MESH_engine_init(void *vedata) if (!e_data.overlay_vert_sh) { char *lib = EDIT_MESH_sh_lib(); e_data.overlay_vert_sh = DRW_shader_create_with_lib( - datatoc_edit_mesh_overlay_loosevert_vert_glsl, NULL, - datatoc_edit_mesh_overlay_frag_glsl, - lib, - "#define VERTEX_SELECTION\n"); + datatoc_edit_mesh_overlay_points_vert_glsl, NULL, + datatoc_gpu_shader_point_varying_color_frag_glsl, lib, + "#define VERTEX_FACING\n"); + e_data.overlay_lvert_sh = DRW_shader_create_with_lib( + datatoc_edit_mesh_overlay_points_vert_glsl, NULL, + datatoc_gpu_shader_point_varying_color_frag_glsl, lib, + NULL); MEM_freeN(lib); } if (!e_data.overlay_facedot_sh) { @@ -328,7 +338,7 @@ static void EDIT_MESH_engine_init(void *vedata) static DRWPass *edit_mesh_create_overlay_pass( float *face_alpha, float *edge_width_scale, int *data_mask, bool do_edges, DRWState statemod, - DRWShadingGroup **r_face_shgrp, DRWShadingGroup **r_ledges_shgrp, + DRWShadingGroup **r_face_shgrp, DRWShadingGroup **r_verts_shgrp, DRWShadingGroup **r_ledges_shgrp, DRWShadingGroup **r_lverts_shgrp, DRWShadingGroup **r_facedot_shgrp) { GPUShader *tri_sh, *ledge_sh; @@ -360,10 +370,15 @@ static DRWPass *edit_mesh_create_overlay_pass( DRW_shgroup_uniform_bool_copy(*r_ledges_shgrp, "doEdges", do_edges); if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) { - *r_lverts_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, pass); + *r_lverts_shgrp = DRW_shgroup_create(e_data.overlay_lvert_sh, pass); DRW_shgroup_uniform_block(*r_lverts_shgrp, "globalsBlock", globals_ubo); DRW_shgroup_uniform_vec2(*r_lverts_shgrp, "viewportSize", DRW_viewport_size_get(), 1); DRW_shgroup_uniform_float(*r_lverts_shgrp, "edgeScale", edge_width_scale, 1); + + *r_verts_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, pass); + DRW_shgroup_uniform_block(*r_verts_shgrp, "globalsBlock", globals_ubo); + DRW_shgroup_uniform_vec2(*r_verts_shgrp, "viewportSize", DRW_viewport_size_get(), 1); + DRW_shgroup_uniform_float(*r_verts_shgrp, "edgeScale", edge_width_scale, 1); } if ((tsettings->selectmode & SCE_SELECT_FACE) != 0) { @@ -499,16 +514,22 @@ static void EDIT_MESH_cache_init(void *vedata) psl->edit_face_overlay = edit_mesh_create_overlay_pass( &face_mod, &stl->g_data->edge_width_scale, stl->g_data->data_mask, stl->g_data->do_edges, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND, - &stl->g_data->face_overlay_shgrp, &stl->g_data->ledges_overlay_shgrp, - &stl->g_data->lverts_overlay_shgrp, &stl->g_data->facedot_overlay_shgrp); + &stl->g_data->face_overlay_shgrp, + &stl->g_data->verts_overlay_shgrp, + &stl->g_data->ledges_overlay_shgrp, + &stl->g_data->lverts_overlay_shgrp, + &stl->g_data->facedot_overlay_shgrp); } else { /* We render all wires with depth and opaque to a new fbo and blend the result based on depth values */ psl->edit_face_occluded = edit_mesh_create_overlay_pass( &zero, &stl->g_data->edge_width_scale, stl->g_data->data_mask, stl->g_data->do_edges, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH, - &stl->g_data->face_occluded_shgrp, &stl->g_data->ledges_occluded_shgrp, - &stl->g_data->lverts_occluded_shgrp, &stl->g_data->facedot_occluded_shgrp); + &stl->g_data->face_occluded_shgrp, + &stl->g_data->verts_occluded_shgrp, + &stl->g_data->ledges_occluded_shgrp, + &stl->g_data->lverts_occluded_shgrp, + &stl->g_data->facedot_occluded_shgrp); /* however we loose the front faces value (because we need the depth of occluded wires and * faces are alpha blended ) so we recover them in a new pass. */ @@ -535,14 +556,24 @@ static void EDIT_MESH_cache_init(void *vedata) } static void edit_mesh_add_ob_to_pass( - Scene *scene, Object *ob, DRWShadingGroup *face_shgrp, DRWShadingGroup *ledges_shgrp, - DRWShadingGroup *lverts_shgrp, DRWShadingGroup *facedot_shgrp, DRWShadingGroup *facefill_shgrp) + Scene *scene, Object *ob, + DRWShadingGroup *face_shgrp, + DRWShadingGroup *verts_shgrp, + DRWShadingGroup *ledges_shgrp, + DRWShadingGroup *lverts_shgrp, + DRWShadingGroup *facedot_shgrp, + DRWShadingGroup *facefill_shgrp) { - struct GPUBatch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts, *geo_ovl_fcenter; + struct GPUBatch *geo_ovl_tris, *geo_ovl_verts, *geo_ovl_ledges, *geo_ovl_lverts, *geo_ovl_fcenter; + struct GPUTexture *data_texture; ToolSettings *tsettings = scene->toolsettings; - DRW_cache_mesh_wire_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts); + DRW_cache_mesh_wire_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts, &data_texture); + + face_shgrp = DRW_shgroup_create_sub(face_shgrp); + DRW_shgroup_uniform_texture(face_shgrp, "dataBuffer", data_texture); DRW_shgroup_call_add(face_shgrp, geo_ovl_tris, ob->obmat); + DRW_shgroup_call_add(ledges_shgrp, geo_ovl_ledges, ob->obmat); if (facefill_shgrp) { @@ -550,6 +581,10 @@ static void edit_mesh_add_ob_to_pass( } if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) { + /* Thoses are point batches. */ + DRW_cache_mesh_normals_overlay_get(ob, &geo_ovl_verts, &geo_ovl_ledges, &geo_ovl_lverts); + DRW_shgroup_call_add(verts_shgrp, geo_ovl_verts, ob->obmat); + DRW_shgroup_call_add(lverts_shgrp, geo_ovl_ledges, ob->obmat); DRW_shgroup_call_add(lverts_shgrp, geo_ovl_lverts, ob->obmat); } @@ -631,6 +666,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) edit_mesh_add_ob_to_pass( scene, ob, stl->g_data->face_occluded_shgrp, + stl->g_data->verts_occluded_shgrp, stl->g_data->ledges_occluded_shgrp, stl->g_data->lverts_occluded_shgrp, stl->g_data->facedot_occluded_shgrp, @@ -640,6 +676,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob) edit_mesh_add_ob_to_pass( scene, ob, stl->g_data->face_overlay_shgrp, + stl->g_data->verts_overlay_shgrp, stl->g_data->ledges_overlay_shgrp, stl->g_data->lverts_overlay_shgrp, (show_face_dots) ? stl->g_data->facedot_overlay_shgrp : NULL, @@ -727,6 +764,7 @@ static void EDIT_MESH_engine_free(void) DRW_SHADER_FREE_SAFE(e_data.weight_face_shader); DRW_SHADER_FREE_SAFE(e_data.overlay_vert_sh); + DRW_SHADER_FREE_SAFE(e_data.overlay_lvert_sh); DRW_SHADER_FREE_SAFE(e_data.overlay_facedot_sh); DRW_SHADER_FREE_SAFE(e_data.overlay_mix_sh); DRW_SHADER_FREE_SAFE(e_data.overlay_facefill_sh); diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl index bdf3ef267e9..b37862f2037 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl @@ -12,6 +12,10 @@ #define VERTEX_SELECTED (1 << 1) #define VERTEX_EXISTS (1 << 2) +#define FACE_ACTIVE (1 << 3) +#define FACE_SELECTED (1 << 4) +#define FACE_FREESTYLE (1 << 5) + uniform bool doEdges = true; vec4 EDIT_MESH_edge_color_outer(int edge_flag, bool face_active, float crease, float bweight) diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl index 92eb00d4dcc..31cebc84461 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl @@ -2,13 +2,6 @@ /* Solid Wirefram implementation * Mike Erwin, Clément Foucault */ -/* This shader follows the principles of - * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ - -/* This is not perfect. Only a subset of intel gpus are affected. - * This fix have some performance impact. - * TODO Refine the range to only affect GPUs. */ - uniform float faceAlphaMod; uniform float edgeScale; @@ -23,12 +16,12 @@ in vec3 vertexColor; in float facing; #endif -flat in vec2 ssPos[3]; +in vec3 barycentric; out vec4 FragColor; /* Vertex flag is shifted and combined with the edge flag */ -#define FACE_ACTIVE (1 << (3 + 8)) +#define FACE_ACTIVE_ (FACE_ACTIVE << 8) #define LARGE_EDGE_SIZE 3.0 @@ -61,12 +54,15 @@ void colorDistEdge(vec4 color, float dist) void main() { - vec3 e, p; - /* Step 1 : Computing Distances */ - distToEdgeAndPoint((ssPos[1] - ssPos[0]) + 1e-8, ssPos[0], e.z, p.x); - distToEdgeAndPoint((ssPos[2] - ssPos[1]) + 1e-8, ssPos[1], e.x, p.y); - distToEdgeAndPoint((ssPos[0] - ssPos[2]) + 1e-8, ssPos[2], e.y, p.z); + vec3 dx = dFdx(barycentric); + vec3 dy = dFdy(barycentric); + vec3 d = vec3( + length(vec2(dx.x, dy.x)), + length(vec2(dx.y, dy.y)), + length(vec2(dx.z, dy.z)) + ); + vec3 e = abs(vec3(barycentric / d)); /* Step 2 : coloring (order dependent) */ @@ -82,7 +78,7 @@ void main() /* Outer large edge */ float largeEdge = e[v] - sizeEdgeFinal * LARGE_EDGE_SIZE; - vec4 large_edge_color = EDIT_MESH_edge_color_outer(flag[v], (flag[0]& FACE_ACTIVE) != 0, edgesCrease[v], edgesBweight[v]); + vec4 large_edge_color = EDIT_MESH_edge_color_outer(flag[v], (flag[0] & FACE_ACTIVE_) != 0, edgesCrease[v], edgesBweight[v]); if (large_edge_color.a != 0.0) { colorDistEdge(large_edge_color, largeEdge); @@ -97,12 +93,13 @@ void main() #ifdef VERTEX_SELECTION colorDistEdge(vec4(vertexColor, 1.0), innerEdge); #else - vec4 inner_edge_color = EDIT_MESH_edge_color_inner(flag[v], (flag[0]& FACE_ACTIVE) != 0); + vec4 inner_edge_color = EDIT_MESH_edge_color_inner(flag[v], (flag[0] & FACE_ACTIVE_) != 0); colorDistEdge(inner_edge_color, innerEdge); #endif } } +#if 0 /* Points */ #ifdef VERTEX_SELECTION for (int v = 0; v < 3; ++v) { @@ -120,11 +117,11 @@ void main() } } #endif +#endif #ifdef VERTEX_FACING FragColor.a *= 1.0 - abs(facing) * 0.4; #endif - /* don't write depth if not opaque */ if (FragColor.a == 0.0) discard; } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl index 68fcc33acff..0368f170cb1 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl @@ -2,11 +2,8 @@ /* Solid Wirefram implementation * Mike Erwin, Clément Foucault */ -/* This shader follows the principles of - * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ - layout(lines) in; -layout(triangle_strip, max_vertices=6) out; +layout(triangle_strip, max_vertices=4) out; uniform mat4 ProjectionMatrix; uniform vec2 viewportSize; @@ -24,6 +21,7 @@ flat out vec3 edgesCrease; flat out vec3 edgesBweight; flat out vec4 faceColor; flat out ivec3 flag; +out vec3 barycentric; #ifdef VERTEX_SELECTION out vec3 vertexColor; #endif @@ -34,9 +32,6 @@ out float facing; /* See fragment shader */ flat out vec2 ssPos[3]; -#define FACE_ACTIVE (1 << 3) -#define FACE_SELECTED (1 << 4) - /* project to screen space */ vec2 proj(vec4 pos) { @@ -94,20 +89,21 @@ void main() ssPos[1] = pos[1]; flag[0] = flag[2] = (vData[0].x << 8); flag[1] = (vData[1].x << 8); - - doVertex(0, pPos[0] + vec4(-dirs1.xy, 0.0, 0.0)); + barycentric = vec3(1.0); doVertex(0, pPos[0] + vec4( dirs1.zw, 0.0, 0.0)); + + barycentric[2] = -1.0; doVertex(0, pPos[0] + vec4(-dirs1.zw, 0.0, 0.0)); flag[2] |= vData[0].y; edgesCrease[2] = vData[0].z / 255.0; edgesBweight[2] = vData[0].w / 255.0; + barycentric = vec3(1.0); doVertex(1, pPos[1] + vec4( dirs2.zw, 0.0, 0.0)); - doVertex(1, pPos[1] + vec4(-dirs2.zw, 0.0, 0.0)); - flag[2] = 0; - doVertex(1, pPos[1] + vec4( dirs2.xy, 0.0, 0.0)); + barycentric[2] = -1.0; + doVertex(1, pPos[1] + vec4(-dirs2.zw, 0.0, 0.0)); EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl index d020bcc6951..ccdf81bff7d 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl @@ -2,30 +2,14 @@ /* Solid Wirefram implementation * Mike Erwin, Clément Foucault */ -/* This shader follows the principles of - * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ - layout(triangles) in; -/* This is not perfect. Only a subset of intel gpus are affected. - * This fix have some performance impact. - * TODO Refine the range to only affect GPUs. */ - -#ifdef EDGE_FIX /* To fix the edge artifacts, we render * an outline strip around the screenspace * triangle. Order is important. * TODO diagram */ - -#ifdef VERTEX_SELECTION -layout(triangle_strip, max_vertices=23) out; -#else -layout(triangle_strip, max_vertices=17) out; -#endif -#else -layout(triangle_strip, max_vertices=3) out; -#endif +layout(triangle_strip, max_vertices=15) out; uniform mat4 ProjectionMatrix; uniform vec2 viewportSize; @@ -43,7 +27,8 @@ flat out vec3 edgesCrease; flat out vec3 edgesBweight; flat out vec4 faceColor; flat out ivec3 flag; -flat out int clipCase; + +out vec3 barycentric; #ifdef VERTEX_SELECTION out vec3 vertexColor; #endif @@ -51,13 +36,6 @@ out vec3 vertexColor; out float facing; #endif -/* See fragment shader */ -flat out vec2 ssPos[3]; - -#define FACE_ACTIVE (1 << 3) -#define FACE_SELECTED (1 << 4) -#define FACE_FREESTYLE (1 << 5) - /* project to screen space */ vec2 proj(vec4 pos) { @@ -73,8 +51,9 @@ void doVertex(int v) #ifdef VERTEX_FACING facing = vFacing[v]; #endif - gl_Position = pPos[v]; + barycentric = vec3(0.0); + barycentric[v % 3] = 1.0; EmitVertex(); } @@ -84,6 +63,7 @@ void doLoopStrip(int v, vec3 offset) doVertex(v); gl_Position.xyz += offset; + barycentric = vec3(1.0); EmitVertex(); } @@ -115,6 +95,7 @@ void main() faceColor = colorFace; /* Vertex */ + vec2 ssPos[3]; ssPos[0] = proj(pPos[0]); ssPos[1] = proj(pPos[1]); ssPos[2] = proj(pPos[2]); @@ -123,10 +104,8 @@ void main() doVertex(1); doVertex(2); -#ifdef EDGE_FIX vec2 fixvec[6]; vec2 fixvecaf[6]; - vec2 cornervec[3]; /* This fix the case when 2 vertices are perfectly aligned * and corner vectors have nowhere to go. @@ -150,8 +129,6 @@ void main() vec2 dir = normalize(v2 - v1); vec2 dir2 = normalize(v3 - v1); - cornervec[i] = -normalize(dir + dir2); - /* perpendicular to dir */ vec2 perp = vec2(-dir.y, dir.x); @@ -162,7 +139,6 @@ void main() /* Make it view independent */ perp *= sizeEdgeFix / viewportSize; - cornervec[i] *= sizeEdgeFix / viewportSize; fixvec[i] = fixvecaf[i] = perp; /* Perspective */ @@ -171,7 +147,6 @@ void main() * our fixvec to be flipped */ fixvec[i] *= -vPos[i].z; fixvecaf[i] *= -vPos[i1].z; - cornervec[i] *= -vPos[i].z; } } @@ -195,16 +170,6 @@ void main() flag[v] &= ~EDGE_EXISTS; doLoopStrip(vaf, vec3(fixvecaf[v], Z_OFFSET)); - /* corner vertices should not draw edges but draw point only */ - flag[vbe] &= ~EDGE_EXISTS; -#ifdef VERTEX_SELECTION - doLoopStrip(vaf, vec3(cornervec[vaf], Z_OFFSET)); -#endif + EndPrimitive(); } - - /* finish the loop strip */ - doLoopStrip(2, vec3(fixvec[2], Z_OFFSET)); -#endif - - EndPrimitive(); } diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl deleted file mode 100644 index 13d824c2410..00000000000 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl +++ /dev/null @@ -1,52 +0,0 @@ - -/* Solid Wirefram implementation - * Mike Erwin, Clément Foucault */ - -/* This shader follows the principles of - * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ - -uniform mat4 ModelViewProjectionMatrix; -uniform vec2 viewportSize; - -in vec3 pos; -in ivec4 data; - -/* these are the same for all vertices - * and does not need interpolation */ -flat out vec3 edgesCrease; -flat out vec3 edgesBweight; -flat out vec4 faceColor; -flat out ivec3 flag; -#ifdef VERTEX_SELECTION -out vec3 vertexColor; -#endif - -/* See fragment shader */ -flat out vec2 ssPos[3]; - -/* project to screen space */ -vec2 proj(vec4 pos) -{ - return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; -} - -void main() -{ - edgesCrease = vec3(0.0); - edgesBweight = vec3(0.0); - - vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); - - /* there is no face */ - faceColor = vec4(0.0); - -#ifdef VERTEX_SELECTION - vertexColor = vec3(0.0); -#endif - - ssPos[0] = ssPos[1] = ssPos[2] = proj(pPos); - flag[0] = flag[1] = flag[2] = (data.x << 8); - - gl_PointSize = sizeEdgeFix; - gl_Position = pPos; -} diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl new file mode 100644 index 00000000000..484a017e171 --- /dev/null +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_points_vert.glsl @@ -0,0 +1,41 @@ + +uniform mat3 NormalMatrix; +uniform mat4 ProjectionMatrix; +uniform mat4 ModelViewMatrix; +uniform mat4 ModelViewProjectionMatrix; +uniform float ofs = 5e-5; + +in vec3 pos; +in ivec4 data; +#ifdef VERTEX_FACING +in vec3 vnor; +#endif + +out vec4 finalColor; + +void main() +{ + finalColor = colorVertex; + finalColor = ((data.x & VERTEX_SELECTED) != 0) ? colorVertexSelect : finalColor; + finalColor = ((data.x & VERTEX_ACTIVE) != 0) ? vec4(colorEditMeshActive.xyz, 1.0) : finalColor; + + gl_PointSize = sizeVertex * 2.0; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position -= ofs; + +#ifdef VERTEX_FACING + vec4 vPos = ModelViewMatrix * vec4(pos, 1.0); + vec3 view_normal = normalize(NormalMatrix * vnor); + vec3 view_vec = (ProjectionMatrix[3][3] == 0.0) + ? normalize(vPos.xyz) + : vec3(0.0, 0.0, 1.0); + float facing = dot(view_vec, view_normal); + + finalColor.a *= 1.0 - abs(facing) * 0.4; +#endif + + if ((data.x & VERTEX_EXISTS) == 0) { + gl_Position = vec4(0.0); + gl_PointSize = 0.0; + } +} 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 7cab2a5035f..8715ab69181 100644 --- a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl +++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl @@ -2,38 +2,103 @@ /* Solid Wirefram implementation * Mike Erwin, Clément Foucault */ -/* This shader follows the principles of - * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */ - +uniform mat3 NormalMatrix; +uniform mat4 ProjectionMatrix; uniform mat4 ModelViewMatrix; uniform mat4 ModelViewProjectionMatrix; uniform ivec4 dataMask = ivec4(0xFF); +uniform float ofs = 1e-5; + +uniform isamplerBuffer dataBuffer; + in vec3 pos; +#ifdef VERTEX_FACING +in vec3 vnor; +#endif + +#ifdef EDGE_FIX in ivec4 data; out vec4 vPos; out vec4 pPos; out ivec4 vData; - -#ifdef VERTEX_FACING -uniform mat4 ProjectionMatrix; -uniform mat3 NormalMatrix; - -in vec3 vnor; +# ifdef VERTEX_FACING out float vFacing; -#endif +# endif void main() { vPos = ModelViewMatrix * vec4(pos, 1.0); pPos = ModelViewProjectionMatrix * vec4(pos, 1.0); + pPos.z -= ofs; vData = data & dataMask; -#ifdef VERTEX_FACING +# ifdef VERTEX_FACING vec3 view_normal = normalize(NormalMatrix * vnor); vec3 view_vec = (ProjectionMatrix[3][3] == 0.0) ? normalize(vPos.xyz) : vec3(0.0, 0.0, 1.0); vFacing = dot(view_vec, view_normal); -#endif +# endif } + +#else /* EDGE_FIX */ + +flat out vec3 edgesCrease; +flat out vec3 edgesBweight; +flat out vec4 faceColor; +flat out ivec3 flag; +# ifdef VERTEX_SELECTION +out vec3 vertexColor; +# endif +# ifdef VERTEX_FACING +out float facing; +# endif + +out vec3 barycentric; + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position.z -= ofs; + + int v_0 = (gl_VertexID / 3) * 3; + int vidx = gl_VertexID % 3; + barycentric = vec3(0.0); + barycentric[vidx] = 1.0; + + /* Edge */ + ivec4 vData[3], data = ivec4(0); + ivec3 eflag; + for (int v = 0; v < 3; ++v) { + data = texelFetch(dataBuffer, v_0 + v); + vData[v] = data & dataMask; + flag[v] = eflag[v] = vData[v].y | (vData[v].x << 8); + edgesCrease[v] = vData[v].z / 255.0; + edgesBweight[v] = vData[v].w / 255.0; + } + + /* Face */ + if ((vData[0].x & FACE_ACTIVE) != 0) + faceColor = colorFaceSelect; + else if ((vData[0].x & FACE_SELECTED) != 0) + faceColor = colorFaceSelect; + else if ((vData[0].x & FACE_FREESTYLE) != 0) + faceColor = colorFaceFreestyle; + else + faceColor = colorFace; + +# ifdef VERTEX_SELECTION + vertexColor = EDIT_MESH_vertex_color(vData[vidx].x).rgb; +# endif +# ifdef VERTEX_FACING + vec4 vPos = ModelViewMatrix * vec4(pos, 1.0); + vec3 view_normal = normalize(NormalMatrix * vnor); + vec3 view_vec = (ProjectionMatrix[3][3] == 0.0) + ? normalize(vPos.xyz) + : vec3(0.0, 0.0, 1.0); + facing = dot(view_vec, view_normal); +# endif +} + +#endif
\ No newline at end of file |