Somewhat improve rendering of transparent meshes.

After this commit, any transparent triangles are drawn last, which
causes them to not clobber the depth buffer, and so if they overlap
some opaque triangles, then these opaque triangles will be visible.

There are still issues with overlapping transparent triangles,
and with transparent triangles overlapping outlines and entities.
pull/135/head
whitequark 2016-12-05 03:11:34 +00:00
parent 4a0b4fd8d3
commit 6fcf1bbe79
4 changed files with 20 additions and 3 deletions

View File

@ -416,6 +416,11 @@ void Group::GenerateDisplayItems() {
}
}
// If we render this mesh, we need to know whether it's transparent,
// and we'll want all transparent triangles last, to make the depth test
// work correctly.
displayMesh.PrecomputeTransparency();
displayDirty = false;
}
}

View File

@ -34,8 +34,6 @@ void SMesh::AddTriangle(STriMeta meta, Vector a, Vector b, Vector c) {
AddTriangle(&t);
}
void SMesh::AddTriangle(const STriangle *st) {
RgbaColor color = st->meta.color;
if(!color.IsEmpty() && color.alpha != 255) isTransparent = true;
l.Add(st);
}
@ -1091,3 +1089,16 @@ void SOutlineList::MakeFromCopyOf(SOutlineList *sol) {
l.Add(so);
}
}
void SMesh::PrecomputeTransparency() {
std::sort(l.begin(), l.end(),
[&](const STriangle &sta, const STriangle &stb) {
RgbaColor colora = sta.meta.color,
colorb = stb.meta.color;
bool opaquea = colora.IsEmpty() || colora.alpha == 255,
opaqueb = colorb.IsEmpty() || colorb.alpha == 255;
if(!opaquea || !opaqueb) isTransparent = true;
return (opaquea != opaqueb && opaquea == true);
});
}

View File

@ -276,6 +276,8 @@ public:
void MakeEdgesInPlaneInto(SEdgeList *sel, Vector n, double d);
void MakeOutlinesInto(SOutlineList *sol, EdgeKind type);
void PrecomputeTransparency();
bool IsEmpty() const;
void RemapFaces(Group *g, int remap);

View File

@ -441,7 +441,6 @@ void SSurface::TriangulateInto(SShell *shell, SMesh *sm) {
for(i = start; i < sm->l.n; i++) {
STriangle *st = &(sm->l.elem[i]);
st->meta = meta;
if(st->meta.color.alpha != 255) sm->isTransparent = true;
st->an = NormalAt(st->a.x, st->a.y);
st->bn = NormalAt(st->b.x, st->b.y);
st->cn = NormalAt(st->c.x, st->c.y);