diff --git a/src/swrenderer/line/r_line.cpp b/src/swrenderer/line/r_line.cpp index 077daa72a7..d702813606 100644 --- a/src/swrenderer/line/r_line.cpp +++ b/src/swrenderer/line/r_line.cpp @@ -171,12 +171,12 @@ namespace swrenderer if (rw_frontcz1 > rw_backcz1 || rw_frontcz2 > rw_backcz2) { rw_havehigh = true; - R_CreateWallSegmentYSloped(wallupper, backsector->ceilingplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); + wallupper.Project(backsector->ceilingplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); } if (rw_frontfz1 < rw_backfz1 || rw_frontfz2 < rw_backfz2) { rw_havelow = true; - R_CreateWallSegmentYSloped(walllower, backsector->floorplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); + walllower.Project(backsector->floorplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); } // Portal @@ -272,30 +272,13 @@ namespace swrenderer if (line->linedef->special == Line_Horizon) { // Be aware: Line_Horizon does not work properly with sloped planes - fillshort(walltop + WallC.sx1, WallC.sx2 - WallC.sx1, centery); - fillshort(wallbottom + WallC.sx1, WallC.sx2 - WallC.sx1, centery); + fillshort(walltop.ScreenY + WallC.sx1, WallC.sx2 - WallC.sx1, centery); + fillshort(wallbottom.ScreenY + WallC.sx1, WallC.sx2 - WallC.sx1, centery); } else { - rw_ceilstat = R_CreateWallSegmentYSloped(walltop, frontsector->ceilingplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); - rw_floorstat = R_CreateWallSegmentYSloped(wallbottom, frontsector->floorplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); - - // [RH] treat off-screen walls as solid -#if 0 // Maybe later... - if (!solid) - { - if (rw_ceilstat == 12 && line->sidedef->GetTexture(side_t::top) != 0) - { - rw_mustmarkceiling = true; - solid = true; - } - if (rw_floorstat == 3 && line->sidedef->GetTexture(side_t::bottom) != 0) - { - rw_mustmarkfloor = true; - solid = true; - } - } -#endif + rw_ceilstat = walltop.Project(frontsector->ceilingplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); + rw_floorstat = wallbottom.Project(frontsector->floorplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); } static SWRenderLine *self = this; @@ -455,8 +438,8 @@ namespace swrenderer // allocate space for masked texture tables, if needed // [RH] Don't just allocate the space; fill it in too. if ((TexMan(sidedef->GetTexture(side_t::mid), true)->UseType != FTexture::TEX_Null || draw_segment->bFakeBoundary || IsFogBoundary(frontsector, backsector)) && - (rw_ceilstat != 12 || !sidedef->GetTexture(side_t::top).isValid()) && - (rw_floorstat != 3 || !sidedef->GetTexture(side_t::bottom).isValid()) && + (rw_ceilstat != ProjectedWallCull::OutsideBelow || !sidedef->GetTexture(side_t::top).isValid()) && + (rw_floorstat != ProjectedWallCull::OutsideAbove || !sidedef->GetTexture(side_t::bottom).isValid()) && (WallC.sz1 >= TOO_CLOSE_Z && WallC.sz2 >= TOO_CLOSE_Z)) { float *swal; @@ -491,8 +474,8 @@ namespace swrenderer for (i = start; i < stop; i++) { - *lwal++ = lwall[i] + xoffset; - *swal++ = swall[i]; + *lwal++ = walltexcoords.UPos[i] + xoffset; + *swal++ = walltexcoords.VStep[i]; } double istart = draw_segment->swall[0] * yscale; @@ -696,7 +679,7 @@ namespace swrenderer { if (rw_havehigh) { // front ceiling is above back ceiling - memcpy(&walltop[WallC.sx1], &wallupper[WallC.sx1], (WallC.sx2 - WallC.sx1) * sizeof(walltop[0])); + memcpy(&walltop.ScreenY[WallC.sx1], &wallupper.ScreenY[WallC.sx1], (WallC.sx2 - WallC.sx1) * sizeof(walltop.ScreenY[0])); rw_havehigh = false; } else if (rw_havelow && frontsector->ceilingplane != backsector->ceilingplane) @@ -707,7 +690,7 @@ namespace swrenderer // Recalculate walltop so that the wall is clipped by the back sector's // ceiling instead of the front sector's ceiling. RenderPortal *renderportal = RenderPortal::Instance(); - R_CreateWallSegmentYSloped(walltop, backsector->ceilingplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); + walltop.Project(backsector->ceilingplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); } // Putting sky ceilings on the front and back of a line alters the way unpegged // positioning works. @@ -916,7 +899,7 @@ namespace swrenderer bottomtexture ? (bottomtexture->Scale.X * sidedef->GetTextureXScale(side_t::bottom)) : 1.; - PrepWall(swall, lwall, sidedef->TexelLength * lwallscale, WallC.sx1, WallC.sx2, WallT); + walltexcoords.Project(sidedef->TexelLength * lwallscale, WallC.sx1, WallC.sx2, WallT); if (fixedcolormap == NULL && fixedlightlev < 0) { @@ -959,13 +942,13 @@ namespace swrenderer auto floorclip = RenderOpaquePass::Instance()->floorclip; for (x = x1; x < x2; ++x) { - if (walltop[x] < ceilingclip[x]) + if (walltop.ScreenY[x] < ceilingclip[x]) { - walltop[x] = ceilingclip[x]; + walltop.ScreenY[x] = ceilingclip[x]; } - if (wallbottom[x] > floorclip[x]) + if (wallbottom.ScreenY[x] > floorclip[x]) { - wallbottom[x] = floorclip[x]; + wallbottom.ScreenY[x] = floorclip[x]; } } @@ -977,7 +960,7 @@ namespace swrenderer for (x = x1; x < x2; ++x) { short top = (clip3d->fakeFloor && clip3d->fake3D & FAKE3D_FAKECEILING) ? clip3d->fakeFloor->ceilingclip[x] : ceilingclip[x]; - short bottom = MIN(walltop[x], floorclip[x]); + short bottom = MIN(walltop.ScreenY[x], floorclip[x]); if (top < bottom) { ceilingplane->top[x] = top; @@ -991,7 +974,7 @@ namespace swrenderer { for (x = x1; x < x2; ++x) { - short top = MAX(wallbottom[x], ceilingclip[x]); + short top = MAX(wallbottom.ScreenY[x], ceilingclip[x]); short bottom = (clip3d->fakeFloor && clip3d->fake3D & FAKE3D_FAKEFLOOR) ? clip3d->fakeFloor->floorclip[x] : floorclip[x]; if (top < bottom) { @@ -1007,27 +990,27 @@ namespace swrenderer { if (clip3d->fake3D & FAKE3D_CLIPBOTFRONT) { - memcpy(clip3d->fakeFloor->floorclip + x1, wallbottom + x1, (x2 - x1) * sizeof(short)); + memcpy(clip3d->fakeFloor->floorclip + x1, wallbottom.ScreenY + x1, (x2 - x1) * sizeof(short)); } else { for (x = x1; x < x2; ++x) { - walllower[x] = MIN(MAX(walllower[x], ceilingclip[x]), wallbottom[x]); + walllower.ScreenY[x] = MIN(MAX(walllower.ScreenY[x], ceilingclip[x]), wallbottom.ScreenY[x]); } - memcpy(clip3d->fakeFloor->floorclip + x1, walllower + x1, (x2 - x1) * sizeof(short)); + memcpy(clip3d->fakeFloor->floorclip + x1, walllower.ScreenY + x1, (x2 - x1) * sizeof(short)); } if (clip3d->fake3D & FAKE3D_CLIPTOPFRONT) { - memcpy(clip3d->fakeFloor->ceilingclip + x1, walltop + x1, (x2 - x1) * sizeof(short)); + memcpy(clip3d->fakeFloor->ceilingclip + x1, walltop.ScreenY + x1, (x2 - x1) * sizeof(short)); } else { for (x = x1; x < x2; ++x) { - wallupper[x] = MAX(MIN(wallupper[x], floorclip[x]), walltop[x]); + wallupper.ScreenY[x] = MAX(MIN(wallupper.ScreenY[x], floorclip[x]), walltop.ScreenY[x]); } - memcpy(clip3d->fakeFloor->ceilingclip + x1, wallupper + x1, (x2 - x1) * sizeof(short)); + memcpy(clip3d->fakeFloor->ceilingclip + x1, wallupper.ScreenY + x1, (x2 - x1) * sizeof(short)); } } if (clip3d->fake3D & FAKE3D_FAKEMASK) return; @@ -1044,7 +1027,7 @@ namespace swrenderer yscale = rw_pic->Scale.Y * rw_midtexturescaley; if (xscale != lwallscale) { - PrepLWall(lwall, curline->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT); + walltexcoords.ProjectPos(curline->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT); lwallscale = xscale; } if (midtexture->bWorldPanning) @@ -1059,7 +1042,7 @@ namespace swrenderer { rw_offset = -rw_offset; } - R_DrawWallSegment(frontsector, curline, WallC, rw_pic, x1, x2, walltop, wallbottom, rw_midtexturemid, swall, lwall, yscale, MAX(rw_frontcz1, rw_frontcz2), MIN(rw_frontfz1, rw_frontfz2), false, wallshade, rw_offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); + R_DrawWallSegment(frontsector, curline, WallC, rw_pic, x1, x2, walltop.ScreenY, wallbottom.ScreenY, rw_midtexturemid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(rw_frontcz1, rw_frontcz2), MIN(rw_frontfz1, rw_frontfz2), false, wallshade, rw_offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); } fillshort(ceilingclip + x1, x2 - x1, viewheight); fillshort(floorclip + x1, x2 - x1, 0xffff); @@ -1070,7 +1053,7 @@ namespace swrenderer { // top wall for (x = x1; x < x2; ++x) { - wallupper[x] = MAX(MIN(wallupper[x], floorclip[x]), walltop[x]); + wallupper.ScreenY[x] = MAX(MIN(wallupper.ScreenY[x], floorclip[x]), walltop.ScreenY[x]); } if (viewactive) { @@ -1079,7 +1062,7 @@ namespace swrenderer yscale = rw_pic->Scale.Y * rw_toptexturescaley; if (xscale != lwallscale) { - PrepLWall(lwall, curline->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT); + walltexcoords.ProjectPos(curline->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT); lwallscale = xscale; } if (toptexture->bWorldPanning) @@ -1094,13 +1077,13 @@ namespace swrenderer { rw_offset = -rw_offset; } - R_DrawWallSegment(frontsector, curline, WallC, rw_pic, x1, x2, walltop, wallupper, rw_toptexturemid, swall, lwall, yscale, MAX(rw_frontcz1, rw_frontcz2), MIN(rw_backcz1, rw_backcz2), false, wallshade, rw_offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); + R_DrawWallSegment(frontsector, curline, WallC, rw_pic, x1, x2, walltop.ScreenY, wallupper.ScreenY, rw_toptexturemid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(rw_frontcz1, rw_frontcz2), MIN(rw_backcz1, rw_backcz2), false, wallshade, rw_offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); } - memcpy(ceilingclip + x1, wallupper + x1, (x2 - x1) * sizeof(short)); + memcpy(ceilingclip + x1, wallupper.ScreenY + x1, (x2 - x1) * sizeof(short)); } else if (markceiling) { // no top wall - memcpy(ceilingclip + x1, walltop + x1, (x2 - x1) * sizeof(short)); + memcpy(ceilingclip + x1, walltop.ScreenY + x1, (x2 - x1) * sizeof(short)); } @@ -1108,7 +1091,7 @@ namespace swrenderer { // bottom wall for (x = x1; x < x2; ++x) { - walllower[x] = MIN(MAX(walllower[x], ceilingclip[x]), wallbottom[x]); + walllower.ScreenY[x] = MIN(MAX(walllower.ScreenY[x], ceilingclip[x]), wallbottom.ScreenY[x]); } if (viewactive) { @@ -1117,7 +1100,7 @@ namespace swrenderer yscale = rw_pic->Scale.Y * rw_bottomtexturescaley; if (xscale != lwallscale) { - PrepLWall(lwall, curline->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT); + walltexcoords.ProjectPos(curline->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT); lwallscale = xscale; } if (bottomtexture->bWorldPanning) @@ -1132,13 +1115,13 @@ namespace swrenderer { rw_offset = -rw_offset; } - R_DrawWallSegment(frontsector, curline, WallC, rw_pic, x1, x2, walllower, wallbottom, rw_bottomtexturemid, swall, lwall, yscale, MAX(rw_backfz1, rw_backfz2), MIN(rw_frontfz1, rw_frontfz2), false, wallshade, rw_offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); + R_DrawWallSegment(frontsector, curline, WallC, rw_pic, x1, x2, walllower.ScreenY, wallbottom.ScreenY, rw_bottomtexturemid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(rw_backfz1, rw_backfz2), MIN(rw_frontfz1, rw_frontfz2), false, wallshade, rw_offset, rw_light, rw_lightstep, light_list, foggy, basecolormap); } - memcpy(floorclip + x1, walllower + x1, (x2 - x1) * sizeof(short)); + memcpy(floorclip + x1, walllower.ScreenY + x1, (x2 - x1) * sizeof(short)); } else if (markfloor) { // no bottom wall - memcpy(floorclip + x1, wallbottom + x1, (x2 - x1) * sizeof(short)); + memcpy(floorclip + x1, wallbottom.ScreenY + x1, (x2 - x1) * sizeof(short)); } } rw_offset = xoffset; diff --git a/src/swrenderer/line/r_line.h b/src/swrenderer/line/r_line.h index cb48eb4bbd..51ec10787e 100644 --- a/src/swrenderer/line/r_line.h +++ b/src/swrenderer/line/r_line.h @@ -14,6 +14,7 @@ #pragma once #include "vectors.h" +#include "r_wallsetup.h" struct seg_t; struct subsector_t; @@ -85,7 +86,7 @@ namespace swrenderer fixed_t rw_offset_mid; fixed_t rw_offset_bottom; - int rw_ceilstat, rw_floorstat; + ProjectedWallCull rw_ceilstat, rw_floorstat; bool rw_mustmarkfloor, rw_mustmarkceiling; bool rw_prepped; bool rw_markportal; @@ -120,5 +121,7 @@ namespace swrenderer bool foggy; FDynamicColormap *basecolormap; + + double lwallscale; }; } diff --git a/src/swrenderer/line/r_walldraw.cpp b/src/swrenderer/line/r_walldraw.cpp index 43aaa38bcd..d6c475a81c 100644 --- a/src/swrenderer/line/r_walldraw.cpp +++ b/src/swrenderer/line/r_walldraw.cpp @@ -421,11 +421,11 @@ namespace swrenderer static void ProcessStripedWall(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, int wallshade, fixed_t xoffset, float light, float lightstep, bool foggy, FDynamicColormap *basecolormap, FLightNode *light_list) { - short most1[MAXWIDTH], most2[MAXWIDTH], most3[MAXWIDTH]; + ProjectedWallLine most1, most2, most3; short *up, *down; up = uwal; - down = most1; + down = most1.ScreenY; assert(WallC.sx1 <= x1); assert(WallC.sx2 >= x2); @@ -435,16 +435,16 @@ namespace swrenderer // kg3D - fake floors instead of zdoom light list for (unsigned int i = 0; i < frontsector->e->XFloor.lightlist.Size(); i++) { - int j = R_CreateWallSegmentYSloped(most3, frontsector->e->XFloor.lightlist[i].plane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); - if (j != 3) + ProjectedWallCull j = most3.Project(frontsector->e->XFloor.lightlist[i].plane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); + if (j != ProjectedWallCull::OutsideAbove) { for (int j = x1; j < x2; ++j) { - down[j] = clamp(most3[j], up[j], dwal[j]); + down[j] = clamp(most3.ScreenY[j], up[j], dwal[j]); } ProcessNormalWall(WallC, x1, x2, up, down, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, basecolormap, light_list); up = down; - down = (down == most1) ? most2 : most1; + down = (down == most1.ScreenY) ? most2.ScreenY : most1.ScreenY; } lightlist_t *lit = &frontsector->e->XFloor.lightlist[i]; @@ -494,7 +494,7 @@ namespace swrenderer static void ProcessWallNP2(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, int x1, int x2, short *uwal, short *dwal, double texturemid, float *swal, fixed_t *lwal, double yrepeat, double top, double bot, int wallshade, fixed_t xoffset, float light, float lightstep, bool mask, bool foggy, FDynamicColormap *basecolormap, FLightNode *light_list) { - short most1[MAXWIDTH], most2[MAXWIDTH], most3[MAXWIDTH]; + ProjectedWallLine most1, most2, most3; short *up, *down; double texheight = rw_pic->GetHeight(); double partition; @@ -508,20 +508,20 @@ namespace swrenderer partition -= scaledtexheight; } up = uwal; - down = most1; + down = most1.ScreenY; texturemid = (partition - ViewPos.Z) * yrepeat + texheight; while (partition > bot) { - int j = R_CreateWallSegmentY(most3, partition - ViewPos.Z, &WallC); - if (j != 3) + ProjectedWallCull j = most3.Project(partition - ViewPos.Z, &WallC); + if (j != ProjectedWallCull::OutsideAbove) { for (int j = x1; j < x2; ++j) { - down[j] = clamp(most3[j], up[j], dwal[j]); + down[j] = clamp(most3.ScreenY[j], up[j], dwal[j]); } ProcessWall(frontsector, curline, WallC, x1, x2, up, down, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, mask, foggy, basecolormap, light_list); up = down; - down = (down == most1) ? most2 : most1; + down = (down == most1.ScreenY) ? most2.ScreenY : most1.ScreenY; } partition -= scaledtexheight; texturemid -= texheight; @@ -531,21 +531,21 @@ namespace swrenderer else { // upside down: draw strips from bottom to top partition = bot - fmod(bot - texturemid / yrepeat - ViewPos.Z, scaledtexheight); - up = most1; + up = most1.ScreenY; down = dwal; texturemid = (partition - ViewPos.Z) * yrepeat + texheight; while (partition < top) { - int j = R_CreateWallSegmentY(most3, partition - ViewPos.Z, &WallC); - if (j != 12) + ProjectedWallCull j = most3.Project(partition - ViewPos.Z, &WallC); + if (j != ProjectedWallCull::OutsideBelow) { for (int j = x1; j < x2; ++j) { - up[j] = clamp(most3[j], uwal[j], down[j]); + up[j] = clamp(most3.ScreenY[j], uwal[j], down[j]); } ProcessWall(frontsector, curline, WallC, x1, x2, up, down, texturemid, swal, lwal, yrepeat, wallshade, xoffset, light, lightstep, mask, foggy, basecolormap, light_list); down = up; - up = (up == most1) ? most2 : most1; + up = (up == most1.ScreenY) ? most2.ScreenY : most1.ScreenY; } partition -= scaledtexheight; texturemid -= texheight; diff --git a/src/swrenderer/line/r_wallsetup.cpp b/src/swrenderer/line/r_wallsetup.cpp index e7a86700de..4c34f3483c 100644 --- a/src/swrenderer/line/r_wallsetup.cpp +++ b/src/swrenderer/line/r_wallsetup.cpp @@ -27,37 +27,35 @@ namespace swrenderer { - short walltop[MAXWIDTH]; - short wallbottom[MAXWIDTH]; - short wallupper[MAXWIDTH]; - short walllower[MAXWIDTH]; - float swall[MAXWIDTH]; - fixed_t lwall[MAXWIDTH]; - double lwallscale; + ProjectedWallLine walltop; + ProjectedWallLine wallbottom; + ProjectedWallLine wallupper; + ProjectedWallLine walllower; + ProjectedWallTexcoords walltexcoords; - int R_CreateWallSegmentY(short *outbuf, double z, const FWallCoords *wallc) + ProjectedWallCull ProjectedWallLine::Project(double z, const FWallCoords *wallc) { - return R_CreateWallSegmentY(outbuf, z, z, wallc); + return Project(z, z, wallc); } - int R_CreateWallSegmentY(short *outbuf, double z1, double z2, const FWallCoords *wallc) + ProjectedWallCull ProjectedWallLine::Project(double z1, double z2, const FWallCoords *wallc) { float y1 = (float)(CenterY - z1 * InvZtoScale / wallc->sz1); float y2 = (float)(CenterY - z2 * InvZtoScale / wallc->sz2); if (y1 < 0 && y2 < 0) // entire line is above screen { - memset(&outbuf[wallc->sx1], 0, (wallc->sx2 - wallc->sx1) * sizeof(outbuf[0])); - return 3; + memset(&ScreenY[wallc->sx1], 0, (wallc->sx2 - wallc->sx1) * sizeof(ScreenY[0])); + return ProjectedWallCull::OutsideAbove; } else if (y1 > viewheight && y2 > viewheight) // entire line is below screen { - fillshort(&outbuf[wallc->sx1], wallc->sx2 - wallc->sx1, viewheight); - return 12; + fillshort(&ScreenY[wallc->sx1], wallc->sx2 - wallc->sx1, viewheight); + return ProjectedWallCull::OutsideBelow; } if (wallc->sx2 <= wallc->sx1) - return 0; + return ProjectedWallCull::Visible; float rcp_delta = 1.0f / (wallc->sx2 - wallc->sx1); if (y1 >= 0.0f && y2 >= 0.0f && xs_RoundToInt(y1) <= viewheight && xs_RoundToInt(y2) <= viewheight) @@ -66,7 +64,7 @@ namespace swrenderer { float t = (x - wallc->sx1) * rcp_delta; float y = y1 * (1.0f - t) + y2 * t; - outbuf[x] = (short)xs_RoundToInt(y); + ScreenY[x] = (short)xs_RoundToInt(y); } } else @@ -75,18 +73,18 @@ namespace swrenderer { float t = (x - wallc->sx1) * rcp_delta; float y = y1 * (1.0f - t) + y2 * t; - outbuf[x] = (short)clamp(xs_RoundToInt(y), 0, viewheight); + ScreenY[x] = (short)clamp(xs_RoundToInt(y), 0, viewheight); } } - return 0; + return ProjectedWallCull::Visible; } - int R_CreateWallSegmentYSloped(short *outbuf, const secplane_t &plane, const FWallCoords *wallc, seg_t *curline, bool xflip) + ProjectedWallCull ProjectedWallLine::Project(const secplane_t &plane, const FWallCoords *wallc, seg_t *curline, bool xflip) { if (!plane.isSlope()) { - return R_CreateWallSegmentY(outbuf, plane.Zat0() - ViewPos.Z, wallc); + return Project(plane.Zat0() - ViewPos.Z, wallc); } else { @@ -151,11 +149,13 @@ namespace swrenderer } } - return R_CreateWallSegmentY(outbuf, z1, z2, wallc); + return Project(z1, z2, wallc); } } - void PrepWall(float *vstep, fixed_t *upos, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT) + ///////////////////////////////////////////////////////////////////////// + + void ProjectedWallTexcoords::Project(double walxrepeat, int x1, int x2, const FWallTmapVals &WallT) { float uOverZ = WallT.UoverZorg + WallT.UoverZstep * (float)(x1 + 0.5 - CenterX); float invZ = WallT.InvZorg + WallT.InvZstep * (float)(x1 + 0.5 - CenterX); @@ -171,8 +171,8 @@ namespace swrenderer { float u = uOverZ / invZ; - upos[x] = (fixed_t)((xrepeat - u * xrepeat) * FRACUNIT); - vstep[x] = depthOrg + u * depthScale; + UPos[x] = (fixed_t)((xrepeat - u * xrepeat) * FRACUNIT); + VStep[x] = depthOrg + u * depthScale; uOverZ += uGradient; invZ += zGradient; @@ -184,8 +184,8 @@ namespace swrenderer { float u = uOverZ / invZ; - upos[x] = (fixed_t)(u * xrepeat * FRACUNIT); - vstep[x] = depthOrg + u * depthScale; + UPos[x] = (fixed_t)(u * xrepeat * FRACUNIT); + VStep[x] = depthOrg + u * depthScale; uOverZ += uGradient; invZ += zGradient; @@ -193,7 +193,7 @@ namespace swrenderer } } - void PrepLWall(fixed_t *upos, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT) + void ProjectedWallTexcoords::ProjectPos(double walxrepeat, int x1, int x2, const FWallTmapVals &WallT) { float uOverZ = WallT.UoverZorg + WallT.UoverZstep * (float)(x1 + 0.5 - CenterX); float invZ = WallT.InvZorg + WallT.InvZstep * (float)(x1 + 0.5 - CenterX); @@ -207,7 +207,7 @@ namespace swrenderer { float u = uOverZ / invZ * xrepeat - xrepeat; - upos[x] = (fixed_t)(u * FRACUNIT); + UPos[x] = (fixed_t)(u * FRACUNIT); uOverZ += uGradient; invZ += zGradient; @@ -219,7 +219,7 @@ namespace swrenderer { float u = uOverZ / invZ * xrepeat; - upos[x] = (fixed_t)(u * FRACUNIT); + UPos[x] = (fixed_t)(u * FRACUNIT); uOverZ += uGradient; invZ += zGradient; diff --git a/src/swrenderer/line/r_wallsetup.h b/src/swrenderer/line/r_wallsetup.h index 5ceac6f65e..628a9029b6 100644 --- a/src/swrenderer/line/r_wallsetup.h +++ b/src/swrenderer/line/r_wallsetup.h @@ -8,18 +8,36 @@ namespace swrenderer struct FWallCoords; struct FWallTmapVals; - extern short walltop[MAXWIDTH]; - extern short wallbottom[MAXWIDTH]; - extern short wallupper[MAXWIDTH]; - extern short walllower[MAXWIDTH]; - extern float swall[MAXWIDTH]; - extern fixed_t lwall[MAXWIDTH]; - extern double lwallscale; + enum class ProjectedWallCull + { + Visible, + OutsideAbove, + OutsideBelow + }; - int R_CreateWallSegmentY(short *outbuf, double z1, double z2, const FWallCoords *wallc); - int R_CreateWallSegmentYSloped(short *outbuf, const secplane_t &plane, const FWallCoords *wallc, seg_t *line, bool xflip); - int R_CreateWallSegmentY(short *outbuf, double z, const FWallCoords *wallc); + class ProjectedWallLine + { + public: + short ScreenY[MAXWIDTH]; - void PrepWall(float *swall, fixed_t *lwall, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT); - void PrepLWall(fixed_t *lwall, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT); + ProjectedWallCull Project(double z1, double z2, const FWallCoords *wallc); + ProjectedWallCull Project(const secplane_t &plane, const FWallCoords *wallc, seg_t *line, bool xflip); + ProjectedWallCull Project(double z, const FWallCoords *wallc); + }; + + class ProjectedWallTexcoords + { + public: + float VStep[MAXWIDTH]; // swall + fixed_t UPos[MAXWIDTH]; // lwall + + void Project(double walxrepeat, int x1, int x2, const FWallTmapVals &WallT); + void ProjectPos(double walxrepeat, int x1, int x2, const FWallTmapVals &WallT); + }; + + extern ProjectedWallLine walltop; + extern ProjectedWallLine wallbottom; + extern ProjectedWallLine wallupper; + extern ProjectedWallLine walllower; + extern ProjectedWallTexcoords walltexcoords; } diff --git a/src/swrenderer/segments/r_drawsegment.cpp b/src/swrenderer/segments/r_drawsegment.cpp index 160290068e..e5864f8050 100644 --- a/src/swrenderer/segments/r_drawsegment.cpp +++ b/src/swrenderer/segments/r_drawsegment.cpp @@ -110,21 +110,21 @@ namespace swrenderer // Clip a midtexture to the floor and ceiling of the sector in front of it. void ClipMidtex(int x1, int x2) { - short most[MAXWIDTH]; + ProjectedWallLine most; RenderPortal *renderportal = RenderPortal::Instance(); - R_CreateWallSegmentYSloped(most, curline->frontsector->ceilingplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); + most.Project(curline->frontsector->ceilingplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); for (int i = x1; i < x2; ++i) { - if (wallupper[i] < most[i]) - wallupper[i] = most[i]; + if (wallupper.ScreenY[i] < most.ScreenY[i]) + wallupper.ScreenY[i] = most.ScreenY[i]; } - R_CreateWallSegmentYSloped(most, curline->frontsector->floorplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); + most.Project(curline->frontsector->floorplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP); for (int i = x1; i < x2; ++i) { - if (walllower[i] > most[i]) - walllower[i] = most[i]; + if (walllower.ScreenY[i] > most.ScreenY[i]) + walllower.ScreenY[i] = most.ScreenY[i]; } } @@ -305,30 +305,30 @@ namespace swrenderer if (clip3d->fake3D & FAKE3D_CLIPTOP) { - R_CreateWallSegmentY(wallupper, textop < clip3d->sclipTop - ViewPos.Z ? textop : clip3d->sclipTop - ViewPos.Z, &WallC); + wallupper.Project(textop < clip3d->sclipTop - ViewPos.Z ? textop : clip3d->sclipTop - ViewPos.Z, &WallC); } else { - R_CreateWallSegmentY(wallupper, textop, &WallC); + wallupper.Project(textop, &WallC); } if (clip3d->fake3D & FAKE3D_CLIPBOTTOM) { - R_CreateWallSegmentY(walllower, textop - texheight > clip3d->sclipBottom - ViewPos.Z ? textop - texheight : clip3d->sclipBottom - ViewPos.Z, &WallC); + walllower.Project(textop - texheight > clip3d->sclipBottom - ViewPos.Z ? textop - texheight : clip3d->sclipBottom - ViewPos.Z, &WallC); } else { - R_CreateWallSegmentY(walllower, textop - texheight, &WallC); + walllower.Project(textop - texheight, &WallC); } for (i = x1; i < x2; i++) { - if (wallupper[i] < mceilingclip[i]) - wallupper[i] = mceilingclip[i]; + if (wallupper.ScreenY[i] < mceilingclip[i]) + wallupper.ScreenY[i] = mceilingclip[i]; } for (i = x1; i < x2; i++) { - if (walllower[i] > mfloorclip[i]) - walllower[i] = mfloorclip[i]; + if (walllower.ScreenY[i] > mfloorclip[i]) + walllower.ScreenY[i] = mfloorclip[i]; } if (clip3d->CurrentSkybox) @@ -342,8 +342,8 @@ namespace swrenderer } } - mfloorclip = walllower; - mceilingclip = wallupper; + mfloorclip = walllower.ScreenY; + mceilingclip = wallupper.ScreenY; // draw the columns one at a time if (visible) @@ -402,23 +402,23 @@ namespace swrenderer if (clip3d->fake3D & FAKE3D_CLIPTOP) { - R_CreateWallSegmentY(wallupper, clip3d->sclipTop - ViewPos.Z, &WallC); + wallupper.Project(clip3d->sclipTop - ViewPos.Z, &WallC); for (i = x1; i < x2; i++) { - if (wallupper[i] < mceilingclip[i]) - wallupper[i] = mceilingclip[i]; + if (wallupper.ScreenY[i] < mceilingclip[i]) + wallupper.ScreenY[i] = mceilingclip[i]; } - mceilingclip = wallupper; + mceilingclip = wallupper.ScreenY; } if (clip3d->fake3D & FAKE3D_CLIPBOTTOM) { - R_CreateWallSegmentY(walllower, clip3d->sclipBottom - ViewPos.Z, &WallC); + walllower.Project(clip3d->sclipBottom - ViewPos.Z, &WallC); for (i = x1; i < x2; i++) { - if (walllower[i] > mfloorclip[i]) - walllower[i] = mfloorclip[i]; + if (walllower.ScreenY[i] > mfloorclip[i]) + walllower.ScreenY[i] = mfloorclip[i]; } - mfloorclip = walllower; + mfloorclip = walllower.ScreenY; } rw_offset = 0; @@ -532,22 +532,22 @@ namespace swrenderer WallT = ds->tmapvals; Clip3DFloors *clip3d = Clip3DFloors::Instance(); - R_CreateWallSegmentY(wallupper, clip3d->sclipTop - ViewPos.Z, &WallC); - R_CreateWallSegmentY(walllower, clip3d->sclipBottom - ViewPos.Z, &WallC); + wallupper.Project(clip3d->sclipTop - ViewPos.Z, &WallC); + walllower.Project(clip3d->sclipBottom - ViewPos.Z, &WallC); for (i = x1; i < x2; i++) { - if (wallupper[i] < mceilingclip[i]) - wallupper[i] = mceilingclip[i]; + if (wallupper.ScreenY[i] < mceilingclip[i]) + wallupper.ScreenY[i] = mceilingclip[i]; } for (i = x1; i < x2; i++) { - if (walllower[i] > mfloorclip[i]) - walllower[i] = mfloorclip[i]; + if (walllower.ScreenY[i] > mfloorclip[i]) + walllower.ScreenY[i] = mfloorclip[i]; } - PrepLWall(lwall, curline->sidedef->TexelLength*xscale, ds->sx1, ds->sx2, WallT); - R_DrawDrawSeg(frontsector, curline, WallC, rw_pic, ds, x1, x2, wallupper, walllower, texturemid, MaskedSWall, lwall, yscale, wallshade, rw_offset, rw_light, rw_lightstep, ds->foggy, basecolormap); + walltexcoords.ProjectPos(curline->sidedef->TexelLength*xscale, ds->sx1, ds->sx2, WallT); + R_DrawDrawSeg(frontsector, curline, WallC, rw_pic, ds, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, MaskedSWall, walltexcoords.UPos, yscale, wallshade, rw_offset, rw_light, rw_lightstep, ds->foggy, basecolormap); } // kg3D - walls of fake floors diff --git a/src/swrenderer/things/r_decal.cpp b/src/swrenderer/things/r_decal.cpp index 9e17b95c8b..c25341c09e 100644 --- a/src/swrenderer/things/r_decal.cpp +++ b/src/swrenderer/things/r_decal.cpp @@ -171,12 +171,12 @@ namespace swrenderer { goto done; } - mceilingclip = walltop; - mfloorclip = wallbottom; + mceilingclip = walltop.ScreenY; + mfloorclip = wallbottom.ScreenY; } else if (pass == 0) { - mceilingclip = walltop; + mceilingclip = walltop.ScreenY; mfloorclip = RenderOpaquePass::Instance()->ceilingclip; needrepeat = 1; } @@ -192,7 +192,7 @@ namespace swrenderer { goto done; } - mceilingclip = walltop; + mceilingclip = walltop.ScreenY; mfloorclip = RenderOpaquePass::Instance()->ceilingclip; break; @@ -211,7 +211,7 @@ namespace swrenderer goto done; } mceilingclip = RenderOpaquePass::Instance()->floorclip; - mfloorclip = wallbottom; + mfloorclip = wallbottom.ScreenY; break; } @@ -226,7 +226,7 @@ namespace swrenderer goto done; } - PrepWall(swall, lwall, WallSpriteTile->GetWidth(), x1, x2, WallT); + walltexcoords.Project(WallSpriteTile->GetWidth(), x1, x2, WallT); if (flipx) { @@ -235,7 +235,7 @@ namespace swrenderer for (i = x1; i < x2; i++) { - lwall[i] = right - lwall[i]; + walltexcoords.UPos[i] = right - walltexcoords.UPos[i]; } } @@ -305,7 +305,7 @@ namespace swrenderer // be set 1 if we need to draw on the lower wall. In all other cases, // needrepeat will be 0, and the while will fail. mceilingclip = RenderOpaquePass::Instance()->floorclip; - mfloorclip = wallbottom; + mfloorclip = wallbottom.ScreenY; } while (needrepeat--); colfunc = basecolfunc; @@ -316,7 +316,7 @@ namespace swrenderer void RenderDecal::DrawColumn(int x, FTexture *WallSpriteTile, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip) { - float iscale = swall[x] * maskedScaleY; + float iscale = walltexcoords.VStep[x] * maskedScaleY; double spryscale = 1 / iscale; double sprtopscreen; if (sprflipvert) @@ -324,6 +324,6 @@ namespace swrenderer else sprtopscreen = CenterY - texturemid * spryscale; - R_DrawMaskedColumn(x, FLOAT2FIXED(iscale), WallSpriteTile, lwall[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); + R_DrawMaskedColumn(x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); } } diff --git a/src/swrenderer/things/r_wallsprite.cpp b/src/swrenderer/things/r_wallsprite.cpp index 76691e07d2..8951724b30 100644 --- a/src/swrenderer/things/r_wallsprite.cpp +++ b/src/swrenderer/things/r_wallsprite.cpp @@ -151,7 +151,7 @@ namespace swrenderer return; FWallTmapVals WallT; WallT.InitFromWallCoords(&spr->wallc); - PrepWall(swall, lwall, spr->pic->GetWidth() << FRACBITS, x1, x2, WallT); + walltexcoords.Project(spr->pic->GetWidth() << FRACBITS, x1, x2, WallT); iyscale = 1 / spr->yscale; double texturemid = (spr->gzt - ViewPos.Z) * iyscale; if (spr->renderflags & RF_XFLIP) @@ -160,7 +160,7 @@ namespace swrenderer for (int i = x1; i < x2; i++) { - lwall[i] = right - lwall[i]; + walltexcoords.UPos[i] = right - walltexcoords.UPos[i]; } } // Prepare lighting @@ -238,7 +238,7 @@ namespace swrenderer void RenderWallSprite::DrawColumn(int x, FTexture *WallSpriteTile, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip) { - float iscale = swall[x] * maskedScaleY; + float iscale = walltexcoords.VStep[x] * maskedScaleY; double spryscale = 1 / iscale; double sprtopscreen; if (sprflipvert) @@ -246,6 +246,6 @@ namespace swrenderer else sprtopscreen = CenterY - texturemid * spryscale; - R_DrawMaskedColumn(x, FLOAT2FIXED(iscale), WallSpriteTile, lwall[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); + R_DrawMaskedColumn(x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip); } }