Wireframe: Refactor to use GL_LINES instead of triangles with alpha blend

This gets rid of the progressive fading of the edges as it does not work
with depth perception (sorting problem with alpha blending).
This commit is contained in:
Clément Foucault 2019-02-12 23:22:36 +01:00
parent 253ff57617
commit e49d955541
Notes: blender-bot 2023-02-14 04:11:24 +01:00
Referenced by issue #60180, Can't select plane objects after changing Display As setting to Wire.
4 changed files with 252 additions and 127 deletions

View File

@ -1176,7 +1176,7 @@ static int mesh_render_data_loose_verts_len_get_maybe_mapped(const MeshRenderDat
return ((rdata->mapped.use == false) ? rdata->loose_vert_len : rdata->mapped.loose_vert_len);
}
static int UNUSED_FUNCTION(mesh_render_data_edges_len_get)(const MeshRenderData *rdata)
static int mesh_render_data_edges_len_get(const MeshRenderData *rdata)
{
BLI_assert(rdata->types & MR_DATATYPE_EDGE);
return rdata->edge_len;
@ -1750,6 +1750,7 @@ typedef struct MeshBatchCache {
GPUVertBuf *loop_pos_nor;
GPUVertBuf *loop_uv_tan;
GPUVertBuf *loop_vcol;
GPUVertBuf *loop_edge_fac;
} ordered;
/* Tesselated: (all verts specified for each triangles).
@ -1795,13 +1796,14 @@ typedef struct MeshBatchCache {
/* Indices to vloops. */
GPUIndexBuf *loops_tris;
GPUIndexBuf *loops_lines;
GPUIndexBuf *loops_line_strips;
/* Edit mode. */
GPUIndexBuf *edit_loops_points; /* verts */
GPUIndexBuf *edit_loops_lines; /* edges */
GPUIndexBuf *edit_loops_tris; /* faces */
/* Edit UVs */
GPUIndexBuf *edituv_loops_points; /* verts */
GPUIndexBuf *edituv_loops_lines; /* edges */
GPUIndexBuf *edituv_loops_line_strips; /* edges */
GPUIndexBuf *edituv_loops_tri_fans; /* faces */
} ibo;
@ -1832,6 +1834,7 @@ typedef struct MeshBatchCache {
GPUBatch *all_edges;
GPUBatch *loose_edges;
GPUBatch *edge_detection;
GPUBatch *wire_edges; /* Individual edges with face normals. */
GPUBatch *wire_loops; /* Loops around faces. */
GPUBatch *wire_loops_uvs; /* Same as wire_loops but only has uvs. */
GPUBatch *wire_triangles; /* Triangles for object mode wireframe. */
@ -1998,7 +2001,7 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_uv);
GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_uv_data);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_tri_fans);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_lines);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_line_strips);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_points);
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_strech_area);
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_strech_angle);
@ -2847,6 +2850,115 @@ static void mesh_create_weights(MeshRenderData *rdata, GPUVertBuf *vbo, DRW_Mesh
GPU_vertbuf_attr_fill(vbo, attr_id.weight, vert_weight);
}
static float mesh_loop_edge_factor_get(
const float f_no[3], const float v_co[3], const float v_no[3], const float v_next_co[3])
{
float enor[3], evec[3];
sub_v3_v3v3(evec, v_next_co, v_co);
cross_v3_v3v3(enor, v_no, evec);
normalize_v3(enor);
float d = fabsf(dot_v3v3(enor, f_no));
/* Rescale to the slider range. */
d *= (1.0f / 0.065f);
CLAMP(d, 0.0f, 1.0f);
return d;
}
static void mesh_create_loop_edge_fac(MeshRenderData *rdata, GPUVertBuf *vbo)
{
static GPUVertFormat format = { 0 };
static struct { uint wd; } attr_id;
if (format.attr_len == 0) {
attr_id.wd = GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
}
const int poly_len = mesh_render_data_polys_len_get(rdata);
const int loop_len = mesh_render_data_loops_len_get(rdata);
const int edge_len = mesh_render_data_edges_len_get(rdata);
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, loop_len);
GPUVertBufRaw wd_step;
GPU_vertbuf_attr_get_raw_data(vbo, attr_id.wd, &wd_step);
if (rdata->mapped.use == false) {
if (rdata->edit_bmesh) {
BMesh *bm = rdata->edit_bmesh->bm;
BMIter iter_efa, iter_loop;
BMFace *efa;
BMLoop *loop;
uint f;
BM_ITER_MESH_INDEX (efa, &iter_efa, bm, BM_FACES_OF_MESH, f) {
BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) {
float ratio = mesh_loop_edge_factor_get(efa->no, loop->v->co, loop->v->no, loop->next->v->co);
*((uchar *)GPU_vertbuf_raw_step(&wd_step)) = ratio * 255;
}
}
BLI_assert(GPU_vertbuf_raw_used(&wd_step) == loop_len);
}
else {
const MVert *mvert = rdata->mvert;
const MPoly *mpoly = rdata->mpoly;
const MLoop *mloop = rdata->mloop;
MEdge *medge = (MEdge *)rdata->medge;
bool use_edge_render = false;
/* TODO(fclem) We don't need them to be packed. But we need rdata->poly_normals */
mesh_render_data_ensure_poly_normals_pack(rdata);
/* Reset flag */
for (int edge = 0; edge < edge_len; ++edge) {
/* NOTE: not thread safe. */
medge[edge].flag &= ~ME_EDGE_TMP_TAG;
/* HACK(fclem) Feels like a hack. Detecting the need for edge render. */
if ((medge[edge].flag & ME_EDGERENDER) == 0) {
use_edge_render = true;
}
}
for (int a = 0; a < poly_len; a++, mpoly++) {
const float *fnor = rdata->poly_normals[a];
for (int b = 0; b < mpoly->totloop; b++) {
const MLoop *ml1 = &mloop[mpoly->loopstart + b];
const MLoop *ml2 = &mloop[mpoly->loopstart + (b + 1) % mpoly->totloop];
/* Will only work for edges that have an odd number of faces connected. */
MEdge *ed = (MEdge *)rdata->medge + ml1->e;
ed->flag ^= ME_EDGE_TMP_TAG;
if (use_edge_render) {
*((uchar *)GPU_vertbuf_raw_step(&wd_step)) = (ed->flag & ME_EDGERENDER) ? 255 : 0;
}
else {
float vnor_f[3];
normal_short_to_float_v3(vnor_f, mvert[ml1->v].no);
float ratio = mesh_loop_edge_factor_get(fnor,
mvert[ml1->v].co,
vnor_f,
mvert[ml2->v].co);
*((uchar *)GPU_vertbuf_raw_step(&wd_step)) = ratio * 253 + 1;
}
}
}
/* Gather non-manifold edges. */
for (int l = 0; l < loop_len; l++, mloop++) {
MEdge *ed = (MEdge *)rdata->medge + mloop->e;
if (ed->flag & ME_EDGE_TMP_TAG) {
uchar data = 255;
GPU_vertbuf_attr_set(vbo, attr_id.wd, l, &data);
}
}
BLI_assert(loop_len == GPU_vertbuf_raw_used(&wd_step));
}
}
else {
BLI_assert(0);
}
}
static void mesh_create_loop_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo)
{
/* TODO deduplicate format creation*/
@ -3603,6 +3715,72 @@ static void mesh_create_surf_tris(MeshRenderData *rdata, GPUIndexBuf *ibo, const
static void mesh_create_loops_lines(
MeshRenderData *rdata, GPUIndexBuf *ibo, const bool use_hide)
{
const int edge_len = mesh_render_data_edges_len_get(rdata);
const int loop_len = mesh_render_data_loops_len_get(rdata);
const int poly_len = mesh_render_data_polys_len_get(rdata);
GPUIndexBufBuilder elb;
GPU_indexbuf_init(&elb, GPU_PRIM_LINES, edge_len, loop_len);
if (rdata->mapped.use == false) {
if (rdata->edit_bmesh) {
BMesh *bm = rdata->edit_bmesh->bm;
BMIter iter;
BMEdge *bm_edge;
BM_ITER_MESH (bm_edge, &iter, bm, BM_EDGES_OF_MESH) {
/* use_hide always for edit-mode */
if (!BM_elem_flag_test(bm_edge, BM_ELEM_HIDDEN) &&
bm_edge->l != NULL)
{
BMLoop *bm_loop1 = BM_vert_find_first_loop(bm_edge->v1);
BMLoop *bm_loop2 = BM_vert_find_first_loop(bm_edge->v2);
int v1 = BM_elem_index_get(bm_loop1);
int v2 = BM_elem_index_get(bm_loop2);
if (v1 > v2) {
SWAP(int, v1, v2);
}
GPU_indexbuf_add_line_verts(&elb, v1, v2);
}
}
}
else {
MLoop *mloop = (MLoop *)rdata->mloop;
MEdge *medge = (MEdge *)rdata->medge;
/* Reset flag */
for (int edge = 0; edge < edge_len; ++edge) {
/* NOTE: not thread safe. */
medge[edge].flag &= ~ME_EDGE_TMP_TAG;
}
for (int poly = 0; poly < poly_len; poly++) {
const MPoly *mp = &rdata->mpoly[poly];
if (!(use_hide && (mp->flag & ME_HIDE))) {
for (int j = 0; j < mp->totloop; j++) {
MEdge *ed = (MEdge *)rdata->medge + mloop[mp->loopstart + j].e;
if ((ed->flag & ME_EDGE_TMP_TAG) == 0) {
ed->flag |= ME_EDGE_TMP_TAG;
int v1 = mp->loopstart + j;
int v2 = mp->loopstart + (j + 1) % mp->totloop;
GPU_indexbuf_add_line_verts(&elb, v1, v2);
}
}
}
}
}
}
else {
/* Implement ... eventually if needed. */
BLI_assert(0);
}
GPU_indexbuf_build_in_place(&elb, ibo);
}
static void mesh_create_loops_line_strips(
MeshRenderData *rdata, GPUIndexBuf *ibo, const bool use_hide)
{
const int loop_len = mesh_render_data_loops_len_get(rdata);
const int poly_len = mesh_render_data_polys_len_get(rdata);
@ -4125,7 +4303,7 @@ GPUBatch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold)
GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
return DRW_batch_request(&cache->batch.wire_triangles);
return DRW_batch_request(&cache->batch.wire_edges);
}
GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(
@ -4705,7 +4883,7 @@ void DRW_mesh_batch_cache_create_requested(
GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_uv);
GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_uv);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_tri_fans);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_lines);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_line_strips);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_points);
/* We only clear the batches as they may already have been referenced. */
GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_area);
@ -4750,11 +4928,16 @@ void DRW_mesh_batch_cache_create_requested(
DRW_vbo_request(cache->batch.surface_weights, &cache->ordered.weights);
}
if (DRW_batch_requested(cache->batch.wire_loops, GPU_PRIM_LINE_STRIP)) {
DRW_ibo_request(cache->batch.wire_loops, &cache->ibo.loops_lines);
DRW_ibo_request(cache->batch.wire_loops, &cache->ibo.loops_line_strips);
DRW_vbo_request(cache->batch.wire_loops, &cache->ordered.loop_pos_nor);
}
if (DRW_batch_requested(cache->batch.wire_edges, GPU_PRIM_LINES)) {
DRW_ibo_request(cache->batch.wire_edges, &cache->ibo.loops_lines);
DRW_vbo_request(cache->batch.wire_edges, &cache->ordered.loop_pos_nor);
DRW_vbo_request(cache->batch.wire_edges, &cache->ordered.loop_edge_fac);
}
if (DRW_batch_requested(cache->batch.wire_loops_uvs, GPU_PRIM_LINE_STRIP)) {
DRW_ibo_request(cache->batch.wire_loops_uvs, &cache->ibo.loops_lines);
DRW_ibo_request(cache->batch.wire_loops_uvs, &cache->ibo.loops_line_strips);
/* For paint overlay. Active layer should have been queried. */
if (cache->cd_lused[CD_MLOOPUV] != 0) {
DRW_vbo_request(cache->batch.wire_loops_uvs, &cache->ordered.loop_uv_tan);
@ -4809,7 +4992,7 @@ void DRW_mesh_batch_cache_create_requested(
DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &cache->edit.loop_stretch_angle);
}
if (DRW_batch_requested(cache->batch.edituv_edges, GPU_PRIM_LINES)) {
DRW_ibo_request(cache->batch.edituv_edges, &cache->ibo.edituv_loops_lines);
DRW_ibo_request(cache->batch.edituv_edges, &cache->ibo.edituv_loops_line_strips);
DRW_vbo_request(cache->batch.edituv_edges, &cache->edit.loop_uv);
DRW_vbo_request(cache->batch.edituv_edges, &cache->edit.loop_uv_data);
}
@ -4877,11 +5060,13 @@ void DRW_mesh_batch_cache_create_requested(
DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_pos_nor, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP);
DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_uv_tan, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_SHADING);
DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_vcol, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_SHADING);
DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_edge_fac, MR_DATATYPE_POLY | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP);
DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->tess.pos_nor, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI | MR_DATATYPE_POLY);
DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->tess.wireframe_data, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.surf_tris, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.loops_tris, MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.loops_lines, MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.loops_lines, MR_DATATYPE_LOOP | MR_DATATYPE_EDGE | MR_DATATYPE_POLY);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.loops_line_strips, MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edges_lines, MR_DATATYPE_VERT | MR_DATATYPE_EDGE);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edges_adj_lines, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.loose_edges_lines, MR_DATATYPE_VERT | MR_DATATYPE_EDGE);
@ -4906,7 +5091,7 @@ void DRW_mesh_batch_cache_create_requested(
DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.facedots_uv, combined_edit_flag | MR_DATATYPE_LOOPUV);
DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.facedots_uv_data, combined_edit_flag);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, cache->ibo.edituv_loops_points, combined_edit_flag);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, cache->ibo.edituv_loops_lines, combined_edit_flag);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, cache->ibo.edituv_loops_line_strips, combined_edit_flag);
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, cache->ibo.edituv_loops_tri_fans, combined_edit_flag);
/* TODO: Some of the flags here may not be needed. */
DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, cache->ibo.edit_loops_points, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI);
@ -4936,6 +5121,9 @@ void DRW_mesh_batch_cache_create_requested(
if (DRW_vbo_requested(cache->ordered.loop_pos_nor)) {
mesh_create_loop_pos_and_nor(rdata, cache->ordered.loop_pos_nor);
}
if (DRW_vbo_requested(cache->ordered.loop_edge_fac)) {
mesh_create_loop_edge_fac(rdata, cache->ordered.loop_edge_fac);
}
if (DRW_vbo_requested(cache->ordered.loop_uv_tan)) {
mesh_create_loop_uv_and_tan(rdata, cache->ordered.loop_uv_tan);
}
@ -4963,6 +5151,9 @@ void DRW_mesh_batch_cache_create_requested(
if (DRW_ibo_requested(cache->ibo.loops_lines)) {
mesh_create_loops_lines(rdata, cache->ibo.loops_lines, use_hide);
}
if (DRW_ibo_requested(cache->ibo.loops_line_strips)) {
mesh_create_loops_line_strips(rdata, cache->ibo.loops_line_strips, use_hide);
}
if (DRW_ibo_requested(cache->ibo.loops_tris)) {
mesh_create_loops_tris(rdata, &cache->ibo.loops_tris, 1, use_hide);
}
@ -5042,14 +5233,14 @@ void DRW_mesh_batch_cache_create_requested(
DRW_vbo_requested(cache->edit.facedots_uv) ||
DRW_vbo_requested(cache->edit.facedots_uv_data) ||
DRW_ibo_requested(cache->ibo.edituv_loops_points) ||
DRW_ibo_requested(cache->ibo.edituv_loops_lines) ||
DRW_ibo_requested(cache->ibo.edituv_loops_line_strips) ||
DRW_ibo_requested(cache->ibo.edituv_loops_tri_fans))
{
mesh_create_uvedit_buffers(rdata,
cache->edit.loop_stretch_area, cache->edit.loop_stretch_angle,
cache->edit.facedots_uv, cache->edit.facedots_uv_data,
cache->ibo.edituv_loops_points,
cache->ibo.edituv_loops_lines,
cache->ibo.edituv_loops_line_strips,
cache->ibo.edituv_loops_tri_fans);
}

View File

@ -55,7 +55,7 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *flat_wires_shgrp;
DRWShadingGroup *sculpt_wires_shgrp;
View3DOverlay overlay;
float wire_step_param[2];
float wire_step_param;
bool ghost_stencil_test;
bool show_overlays;
} OVERLAY_PrivateData; /* Transient data */
@ -127,9 +127,8 @@ static void overlay_engine_init(void *vedata)
});
sh_data->face_wireframe_sculpt = 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, "#define USE_SCULPT\n", NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
}
}
@ -179,7 +178,7 @@ static void overlay_cache_init(void *vedata)
{
/* Wireframe */
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_FIRST_VERTEX_CONVENTION;
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;
const bool use_select = (DRW_state_is_select() || DRW_state_is_depth());
@ -200,7 +199,7 @@ static void overlay_cache_init(void *vedata)
}
g_data->face_wires_shgrp = DRW_shgroup_create(face_wires_sh, psl->face_wireframe_pass);
DRW_shgroup_uniform_vec2(g_data->face_wires_shgrp, "wireStepParam", g_data->wire_step_param, 1);
DRW_shgroup_uniform_float(g_data->face_wires_shgrp, "wireStepParam", &g_data->wire_step_param, 1);
if (rv3d->rflag & RV3D_CLIPPING) {
DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_wires_shgrp, rv3d);
}
@ -210,14 +209,7 @@ static void overlay_cache_init(void *vedata)
DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "wireSize", wire_size);
}
/* Control aspect of the falloff. */
const float sharpness = 4.0f;
/* Scale and bias: Adjust with wiredata encoding. (see mesh_batch_cache_create_edges_wireframe_data) */
const float decompress = (0xFF / (float)(0xFF - 0x20));
g_data->wire_step_param[0] = -sharpness * decompress;
g_data->wire_step_param[1] = decompress + sharpness * stl->g_data->overlay.wireframe_threshold;
g_data->wire_step_param = stl->g_data->overlay.wireframe_threshold - 254.0f / 255.0f;
}
}
@ -227,7 +219,6 @@ static void overlay_cache_populate(void *vedata, Object *ob)
OVERLAY_StorageList *stl = data->stl;
OVERLAY_PrivateData *pd = stl->g_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
RegionView3D *rv3d = draw_ctx->rv3d;
View3D *v3d = draw_ctx->v3d;
if ((!pd->show_overlays) ||
@ -266,14 +257,14 @@ static void overlay_cache_populate(void *vedata, Object *ob)
{
const bool is_active = (ob == draw_ctx->obact);
const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
const bool all_wires = (pd->overlay.wireframe_threshold == 1.0f) ||
(ob->dtx & OB_DRAW_ALL_EDGES);
const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES);
const bool is_wire = (ob->dt < OB_SOLID);
const int stencil_mask = (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF;
DRWShadingGroup *shgrp = NULL;
const float *rim_col = NULL;
const float *wire_col = NULL;
if (UNLIKELY(ob->base_flag & BASE_FROM_SET)) {
rim_col = G_draw.block.colorDupli;
wire_col = G_draw.block.colorDupli;
@ -312,47 +303,29 @@ static void overlay_cache_populate(void *vedata, Object *ob)
}
BLI_assert(rim_col && wire_col);
/* This fixes only the biggest case which is a plane in ortho view. */
int flat_axis = 0;
bool is_flat_object_viewed_from_side = (
(rv3d->persp == RV3D_ORTHO) &&
DRW_object_is_flat(ob, &flat_axis) &&
DRW_object_axis_orthogonal_to_view(ob, flat_axis));
struct GPUBatch *geom;
geom = DRW_cache_object_face_wireframe_get(ob);
if (is_flat_object_viewed_from_side && !is_sculpt_mode) {
/* Avoid losing flat objects when in ortho views (see T56549) */
struct GPUBatch *geom = DRW_cache_object_all_edges_get(ob);
if (geom) {
shgrp = pd->flat_wires_shgrp;
shgrp = DRW_shgroup_create_sub(shgrp);
if (geom || is_sculpt_mode) {
shgrp = (is_sculpt_mode) ? pd->sculpt_wires_shgrp : pd->face_wires_shgrp;
shgrp = DRW_shgroup_create_sub(shgrp);
static float all_wires_param = 10.0f;
DRW_shgroup_uniform_vec2(
shgrp, "wireStepParam", (all_wires) ?
&all_wires_param : &pd->wire_step_param, 1);
if (!(DRW_state_is_select() || DRW_state_is_depth())) {
DRW_shgroup_stencil_mask(shgrp, stencil_mask);
DRW_shgroup_call_object_add(shgrp, geom, ob);
DRW_shgroup_uniform_vec4(shgrp, "color", rim_col, 1);
DRW_shgroup_uniform_vec3(shgrp, "wireColor", wire_col, 1);
DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1);
}
}
else {
struct GPUBatch *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);
static float all_wires_params[2] = {0.0f, 10.0f}; /* Parameters for all wires */
DRW_shgroup_uniform_vec2(
shgrp, "wireStepParam", (all_wires) ?
all_wires_params : pd->wire_step_param, 1);
if (!(DRW_state_is_select() || DRW_state_is_depth())) {
DRW_shgroup_stencil_mask(shgrp, stencil_mask);
DRW_shgroup_uniform_vec3(shgrp, "wireColor", wire_col, 1);
DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1);
}
if (is_sculpt_mode) {
DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat);
}
else {
DRW_shgroup_call_add(shgrp, geom, ob->obmat);
}
if (is_sculpt_mode) {
DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat);
}
else {
DRW_shgroup_call_add(shgrp, geom, ob->obmat);
}
}
if (is_wire && shgrp != NULL) {
@ -392,12 +365,18 @@ static void overlay_draw_scene(void *vedata)
OVERLAY_Data *data = vedata;
OVERLAY_PassList *psl = data->psl;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
if (DRW_state_is_fbo()) {
GPU_framebuffer_bind(dfbl->default_fb);
}
DRW_draw_pass(psl->face_orientation_pass);
MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl);
DRW_draw_pass(psl->face_wireframe_pass);
MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl);
}
static void overlay_engine_free(void)

View File

@ -1,41 +1,23 @@
uniform vec3 wireColor;
uniform vec3 rimColor;
flat in float edgeSharpness;
in float facing;
in vec3 barycentric;
flat in vec3 edgeSharpness;
out vec4 fragColor;
float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); }
/* In pixels */
uniform float wireSize = 0.0; /* Expands the core of the wire (part that is 100% wire color) */
const float wire_smooth = 1.2; /* Smoothing distance after the 100% core. */
/* Alpha constants could be exposed in the future. */
const float front_alpha = 0.35;
const float rim_alpha = 0.75;
void main()
{
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 dist_to_edge = barycentric / d;
if (edgeSharpness < 0.0) {
discard;
}
vec3 fac = abs(dist_to_edge);
float facing_clamped = clamp(abs(facing), 0.0, 1.0);
fac = smoothstep(wireSize + wire_smooth, wireSize, fac);
vec3 final_front_col = mix(rimColor, wireColor, 0.4);
vec3 final_rim_col = mix(rimColor, wireColor, 0.1);
float facing_clamped = clamp((gl_FrontFacing) ? facing : -facing, 0.0, 1.0);
vec3 final_front_col = mix(rimColor, wireColor, 0.05);
fragColor = mix(vec4(rimColor, rim_alpha), vec4(final_front_col, front_alpha), facing_clamped);
fragColor.a *= max_v3(fac * edgeSharpness);
fragColor.rgb = mix(final_rim_col, final_front_col, facing_clamped);
fragColor.a = 1.0f;
}

View File

@ -3,22 +3,11 @@ uniform mat4 ModelViewProjectionMatrix;
uniform mat4 ModelMatrix;
uniform mat3 NormalMatrix;
uniform vec2 wireStepParam;
vec3 get_edge_sharpness(vec3 wd)
{
bvec3 do_edge = greaterThan(wd, vec3(0.0));
bvec3 force_edge = equal(wd, vec3(1.0));
wd = clamp(wireStepParam.x * wd + wireStepParam.y, 0.0, 1.0);
return clamp(wd * vec3(do_edge) + vec3(force_edge), 0.0, 1.0);
}
uniform float wireStepParam;
float get_edge_sharpness(float wd)
{
bool do_edge = (wd > 0.0);
bool force_edge = (wd == 1.0);
wd = (wireStepParam.x * wd + wireStepParam.y);
return clamp(wd * float(do_edge) + float(force_edge), 0.0, 1.0);
return (wd == 1.0) ? 1.0 : ((wd == 0.0) ? -1.0 : (wd + wireStepParam));
}
/* Geometry shader version */
@ -51,35 +40,19 @@ void main()
#else /* SELECT_EDGES */
/* Consecutive pos of the nth vertex
* Only valid for first vertex in the triangle.
* Assuming GL_FRIST_VERTEX_CONVENTION. */
in vec3 pos0;
in vec3 pos1;
in vec3 pos2;
in float wd0; /* wiredata */
in float wd1;
in float wd2;
in vec3 pos;
in vec3 nor;
in float wd;
out float facing;
out vec3 barycentric;
flat out vec3 edgeSharpness;
flat out float edgeSharpness;
void main()
{
int v_n = gl_VertexID % 3;
barycentric = vec3(equal(ivec3(2, 0, 1), ivec3(v_n)));
vec3 wb = vec3(wd0, wd1, wd2);
edgeSharpness = get_edge_sharpness(wb);
/* Don't generate any fragment if there is no edge to draw. */
vec3 pos = (!any(greaterThan(edgeSharpness, vec3(0.04))) && (v_n == 0)) ? pos1 : pos0;
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
edgeSharpness = get_edge_sharpness(wd);
facing = normalize(NormalMatrix * nor).z;
#ifdef USE_WORLD_CLIP_PLANES