Refactor wall setup into ProjectedWallLine and ProjectWallTexcoords

This commit is contained in:
Magnus Norddahl 2017-01-24 06:50:17 +01:00
parent 12271cbfb5
commit ac74a7a1e0
8 changed files with 164 additions and 160 deletions

View file

@ -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;

View file

@ -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;
};
}

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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);
}
}