From f88de70a79c90b10c5111aa1cbb2b7b62d5f1ac0 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Mon, 13 May 2019 13:18:55 +0200 Subject: [PATCH] 3D:: improvements to transparency: works correctly (e.g. in 2D HoM), including models --- graph.cpp | 28 +++++++++++++++++++--------- hyper.h | 4 ++-- polygons.cpp | 11 +++++++++-- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/graph.cpp b/graph.cpp index 889836d5..b7979a7c 100644 --- a/graph.cpp +++ b/graph.cpp @@ -564,7 +564,7 @@ bool noshadow; #if CAP_SHAPES void ShadowV(const transmatrix& V, const hpcshape& bp, PPR prio) { if(WDIM == 2 && GDIM == 3 && bp.shs != bp.she) { - auto& p = queuepolyat(V, bp, 0x18, PPR::TRANSPARENT); + auto& p = queuepolyat(V, bp, 0x18, PPR::TRANSPARENT_SHADOW); p.outline = 0; p.subprio = -100; p.offset = bp.shs; @@ -4377,6 +4377,18 @@ void draw_grid_at(cell *c, const transmatrix& V) { } } +void queue_transparent_wall(const transmatrix& V, hpcshape& sh, color_t color) { + auto& poly = queuepolyat(V, sh, color, PPR::TRANSPARENT_WALL); + hyperpoint h = V * sh.intester; + if(pmodel == mdPerspective) + poly.subprio = int(hdist0(h) * 100000); + else { + hyperpoint h2; + applymodel(h, h2); + poly.subprio = int(h2[2] * 100000); + } + } + void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { cells_drawn++; @@ -4751,7 +4763,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { if(c->land == laHalloween && !wmblack) { transmatrix Vdepth = wmspatial ? mscale(V, geom3::BOTTOM) : V; if(DIM == 3) - draw_shapevec(c, V, shFullFloor.levels[SIDE_LAKE], darkena(firecolor(0, 10), 0, 0xDF), PPR::TRANSPARENT); + draw_shapevec(c, V, shFullFloor.levels[SIDE_LAKE], darkena(firecolor(0, 10), 0, 0xDF), PPR::TRANSPARENT_LAKE); else draw_floorshape(c, Vdepth, shFullFloor, darkena(firecolor(0, 10), 0, 0xDF), PPR::LAKEBOTTOM); } @@ -4802,7 +4814,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { } if(GDIM == 3) { for(int d=0; d<6; d++) - queuepolyat(V2 * spin(d*M_PI/S3), shHalfMirror[2], 0xC0C0C080, PPR::TRANSPARENT).subprio = 3 * c->cpdist + c->cmove(d)->cpdist; + queue_transparent_wall(V2 * spin(d*M_PI/S3), shHalfMirror[2], 0xC0C0C080); } else if(wmspatial) { const int layers = 2 << detaillevel; @@ -4822,9 +4834,8 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { queuepolyat(mirrorif(V2, onleft), shHalfFloor[ct6], darkena(fcol, fd, 0xFF), PPR::FLOORa); } - if(GDIM == 3) { - queuepolyat(V2, shHalfMirror[ct6], 0xC0C0C080, PPR::TRANSPARENT).subprio = 3 * c->cpdist + c->cmove(d)->cpdist; - } + if(GDIM == 3) + queue_transparent_wall(V2, shHalfMirror[ct6], 0xC0C0C080); else if(wmspatial) { const int layers = 2 << detaillevel; for(int z=1; zlevels[SIDE_LAKE], darkena3(fcol, fd0, 0x80), PPR::TRANSPARENT), ptds.back()->subprio = -200; + draw_shapevec(c, V, qfi.fshape->levels[SIDE_LAKE], darkena3(fcol, fd0, 0x80), PPR::TRANSPARENT_LAKE); else draw_qfi(c, (*Vdp), darkena(fcol, fd0, 0x80), PPR::LAKELEV); } @@ -5301,8 +5312,7 @@ void drawcell(cell *c, transmatrix V, int spinv, bool mirrored) { color_t t = transcolor(c, c->move(a), wcol); if(t) { t = t - get_darkval(a) * ((t & 0xF0F0F000) >> 4); - auto& poly = queuepolyat(V, shPlainWall3D[a], t, PPR::TRANSPARENT); - poly.subprio = celldistance(c, viewctr.at->c7) + celldistance(c->move(a), viewctr.at->c7); + queue_transparent_wall(V, shPlainWall3D[a], t); } } if(among(c->wall, waBoat, waStrandedBoat)) drawBoat(c, Vboat, V, V); diff --git a/hyper.h b/hyper.h index dbed4ff0..be5e720b 100644 --- a/hyper.h +++ b/hyper.h @@ -2159,8 +2159,8 @@ enum class PPR { MOBILE_ARROW, LINE, // in depth tested models transparent surfaces need to be depth sorted by HyperRogue - // and set to PPR::TRANSPARENT to draw them after all the opaque ones - TRANSPARENT, + // and set to PPR::TRANSPARENT_* to draw them after all the opaque ones + TRANSPARENT_LAKE, TRANSPARENT_SHADOW, TRANSPARENT_WALL, // no depth testing for SUPERLINE and above SUPERLINE, TEXT, CIRCLE, MAX, diff --git a/polygons.cpp b/polygons.cpp index 5e3e3cd5..c597dc90 100644 --- a/polygons.cpp +++ b/polygons.cpp @@ -1576,7 +1576,7 @@ void drawqueue() { < xintval(ap2.V * xpush0(.1)); }); - for(PPR p: {PPR::TRANSPARENT}) + for(PPR p: {PPR::TRANSPARENT_WALL}) sort(&ptds[qp0[int(p)]], &ptds[qp[int(p)]], [] (const unique_ptr& p1, const unique_ptr& p2) { return p1->subprio > p2->subprio; @@ -1812,8 +1812,15 @@ void finishshape() { area += hpc[i][0] * hpc[i+1][1] - hpc[i+1][0] * hpc[i][1]; if(abs(area) < 1e-9) last->flags |= POLY_ISSIDE; if(area >= 0) last->flags |= POLY_INVERSE; + + if(DIM == 3) { + using namespace hyperpoint_vec; + last->intester = Hypc; + for(int i=last->s; i<=last->e; i++) last->intester += hpc[i]; + if(last->s != last->e) last->intester /= last->e-last->s; + } - for(int s=0; s<4; s++) { + else for(int s=0; s<4; s++) { last->intester = C0; if(s == 0) { for(int i=last->s; ie-1; i++)