Edit Mesh: Refactor edit mesh drawing

This decouple the vertex display from the face+edges.

This is to reduce the number of triangles required to fix the edges
artifacts (aliasing) and increase viewport reactivity when not actively
navigating (ie. mouse scroll).

Also it makes all vertices visible (not cut-off) even when navigating.

However it makes the navigation drawing a bit slower because it has to
render twice.

Also add a depth bias to the wires to avoid depth fighting when previewing
final mesh (modifiers applied).
This commit is contained in:
Clément Foucault 2018-10-12 15:09:43 +02:00
parent fe4840ed4d
commit 03d0219d7a
13 changed files with 303 additions and 164 deletions

View File

@ -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)

View File

@ -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(

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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