Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py8
-rw-r--r--source/blender/blenloader/intern/versioning_280.c12
-rw-r--r--source/blender/draw/intern/draw_cache.c11
-rw-r--r--source/blender/draw/intern/draw_cache.h2
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c151
-rw-r--r--source/blender/draw/modes/overlay_mode.c54
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl21
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl34
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl68
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c1
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_space.c8
13 files changed, 342 insertions, 33 deletions
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 4d680477151..1a70092eb21 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -3573,7 +3573,13 @@ class VIEW3D_PT_overlay(Panel):
col.prop(overlay, "show_relationship_lines")
col.prop(overlay, "show_motion_paths")
col.prop(overlay, "show_face_orientation")
- col.prop(overlay, "show_wireframes")
+
+ row = col.row()
+ row.prop(overlay, "show_wireframes")
+ sub = row.row()
+ sub.active = overlay.show_wireframes
+ sub.prop(overlay, "wireframe_threshold", text="")
+
col.prop(overlay, "show_backface_culling")
if shading.type == "MATERIAL":
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 37f308daa3a..cbfcce963e3 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -1553,5 +1553,17 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "wireframe_threshold")) {
+ for (bScreen *screen = main->screen.first; screen; screen = screen->id.next) {
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ v3d->overlay.wireframe_threshold = 0.5f;
+ }
+ }
+ }
+ }
+ }
}
}
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 14addfe9bcb..d6cea03d573 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -526,6 +526,17 @@ void DRW_cache_object_face_wireframe_get(
}
}
+void DRW_cache_object_face_wireframe_pretty_get(
+ Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count)
+{
+ switch (ob->type) {
+ case OB_MESH:
+ DRW_mesh_batch_cache_get_pretty_wireframes_face_texbuf((Mesh *)ob->data, r_vert_tx, r_faceid_tx, r_tri_count);
+
+ /* TODO, should match 'DRW_cache_object_surface_get' */
+ }
+}
+
Gwn_Batch *DRW_cache_object_loose_edges_get(struct Object *ob)
{
switch (ob->type) {
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 7a1c14b5076..705192653f5 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -56,6 +56,8 @@ struct Gwn_Batch **DRW_cache_object_surface_material_get(
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
void DRW_cache_object_face_wireframe_get(
Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
+void DRW_cache_object_face_wireframe_pretty_get(
+ Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count);
/* Empties */
struct Gwn_Batch *DRW_cache_plain_axes_get(void);
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 0f990c72d01..2824021bb29 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -126,6 +126,8 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me,
/* Object mode Wireframe overlays */
void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
struct Mesh *me, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count);
+void DRW_mesh_batch_cache_get_pretty_wireframes_face_texbuf(
+ struct Mesh *me, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count);
void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index e6dde8adc97..fa78e143e98 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -112,6 +112,10 @@ typedef struct EdgeAdjacentPolys {
int face_index[2];
} EdgeAdjacentPolys;
+typedef struct EdgeAdjacentVerts {
+ int vert_index[2]; /* -1 if none */
+} EdgeAdjacentVerts;
+
typedef struct EdgeDrawAttr {
unsigned char v_flag;
unsigned char e_flag;
@@ -1588,8 +1592,10 @@ typedef struct MeshBatchCache {
Gwn_Batch *edge_detection;
Gwn_VertBuf *edges_face_overlay;
+ Gwn_VertBuf *edges_face_overlay_adj;
GPUTexture *edges_face_overlay_tx;
- int edges_face_overlay_tri_count; /* Number of tri in edges_face_overlay_tx */
+ GPUTexture *edges_face_overlay_adj_tx;
+ int edges_face_overlay_tri_count; /* Number of tri in edges_face_overlay(_adj)_tx */
/* Maybe have shaded_triangles_data split into pos_nor and uv_tangent
* to minimise data transfer for skinned mesh. */
@@ -1871,7 +1877,9 @@ static void mesh_batch_cache_clear(Mesh *me)
GWN_BATCH_DISCARD_SAFE(cache->edge_detection);
GWN_VERTBUF_DISCARD_SAFE(cache->edges_face_overlay);
+ GWN_VERTBUF_DISCARD_SAFE(cache->edges_face_overlay_adj);
DRW_TEXTURE_FREE_SAFE(cache->edges_face_overlay_tx);
+ DRW_TEXTURE_FREE_SAFE(cache->edges_face_overlay_adj_tx);
GWN_VERTBUF_DISCARD_SAFE(cache->shaded_triangles_data);
if (cache->shaded_triangles_in_order) {
@@ -3341,30 +3349,68 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata,
}
#undef NO_EDGE
-static GPUTexture *mesh_batch_cache_get_edges_overlay_texture_buf(MeshRenderData *rdata, MeshBatchCache *cache)
+static EdgeHash *create_looptri_edge_adjacency_hash(MeshRenderData *rdata)
{
- BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI));
-
- BLI_assert(rdata->edit_bmesh == NULL); /* Not supported in edit mode */
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+ /* Create adjacency info in looptri */
+ EdgeHash *eh = BLI_edgehash_new_ex(__func__, tri_len * 3);
+ /* Create edges for each pair of triangles sharing an edge. */
+ for (int i = 0; i < tri_len; i++) {
+ for (int e = 0; e < 3; ++e) {
+ uint v0, v1, v2;
+ if (rdata->edit_bmesh) {
+ const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
+ if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
+ break;
+ }
+ v0 = BM_elem_index_get(bm_looptri[e]->v);
+ v1 = BM_elem_index_get(bm_looptri[(e + 1) % 3]->v);
+ v2 = BM_elem_index_get(bm_looptri[(e + 2) % 3]->v);
+ }
+ else {
+ MLoop *mloop = rdata->mloop;
+ MLoopTri *mlt = rdata->mlooptri + i;
+ v0 = mloop[mlt->tri[e]].v;
+ v1 = mloop[mlt->tri[(e + 1) % 3]].v;
+ v2 = mloop[mlt->tri[(e + 2) % 3]].v;
+ }
- if (cache->edges_face_overlay_tx != NULL) {
- return cache->edges_face_overlay_tx;
+ EdgeAdjacentVerts **eav;
+ bool value_is_init = BLI_edgehash_ensure_p(eh, v1, v2, (void ***)&eav);
+ if (!value_is_init) {
+ *eav = MEM_mallocN(sizeof(**eav), "EdgeAdjacentVerts");
+ (*eav)->vert_index[0] = v0;
+ (*eav)->vert_index[1] = -1;
+ }
+ else {
+ if ((*eav)->vert_index[1] == -1) {
+ (*eav)->vert_index[1] = v0;
+ }
+ else {
+ /* Not a manifold edge. */
+ }
+ }
+ }
}
+ return eh;
+}
+static Gwn_VertBuf *mesh_batch_cache_create_edges_overlay_adj_texture_buf(MeshRenderData *rdata, bool do_adjacency)
+{
const int tri_len = mesh_render_data_looptri_len_get(rdata);
- cache->is_manifold = true;
-
Gwn_VertFormat format = {0};
uint index_id = GWN_vertformat_attr_add(&format, "index", GWN_COMP_I32, 1, GWN_FETCH_INT);
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- cache->edges_face_overlay = vbo;
- int vbo_len_capacity = tri_len * 3;
+ int vbo_len_capacity = tri_len * ((do_adjacency) ? 6 : 3);
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
int vidx = 0;
-
+ EdgeHash *eh = NULL;
+ if (do_adjacency) {
+ eh = create_looptri_edge_adjacency_hash(rdata);
+ }
for (int i = 0; i < tri_len; i++) {
bool edge_is_real[3] = {false, false, false};
@@ -3386,11 +3432,32 @@ static GPUTexture *mesh_batch_cache_get_edges_overlay_texture_buf(MeshRenderData
for (int e = 0; e < 3; ++e) {
/* Save if there is an edge or not inside the sign bit. */
- int value = (int)mloop[mlt->tri[e]].v + 1; /* Int 0 cannot be signed */
+ int v0 = mloop[mlt->tri[e]].v;
+ int value = (int)v0 + 1; /* Int 0 cannot be signed */
value = (edge_is_real[e]) ? -value : value;
GWN_vertbuf_attr_set(vbo, index_id, vidx++, &value);
+
+ if (do_adjacency) {
+ int v1 = mloop[mlt->tri[(e+1) % 3]].v;
+ int v2 = mloop[mlt->tri[(e+2) % 3]].v;
+ EdgeAdjacentVerts *eav = BLI_edgehash_lookup(eh, v0, v1);
+ int adj_v;
+ if (eav->vert_index[0] != v2) {
+ adj_v = eav->vert_index[0];
+ }
+ else if (eav->vert_index[1] != -1) {
+ adj_v = eav->vert_index[1];
+ }
+ else {
+ adj_v = v2; /* Non-manifold edge */
+ }
+ GWN_vertbuf_attr_set(vbo, index_id, vidx++, &adj_v);
+ }
}
}
+ if (do_adjacency) {
+ BLI_edgehash_free(eh, MEM_freeN);
+ }
int vbo_len_used = vidx;
@@ -3398,10 +3465,45 @@ static GPUTexture *mesh_batch_cache_get_edges_overlay_texture_buf(MeshRenderData
GWN_vertbuf_data_resize(vbo, vbo_len_used);
}
+ return vbo;
+}
+
+static GPUTexture *mesh_batch_cache_get_edges_overlay_adj_texture_buf(MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI));
+
+ BLI_assert(rdata->edit_bmesh == NULL); /* Not supported in edit mode */
+
+ if (cache->edges_face_overlay_adj_tx != NULL) {
+ return cache->edges_face_overlay_adj_tx;
+ }
+
+ Gwn_VertBuf *vbo = cache->edges_face_overlay_adj = mesh_batch_cache_create_edges_overlay_adj_texture_buf(rdata, true);
+
+ /* Upload data early because we need to create the texture for it. */
+ GWN_vertbuf_use(vbo);
+ cache->edges_face_overlay_adj_tx = GPU_texture_create_from_vertbuf(vbo);
+ cache->edges_face_overlay_tri_count = vbo->vertex_alloc / 6;
+
+ return cache->edges_face_overlay_adj_tx;
+}
+
+static GPUTexture *mesh_batch_cache_get_edges_overlay_texture_buf(MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI));
+
+ BLI_assert(rdata->edit_bmesh == NULL); /* Not supported in edit mode */
+
+ if (cache->edges_face_overlay_tx != NULL) {
+ return cache->edges_face_overlay_tx;
+ }
+
+ Gwn_VertBuf *vbo = cache->edges_face_overlay = mesh_batch_cache_create_edges_overlay_adj_texture_buf(rdata, false);
+
/* Upload data early because we need to create the texture for it. */
GWN_vertbuf_use(vbo);
cache->edges_face_overlay_tx = GPU_texture_create_from_vertbuf(vbo);
- cache->edges_face_overlay_tri_count = vbo_len_used / 3;
+ cache->edges_face_overlay_tri_count = vbo->vertex_alloc / 3;
return cache->edges_face_overlay_tx;
}
@@ -4027,6 +4129,27 @@ void DRW_mesh_batch_cache_get_wireframes_face_texbuf(
*verts_data = cache->pos_in_order_tx;
}
+void DRW_mesh_batch_cache_get_pretty_wireframes_face_texbuf(
+ Mesh *me, GPUTexture **verts_data, GPUTexture **face_indices, int *tri_count)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->edges_face_overlay_adj_tx == NULL || cache->pos_in_order_tx == NULL) {
+ const int options = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI;
+
+ MeshRenderData *rdata = mesh_render_data_create(me, options);
+
+ mesh_batch_cache_get_edges_overlay_adj_texture_buf(rdata, cache);
+ mesh_batch_cache_get_vert_pos_and_nor_in_order_buf(rdata, cache);
+
+ mesh_render_data_free(rdata);
+ }
+
+ *tri_count = cache->edges_face_overlay_tri_count;
+ *face_indices = cache->edges_face_overlay_adj_tx;
+ *verts_data = cache->pos_in_order_tx;
+}
+
static void mesh_batch_cache_create_overlay_batches(Mesh *me)
{
BLI_assert(me->edit_btmesh != NULL);
diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c
index 131a9bc10db..107d6347c76 100644
--- a/source/blender/draw/modes/overlay_mode.c
+++ b/source/blender/draw/modes/overlay_mode.c
@@ -52,8 +52,10 @@ typedef struct OVERLAY_Data {
} OVERLAY_Data;
typedef struct OVERLAY_PrivateData {
+ GPUShader *wire_sh; /* reference */
DRWShadingGroup *face_orientation_shgrp;
View3DOverlay overlay;
+ float wire_step_param[2];
} OVERLAY_PrivateData; /* Transient data */
/* *********** STATIC *********** */
@@ -62,6 +64,7 @@ static struct {
struct GPUShader *face_orientation_sh;
/* Wireframe shader */
struct GPUShader *face_wireframe_sh;
+ struct GPUShader *face_wireframe_pretty_sh;
} e_data = {NULL};
/* Shaders */
@@ -93,14 +96,22 @@ static void overlay_engine_init(void *vedata)
}
if (!e_data.face_wireframe_sh) {
- char *wireframe_geom = NULL;
- if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
- wireframe_geom = datatoc_overlay_face_wireframe_geom_glsl;
- }
+ bool use_geom = GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY);
+
e_data.face_wireframe_sh = DRW_shader_create(
datatoc_overlay_face_wireframe_vert_glsl,
- wireframe_geom,
- datatoc_overlay_face_wireframe_frag_glsl, NULL);
+ use_geom ? datatoc_overlay_face_wireframe_geom_glsl : NULL,
+ datatoc_overlay_face_wireframe_frag_glsl,
+ use_geom ? "#define USE_GEOM_SHADER\n"
+ : NULL);
+
+ e_data.face_wireframe_pretty_sh = DRW_shader_create(
+ datatoc_overlay_face_wireframe_vert_glsl,
+ use_geom ? datatoc_overlay_face_wireframe_geom_glsl : NULL,
+ datatoc_overlay_face_wireframe_frag_glsl,
+ use_geom ? "#define USE_GEOM_SHADER\n"
+ "#define LIGHT_EDGES\n"
+ : "#define LIGHT_EDGES\n");
}
}
@@ -130,6 +141,25 @@ static void overlay_cache_init(void *vedata)
if (stl->g_data->overlay.flag & V3D_OVERLAY_WIREFRAMES) {
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND;
psl->face_wireframe_pass = DRW_pass_create("Face Wires", state);
+ /* Sticky uniforms (don't need to respecify each time since shader does not change). */
+ stl->g_data->wire_sh = (stl->g_data->overlay.wireframe_threshold == 1.0f) ? e_data.face_wireframe_sh
+ : e_data.face_wireframe_pretty_sh;
+ DRWShadingGroup *shgrp = DRW_shgroup_create(stl->g_data->wire_sh, psl->face_wireframe_pass);
+ DRW_shgroup_uniform_vec2(shgrp, "viewportSize", DRW_viewport_size_get(), 1);
+ DRW_shgroup_uniform_vec2(shgrp, "wireStepParam", stl->g_data->wire_step_param, 1);
+
+ /**
+ * The wireframe threshold ranges from 0.0 to 1.0
+ * When 1.0 we show all the edges, when 0.5 we show as many as 2.7.
+ *
+ * If we wanted 0.0 to match 2.7, factor would need to be 0.003f.
+ * The range controls the falloff effect. If range was 0.0f we would get a hard cut (as in 2.7).
+ * That said we are using a different algorithm so the results will always differ.
+ */
+ const float factor = 0.006f;
+ const float range = 0.0025f;
+ stl->g_data->wire_step_param[1] = (1.0f - factor) + stl->g_data->overlay.wireframe_threshold * factor;
+ stl->g_data->wire_step_param[0] = stl->g_data->wire_step_param[1] + range;
}
}
@@ -156,19 +186,22 @@ static void overlay_cache_populate(void *vedata, Object *ob)
if ((ob != draw_ctx->object_edit) && !BKE_object_is_in_editmode(ob)) {
int tri_count;
GPUTexture *verts = NULL, *faceids;
- DRW_cache_object_face_wireframe_get(ob, &verts, &faceids, &tri_count);
+ if (stl->g_data->overlay.wireframe_threshold == 1.0f) {
+ DRW_cache_object_face_wireframe_get(ob, &verts, &faceids, &tri_count);
+ }
+ else {
+ DRW_cache_object_face_wireframe_pretty_get(ob, &verts, &faceids, &tri_count);
+ }
if (verts) {
float *rim_col = ts.colorWire;
if ((ob->base_flag & BASE_SELECTED) != 0) {
rim_col = (ob == draw_ctx->obact) ? ts.colorActive : ts.colorSelect;
}
- /* TODO(fclem): Compare performance with a geom shader based approach. */
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.face_wireframe_sh, psl->face_wireframe_pass);
+ DRWShadingGroup *shgrp = DRW_shgroup_create(stl->g_data->wire_sh, psl->face_wireframe_pass);
DRW_shgroup_uniform_texture(shgrp, "vertData", verts);
DRW_shgroup_uniform_texture(shgrp, "faceIds", faceids);
DRW_shgroup_uniform_vec3(shgrp, "wireColor", ts.colorWire, 1);
DRW_shgroup_uniform_vec3(shgrp, "rimColor", rim_col, 1);
- DRW_shgroup_uniform_vec2(shgrp, "viewportSize", DRW_viewport_size_get(), 1);
DRW_shgroup_call_procedural_triangles_add(shgrp, tri_count, ob->obmat);
}
}
@@ -198,6 +231,7 @@ static void overlay_engine_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.face_orientation_sh);
DRW_SHADER_FREE_SAFE(e_data.face_wireframe_sh);
+ DRW_SHADER_FREE_SAFE(e_data.face_wireframe_pretty_sh);
}
static const DrawEngineDataSize overlay_data_size = DRW_VIEWPORT_DATA_SIZE(OVERLAY_Data);
diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl
index a714de9579a..5dfbb4352e4 100644
--- a/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl
+++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_frag.glsl
@@ -6,9 +6,14 @@ flat in vec3 ssVec1;
flat in vec3 ssVec2;
in float facing;
+#ifdef LIGHT_EDGES
+flat in vec3 edgeSharpness;
+#endif
+
out vec4 fragColor;
float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); }
+float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); }
/* In pixels */
const float wire_size = 0.0; /* Expands the core of the wire (part that is 100% wire color) */
@@ -27,10 +32,22 @@ void main()
dot(ss_pos, ssVec2)
);
- float fac = smoothstep(wire_size, wire_size + wire_smooth, min_v3(abs(dist_to_edge)));
+#ifdef LIGHT_EDGES
+ vec3 fac = abs(dist_to_edge);
+#else
+ float fac = min_v3(abs(dist_to_edge));
+#endif
+
+ fac = smoothstep(wire_size + wire_smooth, wire_size, fac);
+
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 *= (1.0 - fac);
+
+#ifdef LIGHT_EDGES
+ fragColor.a *= max_v3(fac * edgeSharpness);
+#else
+ fragColor.a *= fac;
+#endif
}
diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl
index 1cea418419e..8f5712cca03 100644
--- a/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl
+++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_geom.glsl
@@ -1,7 +1,12 @@
+/* This shader is only used for intel GPU where the Geom shader is faster
+ * than doing everything thrice in the vertex shader. */
+
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
+uniform vec2 wireStepParam;
+
in vec2 ssPos[];
in float facingOut[];
@@ -10,8 +15,16 @@ flat out vec3 ssVec1;
flat out vec3 ssVec2;
out float facing;
+#ifdef LIGHT_EDGES
+in vec3 obPos[];
+in vec3 edgeAdj[];
+
+flat out vec3 edgeSharpness;
+#endif
+
#define NO_EDGE vec3(10000.0);
+/* TODO(fclem) remove code duplication. */
vec3 compute_vec(vec2 v0, vec2 v1)
{
vec2 v = normalize(v1 - v0);
@@ -19,6 +32,13 @@ vec3 compute_vec(vec2 v0, vec2 v1)
return vec3(v, -dot(v, v0));
}
+float get_edge_sharpness(vec3 e0, vec3 e1, vec3 e2)
+{
+ vec3 n0 = normalize(cross(e0, e1));
+ vec3 n1 = normalize(cross(e1, e2));
+ return dot(n0, n1);
+}
+
void main(void)
{
vec3 facings = vec3(facingOut[0], facingOut[1], facingOut[2]);
@@ -29,6 +49,20 @@ void main(void)
ssVec1 = do_edge.y ? compute_vec(ssPos[1], ssPos[2]) : NO_EDGE;
ssVec2 = do_edge.z ? compute_vec(ssPos[2], ssPos[0]) : NO_EDGE;
+#ifdef LIGHT_EDGES
+ vec3 edges[3];
+ edges[0] = obPos[1] - obPos[0];
+ edges[1] = obPos[2] - obPos[1];
+ edges[2] = obPos[0] - obPos[2];
+
+ edgeSharpness.x = get_edge_sharpness(edgeAdj[0] - obPos[0], edges[0], -edges[2]);
+ edgeSharpness.y = get_edge_sharpness(edgeAdj[1] - obPos[1], edges[1], -edges[0]);
+ edgeSharpness.z = get_edge_sharpness(edgeAdj[2] - obPos[2], edges[2], -edges[1]);
+
+ /* Easy to adjust parameters. */
+ edgeSharpness = smoothstep(wireStepParam.xxx, wireStepParam.yyy, edgeSharpness);
+#endif
+
gl_Position = gl_in[0].gl_Position;
facing = facings.x;
EmitVertex();
diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
index 2cd888e7537..96afb8748b6 100644
--- a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
+++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
@@ -1,13 +1,10 @@
-#ifdef GPU_INTEL
-#define USE_GEOM_SHADER
-#endif
-
uniform mat4 ModelViewProjectionMatrix;
uniform mat4 ModelViewMatrix;
uniform mat4 ProjectionMatrix;
uniform mat3 NormalMatrix;
+uniform vec2 wireStepParam;
uniform vec2 viewportSize;
uniform float nearDist;
@@ -24,6 +21,15 @@ flat out vec3 ssVec2;
out float facing;
#endif
+#ifdef LIGHT_EDGES
+#ifdef USE_GEOM_SHADER
+out vec3 obPos;
+out vec3 edgeAdj;
+#else
+flat out vec3 edgeSharpness;
+#endif
+#endif
+
/* project to screen space */
vec2 proj(vec4 pos)
{
@@ -73,12 +79,24 @@ vec3 get_vertex_pos(int v_id)
return pos;
}
+float get_edge_sharpness(vec3 e0, vec3 e1, vec3 e2)
+{
+ vec3 n0 = normalize(cross(e0, e1));
+ vec3 n1 = normalize(cross(e1, e2));
+ return dot(n0, n1);
+}
+
#define NO_EDGE vec3(10000.0);
void main()
{
#ifdef USE_GEOM_SHADER
+
+# ifdef LIGHT_EDGES
+ int v_id = texelFetch(faceIds, gl_VertexID * 2).r;
+# else
int v_id = texelFetch(faceIds, gl_VertexID).r;
+# endif
bool do_edge = v_id < 0;
v_id = abs(v_id) - 1;
@@ -91,15 +109,28 @@ void main()
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
ssPos = proj(gl_Position);
+# ifdef LIGHT_EDGES
+ int adj_id = texelFetch(faceIds, gl_VertexID * 2 + 1).r;
+ obPos = pos;
+ edgeAdj = get_vertex_pos(adj_id);
+# endif
+
#else
+# ifdef LIGHT_EDGES
+ int v_0 = (gl_VertexID / 3) * 6;
+ ivec2 ofs = ivec2(2, 4); /* GL_TRIANGLE_ADJACENCY */
+# else
int v_0 = (gl_VertexID / 3) * 3;
+ ivec2 ofs = ivec2(1, 2); /* GL_TRIANGLES */
+# endif
int v_n = gl_VertexID % 3;
+
/* Getting the same positions for each of the 3 verts. */
ivec3 v_id;
v_id.x = texelFetch(faceIds, v_0).r;
- v_id.y = texelFetch(faceIds, v_0 + 1).r;
- v_id.z = texelFetch(faceIds, v_0 + 2).r;
+ v_id.y = texelFetch(faceIds, v_0 + ofs.x).r;
+ v_id.z = texelFetch(faceIds, v_0 + ofs.y).r;
bvec3 do_edge = lessThan(v_id, ivec3(0));
v_id = abs(v_id) - 1;
@@ -128,5 +159,30 @@ void main()
vec3 nor = get_vertex_nor(v_id[v_n]);
facing = normalize(NormalMatrix * nor).z;
+
+# ifdef LIGHT_EDGES
+ ivec3 adj_id;
+ adj_id.x = texelFetch(faceIds, v_0 + 1).r;
+ adj_id.y = texelFetch(faceIds, v_0 + 3).r;
+ adj_id.z = texelFetch(faceIds, v_0 + 5).r;
+
+ vec3 adj_pos[3];
+ adj_pos[0] = get_vertex_pos(adj_id.x);
+ adj_pos[1] = get_vertex_pos(adj_id.y);
+ adj_pos[2] = get_vertex_pos(adj_id.z);
+
+ vec3 edges[3];
+ edges[0] = pos[1] - pos[0];
+ edges[1] = pos[2] - pos[1];
+ edges[2] = pos[0] - pos[2];
+
+ edgeSharpness.x = get_edge_sharpness(adj_pos[0] - pos[0], edges[0], -edges[2]);
+ edgeSharpness.y = get_edge_sharpness(adj_pos[1] - pos[1], edges[1], -edges[0]);
+ edgeSharpness.z = get_edge_sharpness(adj_pos[2] - pos[2], edges[2], -edges[1]);
+
+ /* Easy to adjust parameters. */
+ edgeSharpness = smoothstep(wireStepParam.xxx, wireStepParam.yyy, edgeSharpness);
+# endif
+
#endif
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index d4fa98cfc88..7d8df34264e 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -329,6 +329,7 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
copy_v3_fl(v3d->shading.single_color, 0.8f);
v3d->overlay.flag = V3D_OVERLAY_LOOK_DEV;
+ v3d->overlay.wireframe_threshold = 0.5f;
v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 68da501d452..c0f13308df6 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -166,6 +166,9 @@ typedef struct View3DOverlay {
/* Armature edit/pose mode settings */
int arm_flag;
+
+ /* Other settings */
+ float wireframe_threshold, pad;
} View3DOverlay;
/* 3D ViewPort Struct */
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 8bc6391a761..284e0ea20bc 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -2565,6 +2565,14 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Wireframes", "Show face edges wires");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ prop = RNA_def_property(srna, "wireframe_threshold", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "overlay.wireframe_threshold");
+ RNA_def_property_float_default(prop, 0.5f);
+ RNA_def_property_ui_text(prop, "Wireframe Threshold", "Adjust the number of wires displayed (1 for all wires)");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
prop = RNA_def_property(srna, "show_paint_wire", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.paint_flag", V3D_OVERLAY_PAINT_WIRE);
RNA_def_property_ui_text(prop, "Show Wire", "Use wireframe display in painting modes");