Fix T73518: Normal Overlay

This change will not render the normals for faces that are hidden.
Before we had instance drawing the hidden faces were registered in the
index buffer. During the overlay refactoring the rendering was migrated
to instance rendering. Instance rendering does not use the index buffer
so the data was ignored.

This patch stored the normal visibility in the .w part of the normal or
for face normals it will set the normal to zero. The shader looks at
this and renders the normals fully transparent when detected.

Reviewed By: Clément Foucault

Differential Revision: https://developer.blender.org/D6798
This commit is contained in:
Jeroen Bakker 2020-02-10 15:29:16 +01:00
parent d5d235c44f
commit e2e2a98573
Notes: blender-bot 2023-02-14 06:00:45 +01:00
Referenced by issue #74618, Face Normals in Edit Mode remain when hiding Faces
Referenced by issue #73518, Normals overlay - keeps staying visible for hidden mesh parts.
2 changed files with 54 additions and 17 deletions

View File

@ -4,8 +4,8 @@ uniform sampler2D depthTex;
uniform float alpha = 1.0;
in vec3 pos;
in vec3 lnor;
in vec3 vnor;
in vec4 lnor;
in vec4 vnor;
in vec4 norAndFlag;
flat out vec4 finalColor;
@ -22,16 +22,28 @@ void main()
vec3 nor;
/* Select the right normal by cheking if the generic attrib is used. */
if (!all(equal(lnor, vec3(0)))) {
nor = lnor;
if (!all(equal(lnor.xyz, vec3(0)))) {
if (lnor.w < 0.0) {
finalColor = vec4(0.0);
return;
}
nor = lnor.xyz;
finalColor = colorLNormal;
}
else if (!all(equal(vnor, vec3(0)))) {
nor = vnor;
else if (!all(equal(vnor.xyz, vec3(0)))) {
if (vnor.w < 0.0) {
finalColor = vec4(0.0);
return;
}
nor = vnor.xyz;
finalColor = colorVNormal;
}
else {
nor = norAndFlag.xyz;
if (all(equal(nor, vec3(0.0)))) {
finalColor = vec4(0.0);
return;
}
finalColor = colorNormal;
}

View File

@ -1483,13 +1483,15 @@ static void extract_pos_nor_loop_bmesh(const MeshRenderData *UNUSED(mr),
PosNorLoop *vert = data->vbo_data + l;
copy_v3_v3(vert->pos, loop->v->co);
vert->nor = data->packed_nor[BM_elem_index_get(loop->v)];
BMFace *efa = loop->f;
vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
}
static void extract_pos_nor_loop_mesh(const MeshRenderData *mr,
int l,
const MLoop *mloop,
int UNUSED(p),
const MPoly *UNUSED(mpoly),
const MPoly *mpoly,
void *_data)
{
MeshExtract_PosNor_Data *data = _data;
@ -1498,7 +1500,7 @@ static void extract_pos_nor_loop_mesh(const MeshRenderData *mr,
copy_v3_v3(vert->pos, mvert->co);
vert->nor = data->packed_nor[mloop->v];
/* Flag for paint mode overlay. */
if (mvert->flag & ME_HIDE) {
if (mpoly->flag & ME_HIDE || mvert->flag & ME_HIDE) {
vert->nor.w = -1;
}
else if (mvert->flag & SELECT) {
@ -1606,6 +1608,8 @@ static void extract_lnor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loo
else {
((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(loop->f->no);
}
BMFace *efa = loop->f;
((GPUPackedNormal *)data)[l].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0;
}
static void extract_lnor_loop_mesh(
@ -3711,6 +3715,10 @@ static const MeshExtract extract_fdots_pos = {
/* ---------------------------------------------------------------------- */
/** \name Extract Facedots Normal and edit flag
* \{ */
#define NOR_AND_FLAG_DEFAULT 0
#define NOR_AND_FLAG_SELECT 1
#define NOR_AND_FLAG_ACTIVE -1
#define NOR_AND_FLAG_HIDDEN -2
static void *extract_fdots_nor_init(const MeshRenderData *mr, void *buf)
{
@ -3727,6 +3735,7 @@ static void *extract_fdots_nor_init(const MeshRenderData *mr, void *buf)
static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void *UNUSED(data))
{
static float invalid_normal[3] = {0.0f, 0.0f, 0.0f};
GPUVertBuf *vbo = buf;
GPUPackedNormal *nor = (GPUPackedNormal *)vbo->data;
BMFace *efa;
@ -3735,17 +3744,33 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void *
if (mr->extract_type == MR_EXTRACT_BMESH) {
for (int f = 0; f < mr->poly_len; f++) {
efa = BM_face_at_index(mr->bm, f);
nor[f] = GPU_normal_convert_i10_v3(efa->no);
/* Select / Active Flag. */
nor[f].w = BM_elem_flag_test(efa, BM_ELEM_SELECT) ? ((efa == mr->efa_act) ? -1 : 1) : 0;
const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
if (is_face_hidden) {
nor[f] = GPU_normal_convert_i10_v3(invalid_normal);
nor[f].w = NOR_AND_FLAG_HIDDEN;
}
else {
nor[f] = GPU_normal_convert_i10_v3(efa->no);
/* Select / Active Flag. */
nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
NOR_AND_FLAG_DEFAULT);
}
}
}
else {
for (int f = 0; f < mr->poly_len; f++) {
nor[f] = GPU_normal_convert_i10_v3(mr->poly_normals[f]);
if ((efa = bm_original_face_get(mr, f))) {
efa = bm_original_face_get(mr, f);
if (!efa || BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
nor[f] = GPU_normal_convert_i10_v3(invalid_normal);
nor[f].w = NOR_AND_FLAG_HIDDEN;
}
else {
nor[f] = GPU_normal_convert_i10_v3(efa->no);
/* Select / Active Flag. */
nor[f].w = BM_elem_flag_test(efa, BM_ELEM_SELECT) ? ((efa == mr->efa_act) ? -1 : 1) : 0;
nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ?
((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) :
NOR_AND_FLAG_DEFAULT);
}
}
}
@ -4013,9 +4038,9 @@ static void *extract_select_idx_init(const MeshRenderData *mr, void *buf)
}
/* TODO Use glVertexID to get loop index and use the data structure on the CPU to retrieve the
* select element associated with this loop ID. This would remove the need for this separate index
* VBOs. We could upload the p/e/v_origindex as a buffer texture and sample it inside the shader to
* output original index. */
* select element associated with this loop ID. This would remove the need for this separate
* index VBOs. We could upload the p/e/v_origindex as a buffer texture and sample it inside the
* shader to output original index. */
static void extract_poly_idx_loop_bmesh(const MeshRenderData *UNUSED(mr),
int l,