Further isolate texture coordinate calculations to r_wallsetup

This commit is contained in:
Magnus Norddahl 2019-11-08 03:46:07 +01:00
parent c64fafc490
commit 62ec165d28
16 changed files with 176 additions and 174 deletions

View file

@ -418,10 +418,6 @@ namespace swrenderer
(mFloorClipped != ProjectedWallCull::OutsideAbove || !sidedef->GetTexture(side_t::bottom).isValid()) && (mFloorClipped != ProjectedWallCull::OutsideAbove || !sidedef->GetTexture(side_t::bottom).isValid()) &&
(WallC.sz1 >= TOO_CLOSE_Z && WallC.sz2 >= TOO_CLOSE_Z)) (WallC.sz1 >= TOO_CLOSE_Z && WallC.sz2 >= TOO_CLOSE_Z))
{ {
float *swal;
fixed_t *lwal;
int i;
maskedtexture = true; maskedtexture = true;
// kg3D - backup for mid and fake walls // kg3D - backup for mid and fake walls
@ -429,16 +425,12 @@ namespace swrenderer
memcpy(draw_segment->bkup, &Thread->OpaquePass->ceilingclip[start], sizeof(short)*(stop - start)); memcpy(draw_segment->bkup, &Thread->OpaquePass->ceilingclip[start], sizeof(short)*(stop - start));
draw_segment->bFogBoundary = IsFogBoundary(mFrontSector, mBackSector); draw_segment->bFogBoundary = IsFogBoundary(mFrontSector, mBackSector);
if (sidedef->GetTexture(side_t::mid).isValid() || draw_segment->Has3DFloorWalls()) bool is_translucent = sidedef->GetTexture(side_t::mid).isValid() || draw_segment->Has3DFloorWalls();
if (is_translucent)
{ {
if (sidedef->GetTexture(side_t::mid).isValid()) if (sidedef->GetTexture(side_t::mid).isValid())
draw_segment->SetHas3DFloorMidTexture(); draw_segment->SetHas3DFloorMidTexture();
draw_segment->maskedtexturecol = Thread->FrameMemory->AllocMemory<fixed_t>(stop - start);
draw_segment->swall = Thread->FrameMemory->AllocMemory<float>(stop - start);
lwal = draw_segment->maskedtexturecol;
swal = draw_segment->swall;
FTexture *tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true); FTexture *tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true);
FSoftwareTexture *pic = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr; FSoftwareTexture *pic = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr;
double yscale = (pic ? pic->GetScale().Y : 1.0) * sidedef->GetTextureYScale(side_t::mid); double yscale = (pic ? pic->GetScale().Y : 1.0) * sidedef->GetTextureYScale(side_t::mid);
@ -449,40 +441,13 @@ namespace swrenderer
xoffset = xs_RoundToInt(xoffset * lwallscale); xoffset = xs_RoundToInt(xoffset * lwallscale);
} }
for (i = start; i < stop; i++) draw_segment->texcoords.Set(Thread, walltexcoords, start, stop, xoffset, yscale);
{
*lwal++ = walltexcoords.UPos[i] + xoffset;
*swal++ = walltexcoords.VStep[i];
}
double istart = draw_segment->swall[0] * yscale;
double iend = *(swal - 1) * yscale;
#if 0
///This was for avoiding overflow when using fixed point. It might not be needed anymore.
const double mini = 3 / 65536.0;
if (istart < mini && istart >= 0) istart = mini;
if (istart > -mini && istart < 0) istart = -mini;
if (iend < mini && iend >= 0) iend = mini;
if (iend > -mini && iend < 0) iend = -mini;
#endif
istart = 1 / istart;
iend = 1 / iend;
draw_segment->yscale = (float)yscale;
draw_segment->iscale = (float)istart;
if (stop - start > 1)
{
draw_segment->iscalestep = float((iend - istart) / (stop - start - 1));
}
else
{
draw_segment->iscalestep = 0;
}
} }
draw_segment->light = mLight.GetLightPos(start); draw_segment->light = mLight.GetLightPos(start);
draw_segment->lightstep = mLight.GetLightStep(); draw_segment->lightstep = mLight.GetLightStep();
if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr) if (draw_segment->bFogBoundary || is_translucent)
{ {
Thread->DrawSegments->PushTranslucent(draw_segment); Thread->DrawSegments->PushTranslucent(draw_segment);
} }
@ -1118,7 +1083,7 @@ namespace swrenderer
double yscale = rw_pic->GetScale().Y * mTopPart.TextureScaleV; double yscale = rw_pic->GetScale().Y * mTopPart.TextureScaleV;
if (xscale != lwallscale) if (xscale != lwallscale)
{ {
walltexcoords.ProjectPos(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT); walltexcoords.Project(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT);
lwallscale = xscale; lwallscale = xscale;
} }
fixed_t offset; fixed_t offset;
@ -1136,7 +1101,7 @@ namespace swrenderer
} }
RenderWallPart renderWallpart(Thread); RenderWallPart renderWallpart(Thread);
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallupper.ScreenY, mTopPart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mBackCeilingZ1, mBackCeilingZ2), false, false, OPAQUE, offset, mLight, GetLightList()); renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallupper.ScreenY, mTopPart.TextureMid, walltexcoords, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mBackCeilingZ1, mBackCeilingZ2), false, false, OPAQUE, offset, mLight, GetLightList());
} }
void SWRenderLine::RenderMiddleTexture(int x1, int x2) void SWRenderLine::RenderMiddleTexture(int x1, int x2)
@ -1149,7 +1114,7 @@ namespace swrenderer
double yscale = rw_pic->GetScale().Y * mMiddlePart.TextureScaleV; double yscale = rw_pic->GetScale().Y * mMiddlePart.TextureScaleV;
if (xscale != lwallscale) if (xscale != lwallscale)
{ {
walltexcoords.ProjectPos(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT); walltexcoords.Project(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT);
lwallscale = xscale; lwallscale = xscale;
} }
fixed_t offset; fixed_t offset;
@ -1167,7 +1132,7 @@ namespace swrenderer
} }
RenderWallPart renderWallpart(Thread); RenderWallPart renderWallpart(Thread);
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallbottom.ScreenY, mMiddlePart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, offset, mLight, GetLightList()); renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walltop.ScreenY, wallbottom.ScreenY, mMiddlePart.TextureMid, walltexcoords, yscale, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, offset, mLight, GetLightList());
} }
void SWRenderLine::RenderBottomTexture(int x1, int x2) void SWRenderLine::RenderBottomTexture(int x1, int x2)
@ -1181,7 +1146,7 @@ namespace swrenderer
double yscale = rw_pic->GetScale().Y * mBottomPart.TextureScaleV; double yscale = rw_pic->GetScale().Y * mBottomPart.TextureScaleV;
if (xscale != lwallscale) if (xscale != lwallscale)
{ {
walltexcoords.ProjectPos(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT); walltexcoords.Project(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength*xscale, WallC.sx1, WallC.sx2, WallT);
lwallscale = xscale; lwallscale = xscale;
} }
fixed_t offset; fixed_t offset;
@ -1199,7 +1164,7 @@ namespace swrenderer
} }
RenderWallPart renderWallpart(Thread); RenderWallPart renderWallpart(Thread);
renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walllower.ScreenY, wallbottom.ScreenY, mBottomPart.TextureMid, walltexcoords.VStep, walltexcoords.UPos, yscale, MAX(mBackFloorZ1, mBackFloorZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, offset, mLight, GetLightList()); renderWallpart.Render(mFrontSector, mLineSegment, WallC, rw_pic, x1, x2, walllower.ScreenY, wallbottom.ScreenY, mBottomPart.TextureMid, walltexcoords, yscale, MAX(mBackFloorZ1, mBackFloorZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, offset, mLight, GetLightList());
} }
FLightNode *SWRenderLine::GetLightList() FLightNode *SWRenderLine::GetLightList()

View file

@ -115,7 +115,7 @@ namespace swrenderer
RenderFogBoundary renderfog; RenderFogBoundary renderfog;
renderfog.Render(Thread, x1, x2, mceilingclip, mfloorclip, mLight); renderfog.Render(Thread, x1, x2, mceilingclip, mfloorclip, mLight);
if (ds->maskedtexturecol == nullptr) if (!ds->texcoords)
renderwall = false; renderwall = false;
} }
else if ((ds->Has3DFloorWalls() && !ds->Has3DFloorMidTexture()) || !visible) else if ((ds->Has3DFloorWalls() && !ds->Has3DFloorMidTexture()) || !visible)
@ -156,11 +156,7 @@ namespace swrenderer
const short *mfloorclip = ds->sprbottomclip - ds->x1; const short *mfloorclip = ds->sprbottomclip - ds->x1;
const short *mceilingclip = ds->sprtopclip - ds->x1; const short *mceilingclip = ds->sprtopclip - ds->x1;
float *MaskedSWall = ds->swall - ds->x1; float MaskedScaleY = ds->texcoords.yscale;
float MaskedScaleY = ds->yscale;
fixed_t *maskedtexturecol = ds->maskedtexturecol - ds->x1;
double spryscale = ds->iscale + ds->iscalestep * (x1 - ds->x1);
float rw_scalestep = ds->iscalestep;
// find positioning // find positioning
double texheight = tex->GetScaledHeightDouble(); double texheight = tex->GetScaledHeightDouble();
@ -311,19 +307,12 @@ namespace swrenderer
for (int x = x1; x < x2; ++x) for (int x = x1; x < x2; ++x)
{ {
if (needslight) if (needslight)
{
columndrawerargs.SetLight(lightpos, mLight.GetLightLevel(), mLight.GetFoggy(), Thread->Viewport.get()); columndrawerargs.SetLight(lightpos, mLight.GetLightLevel(), mLight.GetFoggy(), Thread->Viewport.get());
lightpos += mLight.GetLightStep();
}
fixed_t iscale = xs_Fix<16>::ToFix(MaskedSWall[x] * MaskedScaleY); columndrawerargs.DrawMaskedColumn(Thread, x, tex, ds->texcoords, texturemid, MaskedScaleY, sprflipvert, mfloorclip, mceilingclip, renderstyle);
double sprtopscreen;
if (sprflipvert)
sprtopscreen = viewport->CenterY + texturemid * spryscale;
else
sprtopscreen = viewport->CenterY - texturemid * spryscale;
columndrawerargs.DrawMaskedColumn(Thread, x, iscale, tex, maskedtexturecol[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, renderstyle);
lightpos += mLight.GetLightStep();
spryscale += rw_scalestep;
} }
} }
} }
@ -390,7 +379,7 @@ namespace swrenderer
bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0; bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0;
RenderWallPart renderWallpart(Thread); RenderWallPart renderWallpart(Thread);
renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, mceilingclip, mfloorclip, texturemid, MaskedSWall, maskedtexturecol, ds->yscale, top, bot, true, additive, alpha, rw_offset, mLight, nullptr); renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, mceilingclip, mfloorclip, texturemid, ds->texcoords, ds->texcoords.yscale, top, bot, true, additive, alpha, rw_offset, mLight, nullptr);
} }
return false; return false;
@ -412,9 +401,6 @@ namespace swrenderer
const short *mfloorclip = ds->sprbottomclip - ds->x1; const short *mfloorclip = ds->sprbottomclip - ds->x1;
const short *mceilingclip = ds->sprtopclip - ds->x1; const short *mceilingclip = ds->sprtopclip - ds->x1;
//double spryscale = ds->iscale + ds->iscalestep * (x1 - ds->x1);
float *MaskedSWall = ds->swall - ds->x1;
// find positioning // find positioning
side_t *scaledside; side_t *scaledside;
side_t::ETexpart scaledpart; side_t::ETexpart scaledpart;
@ -478,13 +464,13 @@ namespace swrenderer
} }
ProjectedWallTexcoords walltexcoords; ProjectedWallTexcoords walltexcoords;
walltexcoords.ProjectPos(Thread->Viewport.get(), curline->sidedef->TexelLength*xscale, ds->WallC.sx1, ds->WallC.sx2, WallT); walltexcoords.Project(Thread->Viewport.get(), curline->sidedef->TexelLength*xscale, ds->WallC.sx1, ds->WallC.sx2, WallT);
double top, bot; double top, bot;
GetMaskedWallTopBottom(ds, top, bot); GetMaskedWallTopBottom(ds, top, bot);
RenderWallPart renderWallpart(Thread); RenderWallPart renderWallpart(Thread);
renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, MaskedSWall, walltexcoords.UPos, yscale, top, bot, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha, rw_offset, mLight, nullptr); renderWallpart.Render(frontsector, curline, WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, texturemid, walltexcoords, yscale, top, bot, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha, rw_offset, mLight, nullptr);
RenderDecal::RenderDecals(Thread, curline->sidedef, ds, curline, mLight, wallupper.ScreenY, walllower.ScreenY, true); RenderDecal::RenderDecals(Thread, curline->sidedef, ds, curline, mLight, wallupper.ScreenY, walllower.ScreenY, true);
} }

View file

@ -54,7 +54,7 @@
namespace swrenderer namespace swrenderer
{ {
void RenderWallPart::ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal) void RenderWallPart::ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal)
{ {
if (rw_pic == nullptr) if (rw_pic == nullptr)
return; return;
@ -410,7 +410,7 @@ namespace swrenderer
} }
} }
void RenderWallPart::ProcessStripedWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal) void RenderWallPart::ProcessStripedWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal)
{ {
ProjectedWallLine most1, most2, most3; ProjectedWallLine most1, most2, most3;
const short *up; const short *up;
@ -445,7 +445,7 @@ namespace swrenderer
ProcessNormalWall(up, dwal, texturemid, swal, lwal); ProcessNormalWall(up, dwal, texturemid, swal, lwal);
} }
void RenderWallPart::ProcessWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal) void RenderWallPart::ProcessWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal)
{ {
CameraLight *cameraLight = CameraLight::Instance(); CameraLight *cameraLight = CameraLight::Instance();
if (cameraLight->FixedColormap() != NULL || cameraLight->FixedLightLevel() >= 0 || !(frontsector->e && frontsector->e->XFloor.lightlist.Size())) if (cameraLight->FixedColormap() != NULL || cameraLight->FixedLightLevel() >= 0 || !(frontsector->e && frontsector->e->XFloor.lightlist.Size()))
@ -469,7 +469,7 @@ namespace swrenderer
// //
//============================================================================= //=============================================================================
void RenderWallPart::ProcessWallNP2(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal, double top, double bot) void RenderWallPart::ProcessWallNP2(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal, double top, double bot)
{ {
ProjectedWallLine most1, most2, most3; ProjectedWallLine most1, most2, most3;
double texheight = rw_pic->GetHeight(); double texheight = rw_pic->GetHeight();
@ -530,7 +530,7 @@ namespace swrenderer
} }
} }
void RenderWallPart::Render(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, FSoftwareTexture *pic, int x1, int x2, const short *walltop, const short *wallbottom, double texturemid, float *swall, fixed_t *lwall, double yscale, double top, double bottom, bool mask, bool additive, fixed_t alpha, fixed_t xoffset, const ProjectedWallLight &light, FLightNode *light_list) void RenderWallPart::Render(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, FSoftwareTexture *pic, int x1, int x2, const short *walltop, const short *wallbottom, double texturemid, const ProjectedWallTexcoords& texcoords, double yscale, double top, double bottom, bool mask, bool additive, fixed_t alpha, fixed_t xoffset, const ProjectedWallLight &light, FLightNode *light_list)
{ {
this->x1 = x1; this->x1 = x1;
this->x2 = x2; this->x2 = x2;
@ -550,11 +550,39 @@ namespace swrenderer
if (rw_pic->GetHeight() != 1 << rw_pic->GetHeightBits()) if (rw_pic->GetHeight() != 1 << rw_pic->GetHeightBits())
{ {
ProcessWallNP2(walltop, wallbottom, texturemid, swall, lwall, top, bottom); ProcessWallNP2(walltop, wallbottom, texturemid, texcoords.VStep, texcoords.UPos, top, bottom);
} }
else else
{ {
ProcessWall(walltop, wallbottom, texturemid, swall, lwall); ProcessWall(walltop, wallbottom, texturemid, texcoords.VStep, texcoords.UPos);
}
}
void RenderWallPart::Render(sector_t* frontsector, seg_t* curline, const FWallCoords& WallC, FSoftwareTexture* pic, int x1, int x2, const short* walltop, const short* wallbottom, double texturemid, const DrawSegmentWallTexcoords& texcoords, double yscale, double top, double bottom, bool mask, bool additive, fixed_t alpha, fixed_t xoffset, const ProjectedWallLight& light, FLightNode* light_list)
{
this->x1 = x1;
this->x2 = x2;
this->frontsector = frontsector;
this->curline = curline;
this->WallC = WallC;
this->yrepeat = yscale;
this->mLight = light;
this->xoffset = xoffset;
this->light_list = light_list;
this->rw_pic = pic;
this->mask = mask;
this->additive = additive;
this->alpha = alpha;
Thread->PrepareTexture(pic, DefaultRenderStyle()); // Get correct render style? Shaded won't get here.
if (rw_pic->GetHeight() != 1 << rw_pic->GetHeightBits())
{
ProcessWallNP2(walltop, wallbottom, texturemid, texcoords.VStep, texcoords.UPos, top, bottom);
}
else
{
ProcessWall(walltop, wallbottom, texturemid, texcoords.VStep, texcoords.UPos);
} }
} }

View file

@ -55,8 +55,7 @@ namespace swrenderer
const short *walltop, const short *walltop,
const short *wallbottom, const short *wallbottom,
double texturemid, double texturemid,
float *swall, const ProjectedWallTexcoords &texcoords,
fixed_t *lwall,
double yscale, double yscale,
double top, double top,
double bottom, double bottom,
@ -67,13 +66,34 @@ namespace swrenderer
const ProjectedWallLight &light, const ProjectedWallLight &light,
FLightNode *light_list); FLightNode *light_list);
void Render(
sector_t* frontsector,
seg_t* curline,
const FWallCoords& WallC,
FSoftwareTexture* rw_pic,
int x1,
int x2,
const short* walltop,
const short* wallbottom,
double texturemid,
const DrawSegmentWallTexcoords& texcoords,
double yscale,
double top,
double bottom,
bool mask,
bool additive,
fixed_t alpha,
fixed_t xoffset,
const ProjectedWallLight& light,
FLightNode* light_list);
RenderThread *Thread = nullptr; RenderThread *Thread = nullptr;
private: private:
void ProcessWallNP2(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal, double top, double bot); void ProcessWallNP2(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal, double top, double bot);
void ProcessWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal); void ProcessWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal);
void ProcessStripedWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal); void ProcessStripedWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal);
void ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, float *swal, fixed_t *lwal); void ProcessNormalWall(const short *uwal, const short *dwal, double texturemid, const float *swal, const fixed_t *lwal);
void SetLights(WallDrawerArgs &drawerargs, int x, int y1); void SetLights(WallDrawerArgs &drawerargs, int x, int y1);
int x1 = 0; int x1 = 0;

View file

@ -170,7 +170,7 @@ namespace swrenderer
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
void ProjectedWallTexcoords::Project(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT) void ProjectedWallTexcoords::Project(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT, bool flipx)
{ {
float uOverZ = WallT.UoverZorg + WallT.UoverZstep * (float)(x1 + 0.5 - viewport->CenterX); float uOverZ = WallT.UoverZorg + WallT.UoverZstep * (float)(x1 + 0.5 - viewport->CenterX);
float invZ = WallT.InvZorg + WallT.InvZstep * (float)(x1 + 0.5 - viewport->CenterX); float invZ = WallT.InvZorg + WallT.InvZstep * (float)(x1 + 0.5 - viewport->CenterX);
@ -206,39 +206,45 @@ namespace swrenderer
invZ += zGradient; invZ += zGradient;
} }
} }
if (flipx)
{
int right = (int)walxrepeat - 1;
for (int i = x1; i < x2; i++)
{
UPos[i] = right - UPos[i];
}
}
} }
void ProjectedWallTexcoords::ProjectPos(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT) /////////////////////////////////////////////////////////////////////////
void DrawSegmentWallTexcoords::Set(RenderThread* thread, const ProjectedWallTexcoords& texcoords, int x1, int x2, fixed_t xoffset, double yscale)
{ {
float uOverZ = WallT.UoverZorg + WallT.UoverZstep * (float)(x1 + 0.5 - viewport->CenterX); UPos = thread->FrameMemory->AllocMemory<fixed_t>(x2 - x1) - x1;
float invZ = WallT.InvZorg + WallT.InvZstep * (float)(x1 + 0.5 - viewport->CenterX); VStep = thread->FrameMemory->AllocMemory<float>(x2 - x1) - x1;
float uGradient = WallT.UoverZstep;
float zGradient = WallT.InvZstep;
float xrepeat = (float)fabs(walxrepeat);
if (walxrepeat < 0.0f) for (int i = x1; i < x2; i++)
{ {
for (int x = x1; x < x2; x++) UPos[i] = texcoords.UPos[i] + xoffset;
{ VStep[i] = texcoords.VStep[i];
float u = uOverZ / invZ * xrepeat - xrepeat; }
UPos[x] = (fixed_t)(u * FRACUNIT); double istart = VStep[x1] * yscale;
double iend = VStep[x2 - 1] * yscale;
uOverZ += uGradient; istart = 1 / istart;
invZ += zGradient; iend = 1 / iend;
}
this->yscale = (float)yscale;
iscale = (float)istart;
if (x2 - x1 > 1)
{
iscalestep = float((iend - istart) / (x2 - x1 - 1));
} }
else else
{ {
for (int x = x1; x < x2; x++) iscalestep = 0;
{
float u = uOverZ / invZ * xrepeat;
UPos[x] = (fixed_t)(u * FRACUNIT);
uOverZ += uGradient;
invZ += zGradient;
}
} }
} }

View file

@ -50,11 +50,33 @@ namespace swrenderer
class ProjectedWallTexcoords class ProjectedWallTexcoords
{ {
public: public:
void Project(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT, bool flipx = false);
private:
float VStep[MAXWIDTH]; // swall float VStep[MAXWIDTH]; // swall
fixed_t UPos[MAXWIDTH]; // lwall fixed_t UPos[MAXWIDTH]; // lwall
void Project(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT); friend class DrawSegmentWallTexcoords;
void ProjectPos(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT); friend class RenderWallPart;
friend class SpriteDrawerArgs;
};
class DrawSegmentWallTexcoords
{
public:
void Set(RenderThread *thread, const ProjectedWallTexcoords& texcoords, int x1, int x2, fixed_t xoffset, double yscale);
float yscale;
float iscale, iscalestep;
explicit operator bool() const { return UPos; }
private:
float* VStep = nullptr; // swall
fixed_t* UPos = nullptr; // maskedtexturecol
friend class RenderWallPart;
friend class SpriteDrawerArgs;
}; };
class ProjectedWallLight class ProjectedWallLight

View file

@ -214,8 +214,6 @@ namespace swrenderer
draw_segment->silhouette = SIL_BOTH; draw_segment->silhouette = SIL_BOTH;
draw_segment->sprbottomclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left); draw_segment->sprbottomclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left);
draw_segment->sprtopclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left); draw_segment->sprtopclip = Thread->FrameMemory->AllocMemory<short>(pl->right - pl->left);
draw_segment->maskedtexturecol = nullptr;
draw_segment->swall = nullptr;
draw_segment->bFogBoundary = false; draw_segment->bFogBoundary = false;
draw_segment->curline = nullptr; draw_segment->curline = nullptr;
memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short)); memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short));

View file

@ -156,7 +156,7 @@ namespace swrenderer
// [ZZ] the same as above // [ZZ] the same as above
if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq) if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq)
continue; continue;
if (ds->maskedtexturecol || ds->bFogBoundary) if (ds->texcoords || ds->bFogBoundary)
{ {
RenderDrawSegment renderer(Thread); RenderDrawSegment renderer(Thread);
renderer.Render(ds, ds->x1, ds->x2, clip3DFloor); renderer.Render(ds, ds->x1, ds->x2, clip3DFloor);

View file

@ -29,18 +29,16 @@ namespace swrenderer
{ {
seg_t *curline; seg_t *curline;
float light, lightstep; float light, lightstep;
float iscale, iscalestep;
short x1, x2; // Same as sx1 and sx2, but clipped to the drawseg short x1, x2; // Same as sx1 and sx2, but clipped to the drawseg
FWallCoords WallC; FWallCoords WallC;
float yscale;
uint8_t silhouette = 0; // 0=none, 1=bottom, 2=top, 3=both uint8_t silhouette = 0; // 0=none, 1=bottom, 2=top, 3=both
bool bFogBoundary = false; bool bFogBoundary = false;
DrawSegmentWallTexcoords texcoords;
// Pointers to lists for sprite clipping, all three adjusted so [x1] is first value. // Pointers to lists for sprite clipping, all three adjusted so [x1] is first value.
short *sprtopclip = nullptr; short *sprtopclip = nullptr;
short *sprbottomclip = nullptr; short *sprbottomclip = nullptr;
fixed_t *maskedtexturecol = nullptr;
float *swall = nullptr;
short *bkup = nullptr; // sprtopclip backup, for mid and fake textures short *bkup = nullptr; // sprtopclip backup, for mid and fake textures
bool sprclipped = false; // True if draw segment was used for clipping sprites bool sprclipped = false; // True if draw segment was used for clipping sprites

View file

@ -242,18 +242,7 @@ namespace swrenderer
} }
ProjectedWallTexcoords walltexcoords; ProjectedWallTexcoords walltexcoords;
walltexcoords.Project(thread->Viewport.get(), WallSpriteTile->GetWidth(), x1, x2, WallT); walltexcoords.Project(thread->Viewport.get(), WallSpriteTile->GetWidth(), x1, x2, WallT, flipx);
if (flipx)
{
int i;
int right = (WallSpriteTile->GetWidth() << FRACBITS) - 1;
for (i = x1; i < x2; i++)
{
walltexcoords.UPos[i] = right - walltexcoords.UPos[i];
}
}
// Prepare lighting // Prepare lighting
usecolormap = light.GetBaseColormap(); usecolormap = light.GetBaseColormap();
@ -302,7 +291,7 @@ namespace swrenderer
{ // calculate lighting { // calculate lighting
drawerargs.SetLight(lightpos, light.GetLightLevel(), light.GetFoggy(), thread->Viewport.get()); drawerargs.SetLight(lightpos, light.GetLightLevel(), light.GetFoggy(), thread->Viewport.get());
} }
DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, decal->RenderStyle); drawerargs.DrawMaskedColumn(thread, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, decal->RenderStyle);
lightpos += light.GetLightStep(); lightpos += light.GetLightStep();
x++; x++;
} }
@ -315,19 +304,4 @@ namespace swrenderer
mfloorclip = wallbottom; mfloorclip = wallbottom;
} while (needrepeat--); } while (needrepeat--);
} }
void RenderDecal::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FSoftwareTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style)
{
auto viewport = thread->Viewport.get();
float iscale = walltexcoords.VStep[x] * maskedScaleY;
double spryscale = 1 / iscale;
double sprtopscreen;
if (sprflipvert)
sprtopscreen = viewport->CenterY + texturemid * spryscale;
else
sprtopscreen = viewport->CenterY - texturemid * spryscale;
drawerargs.DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style);
}
} }

View file

@ -16,6 +16,5 @@ namespace swrenderer
private: private:
static void Render(RenderThread *thread, side_t *wall, DBaseDecal *first, DrawSegment *clipper, seg_t *curline, const ProjectedWallLight &light, const short *walltop, const short *wallbottom, bool drawsegPass); static void Render(RenderThread *thread, side_t *wall, DBaseDecal *first, DrawSegment *clipper, seg_t *curline, const ProjectedWallLight &light, const short *walltop, const short *wallbottom, bool drawsegPass);
static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FSoftwareTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style);
}; };
} }

View file

@ -405,9 +405,7 @@ namespace swrenderer
DrawSegment *ds = segmentlist->Segment(index); DrawSegment *ds = segmentlist->Segment(index);
// determine if the drawseg obscures the sprite // determine if the drawseg obscures the sprite
if (ds->x1 >= x2 || ds->x2 <= x1 || if (ds->x1 >= x2 || ds->x2 <= x1 || (!(ds->silhouette & SIL_BOTH) && !ds->texcoords && !ds->bFogBoundary))
(!(ds->silhouette & SIL_BOTH) && ds->maskedtexturecol == nullptr &&
!ds->bFogBoundary))
{ {
// does not cover sprite // does not cover sprite
continue; continue;

View file

@ -175,19 +175,10 @@ namespace swrenderer
WallT.InitFromWallCoords(thread, &spr->wallc); WallT.InitFromWallCoords(thread, &spr->wallc);
ProjectedWallTexcoords walltexcoords; ProjectedWallTexcoords walltexcoords;
walltexcoords.Project(thread->Viewport.get(), spr->pic->GetWidth() << FRACBITS, x1, x2, WallT); walltexcoords.Project(thread->Viewport.get(), spr->pic->GetWidth(), x1, x2, WallT, spr->renderflags & RF_XFLIP);
iyscale = 1 / spr->yscale; iyscale = 1 / spr->yscale;
double texturemid = (spr->gzt - thread->Viewport->viewpoint.Pos.Z) * iyscale; double texturemid = (spr->gzt - thread->Viewport->viewpoint.Pos.Z) * iyscale;
if (spr->renderflags & RF_XFLIP)
{
int right = (spr->pic->GetWidth() << FRACBITS) - 1;
for (int i = x1; i < x2; i++)
{
walltexcoords.UPos[i] = right - walltexcoords.UPos[i];
}
}
// Prepare lighting // Prepare lighting
@ -238,24 +229,9 @@ namespace swrenderer
drawerargs.SetLight(light, spr->sector->lightlevel, spr->foggy, thread->Viewport.get()); drawerargs.SetLight(light, spr->sector->lightlevel, spr->foggy, thread->Viewport.get());
} }
if (!translucentPass->ClipSpriteColumnWithPortals(x, spr)) if (!translucentPass->ClipSpriteColumnWithPortals(x, spr))
DrawColumn(thread, drawerargs, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, spr->RenderStyle); drawerargs.DrawMaskedColumn(thread, x, WallSpriteTile, walltexcoords, texturemid, maskedScaleY, sprflipvert, mfloorclip, mceilingclip, spr->RenderStyle);
light += lightstep; light += lightstep;
x++; x++;
} }
} }
void RenderWallSprite::DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FSoftwareTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style)
{
auto viewport = thread->Viewport.get();
float iscale = walltexcoords.VStep[x] * maskedScaleY;
double spryscale = 1 / iscale;
double sprtopscreen;
if (sprflipvert)
sprtopscreen = viewport->CenterY + texturemid * spryscale;
else
sprtopscreen = viewport->CenterY - texturemid * spryscale;
drawerargs.DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style);
}
} }

View file

@ -17,8 +17,6 @@ namespace swrenderer
void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) override; void Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor) override;
private: private:
static void DrawColumn(RenderThread *thread, SpriteDrawerArgs &drawerargs, int x, FSoftwareTexture *WallSpriteTile, const ProjectedWallTexcoords &walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style);
FWallCoords wallc; FWallCoords wallc;
uint32_t Translation = 0; uint32_t Translation = 0;
uint32_t FillColor = 0; uint32_t FillColor = 0;

View file

@ -43,6 +43,36 @@ namespace swrenderer
colfunc = &SWPixelFormatDrawers::DrawColumn; colfunc = &SWPixelFormatDrawers::DrawColumn;
} }
void SpriteDrawerArgs::DrawMaskedColumn(RenderThread* thread, int x, FSoftwareTexture* WallSpriteTile, const ProjectedWallTexcoords& walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short* mfloorclip, const short* mceilingclip, FRenderStyle style)
{
auto viewport = thread->Viewport.get();
float iscale = walltexcoords.VStep[x] * maskedScaleY;
double spryscale = 1 / iscale;
double sprtopscreen;
if (sprflipvert)
sprtopscreen = viewport->CenterY + texturemid * spryscale;
else
sprtopscreen = viewport->CenterY - texturemid * spryscale;
DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style);
}
void SpriteDrawerArgs::DrawMaskedColumn(RenderThread* thread, int x, FSoftwareTexture* WallSpriteTile, const DrawSegmentWallTexcoords& walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short* mfloorclip, const short* mceilingclip, FRenderStyle style)
{
auto viewport = thread->Viewport.get();
float iscale = walltexcoords.VStep[x] * maskedScaleY;
double spryscale = 1 / iscale;
double sprtopscreen;
if (sprflipvert)
sprtopscreen = viewport->CenterY + texturemid * spryscale;
else
sprtopscreen = viewport->CenterY - texturemid * spryscale;
DrawMaskedColumn(thread, x, FLOAT2FIXED(iscale), WallSpriteTile, walltexcoords.UPos[x], spryscale, sprtopscreen, sprflipvert, mfloorclip, mceilingclip, style);
}
void SpriteDrawerArgs::DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FSoftwareTexture *tex, fixed_t col, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style, bool unmasked) void SpriteDrawerArgs::DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FSoftwareTexture *tex, fixed_t col, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style, bool unmasked)
{ {
if (x < thread->X1 || x >= thread->X2) if (x < thread->X1 || x >= thread->X2)

View file

@ -9,6 +9,8 @@ struct FLightNode;
namespace swrenderer namespace swrenderer
{ {
class RenderThread; class RenderThread;
class ProjectedWallTexcoords;
class DrawSegmentWallTexcoords;
class VoxelBlock class VoxelBlock
{ {
@ -33,6 +35,8 @@ namespace swrenderer
void SetSolidColor(int color) { dc_color = color; dc_color_bgra = GPalette.BaseColors[color]; } void SetSolidColor(int color) { dc_color = color; dc_color_bgra = GPalette.BaseColors[color]; }
void SetDynamicLight(uint32_t color) { dynlightcolor = color; } void SetDynamicLight(uint32_t color) { dynlightcolor = color; }
void DrawMaskedColumn(RenderThread* thread, int x, FSoftwareTexture* WallSpriteTile, const ProjectedWallTexcoords& walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short* mfloorclip, const short* mceilingclip, FRenderStyle style);
void DrawMaskedColumn(RenderThread* thread, int x, FSoftwareTexture* WallSpriteTile, const DrawSegmentWallTexcoords& walltexcoords, double texturemid, float maskedScaleY, bool sprflipvert, const short* mfloorclip, const short* mceilingclip, FRenderStyle style);
void DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FSoftwareTexture *texture, fixed_t column, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style, bool unmasked = false); void DrawMaskedColumn(RenderThread *thread, int x, fixed_t iscale, FSoftwareTexture *texture, fixed_t column, double spryscale, double sprtopscreen, bool sprflipvert, const short *mfloorclip, const short *mceilingclip, FRenderStyle style, bool unmasked = false);
void FillColumn(RenderThread *thread); void FillColumn(RenderThread *thread);
void DrawVoxelBlocks(RenderThread *thread, const VoxelBlock *blocks, int blockcount); void DrawVoxelBlocks(RenderThread *thread, const VoxelBlock *blocks, int blockcount);