diff --git a/src/rendering/swrenderer/line/r_fogboundary.cpp b/src/rendering/swrenderer/line/r_fogboundary.cpp index c17f900194..09a6bce20a 100644 --- a/src/rendering/swrenderer/line/r_fogboundary.cpp +++ b/src/rendering/swrenderer/line/r_fogboundary.cpp @@ -54,15 +54,12 @@ namespace swrenderer { - void RenderFogBoundary::Render(RenderThread *thread, int x1, int x2, const DrawSegmentClipInfo& clip, const ProjectedWallLight &wallLight) + void RenderFogBoundary::Render(RenderThread *thread, int x1, int x2, const short* uclip, const short* dclip, const ProjectedWallLight &wallLight) { // This is essentially the same as R_MapVisPlane but with an extra step // to create new horizontal spans whenever the light changes enough that // we need to use a new colormap. - const short* uclip = clip.sprtopclip; - const short* dclip = clip.sprbottomclip; - int wallshade = LightVisibility::LightLevelToShade(wallLight.GetLightLevel(), wallLight.GetFoggy(), thread->Viewport.get()); int x = x2 - 1; int t2 = uclip[x]; diff --git a/src/rendering/swrenderer/line/r_fogboundary.h b/src/rendering/swrenderer/line/r_fogboundary.h index 4f7696cd69..312393f9c1 100644 --- a/src/rendering/swrenderer/line/r_fogboundary.h +++ b/src/rendering/swrenderer/line/r_fogboundary.h @@ -31,7 +31,7 @@ namespace swrenderer class RenderFogBoundary { public: - void Render(RenderThread *thread, int x1, int x2, const DrawSegmentClipInfo &clip, const ProjectedWallLight &wallLight); + void Render(RenderThread *thread, int x1, int x2, const short* uclip, const short* dclip, const ProjectedWallLight &wallLight); private: void RenderSection(RenderThread *thread, int y, int y2, int x1); diff --git a/src/rendering/swrenderer/line/r_renderdrawsegment.cpp b/src/rendering/swrenderer/line/r_renderdrawsegment.cpp index a28d8f4c4c..fc5f51db60 100644 --- a/src/rendering/swrenderer/line/r_renderdrawsegment.cpp +++ b/src/rendering/swrenderer/line/r_renderdrawsegment.cpp @@ -90,41 +90,25 @@ namespace swrenderer } } - if (!ds->HasTranslucentMidTexture() && !ds->HasFogBoundary() && !ds->Has3DFloorWalls()) - { - return; - } - if (ds->HasFogBoundary()) - { - RenderFogBoundary renderfog; - renderfog.Render(Thread, x1, x2, ds->drawsegclip, mLight); - } + RenderFog(ds, x1, x2); - bool notrelevant = false; if (ds->HasTranslucentMidTexture()) - notrelevant = RenderWall(ds, x1, x2); + RenderWall(ds, x1, x2); if (ds->Has3DFloorWalls()) - { Render3DFloorWallRange(ds, x1, x2); - } - if (!notrelevant) - { + if (ds->HasFogBoundary() || ds->HasTranslucentMidTexture() || ds->Has3DFloorWalls()) ds->drawsegclip.SetRangeDrawn(x1, x2); - } } - bool RenderDrawSegment::RenderWall(DrawSegment *ds, int x1, int x2) + void RenderDrawSegment::RenderWall(DrawSegment *ds, int x1, int x2) { auto renderstyle = DefaultRenderStyle(); auto viewport = Thread->Viewport.get(); Clip3DFloors *clip3d = Thread->Clip3D.get(); - if (!curline->sidedef->GetTexture(side_t::mid).isValid()) - return false; - FTexture *ttex = TexMan.GetPalettedTexture(curline->sidedef->GetTexture(side_t::mid), true); if (curline->GetLevel()->i_compatflags & COMPATF_MASKEDMIDTEX) { @@ -139,41 +123,17 @@ namespace swrenderer if (!wrap) { // Texture does not wrap vertically. - // find positioning - double texheight = tex->GetScaledHeightDouble() / fabs(curline->sidedef->GetTextureYScale(side_t::mid)); - double texturemid; - if (curline->linedef->flags & ML_DONTPEGBOTTOM) - texturemid = MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)) + texheight; - else - texturemid = MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling)); - double rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid); - if (tex->useWorldPanning(curline->GetLevel())) - rowoffset /= fabs(tex->GetScale().Y * curline->sidedef->GetTextureYScale(side_t::mid)); - double textop = texturemid + rowoffset - Thread->Viewport->viewpoint.Pos.Z; + double ceilZ, floorZ; + GetNoWrapMidTextureZ(ds, tex, ceilZ, floorZ); - // [RH] Don't bother drawing segs that are completely offscreen - if (viewport->globaldclip * ds->WallC.sz1 < -textop && viewport->globaldclip * ds->WallC.sz2 < -textop) - { // Texture top is below the bottom of the screen - return false; - } + // Texture top is below the bottom of the screen + if (viewport->globaldclip * ds->WallC.sz1 < -ceilZ && viewport->globaldclip * ds->WallC.sz2 < -ceilZ) return; - if (viewport->globaluclip * ds->WallC.sz1 > texheight - textop && viewport->globaluclip * ds->WallC.sz2 > texheight - textop) - { // Texture bottom is above the top of the screen - return false; - } + // Texture bottom is above the top of the screen + if (viewport->globaluclip * ds->WallC.sz1 > -floorZ && viewport->globaluclip * ds->WallC.sz2 > -floorZ) return; - if (m3DFloor.clipBottom && textop < m3DFloor.sclipBottom - Thread->Viewport->viewpoint.Pos.Z) - { - return true; - } - if (m3DFloor.clipTop && textop - texheight > m3DFloor.sclipTop - Thread->Viewport->viewpoint.Pos.Z) - { - return true; - } - - // Unclipped vanilla Doom range for the wall. Relies on ceiling/floor clip to clamp the wall in range. - double ceilZ = textop; - double floorZ = textop - texheight; + if (m3DFloor.clipBottom && ceilZ < m3DFloor.sclipBottom - Thread->Viewport->viewpoint.Pos.Z) return; + if (m3DFloor.clipTop && floorZ > m3DFloor.sclipTop - Thread->Viewport->viewpoint.Pos.Z) return; // The 3D Floors implementation destroys the ceiling clip when doing its height passes.. if (m3DFloor.clipTop || m3DFloor.clipBottom) @@ -241,21 +201,13 @@ namespace swrenderer if (m3DFloor.clipTop) { wallupper.Project(Thread->Viewport.get(), m3DFloor.sclipTop - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC); - for (int i = x1; i < x2; i++) - { - if (wallupper.ScreenY[i] < mceilingclip[i]) - wallupper.ScreenY[i] = mceilingclip[i]; - } + wallupper.ClipTop(x1, x2, ds->drawsegclip); mceilingclip = wallupper.ScreenY; } if (m3DFloor.clipBottom) { walllower.Project(Thread->Viewport.get(), m3DFloor.sclipBottom - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC); - for (int i = x1; i < x2; i++) - { - if (walllower.ScreenY[i] > mfloorclip[i]) - walllower.ScreenY[i] = mfloorclip[i]; - } + walllower.ClipBottom(x1, x2, ds->drawsegclip); mfloorclip = walllower.ScreenY; } } @@ -268,8 +220,6 @@ namespace swrenderer RenderWallPart renderWallpart(Thread); renderWallpart.Render(frontsector, curline, ds->WallC, tex, x1, x2, mceilingclip, mfloorclip, ds->texcoords, top, bot, true, additive, alpha, mLight, nullptr); - - return false; } void RenderDrawSegment::Render3DFloorWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic) @@ -280,7 +230,6 @@ namespace swrenderer mLight.SetLightLeft(ds->light, ds->lightstep, ds->x1); - Clip3DFloors *clip3d = Thread->Clip3D.get(); wallupper.Project(Thread->Viewport.get(), clipTop - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC); walllower.Project(Thread->Viewport.get(), clipBottom - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC); @@ -312,16 +261,11 @@ namespace swrenderer frontsector = curline->frontsector; backsector = curline->backsector; - if (backsector == nullptr) - { + if (!backsector) return; - } + if (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls()) - { - sector_t *sec = backsector; - backsector = frontsector; - frontsector = sec; - } + std::swap(frontsector, backsector); floorHeight = backsector->CenterFloor(); ceilingHeight = backsector->CenterCeiling(); @@ -711,6 +655,29 @@ namespace swrenderer } } + void RenderDrawSegment::RenderFog(DrawSegment* ds, int x1, int x2) + { + const short* mfloorclip = ds->drawsegclip.sprbottomclip; + const short* mceilingclip = ds->drawsegclip.sprtopclip; + + if (m3DFloor.clipTop) + { + wallupper.Project(Thread->Viewport.get(), m3DFloor.sclipTop - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC); + wallupper.ClipTop(x1, x2, ds->drawsegclip); + mceilingclip = wallupper.ScreenY; + } + + if (m3DFloor.clipBottom) + { + walllower.Project(Thread->Viewport.get(), m3DFloor.sclipBottom - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC); + walllower.ClipBottom(x1, x2, ds->drawsegclip); + mfloorclip = walllower.ScreenY; + } + + RenderFogBoundary renderfog; + renderfog.Render(Thread, x1, x2, mceilingclip, mfloorclip, mLight); + } + // Clip a midtexture to the floor and ceiling of the sector in front of it. void RenderDrawSegment::ClipMidtex(DrawSegment* ds, int x1, int x2) { @@ -750,4 +717,22 @@ namespace swrenderer bot = MAX(bot, m3DFloor.sclipBottom); } } + + void RenderDrawSegment::GetNoWrapMidTextureZ(DrawSegment* ds, FSoftwareTexture* tex, double& ceilZ, double& floorZ) + { + double texheight = tex->GetScaledHeightDouble() / fabs(curline->sidedef->GetTextureYScale(side_t::mid)); + double texturemid; + if (curline->linedef->flags & ML_DONTPEGBOTTOM) + texturemid = MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)) + texheight; + else + texturemid = MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling)); + double rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid); + if (tex->useWorldPanning(curline->GetLevel())) + rowoffset /= fabs(tex->GetScale().Y * curline->sidedef->GetTextureYScale(side_t::mid)); + double textop = texturemid + rowoffset - Thread->Viewport->viewpoint.Pos.Z; + + // Unclipped vanilla Doom range for the wall. Relies on ceiling/floor clip to clamp the wall in range. + ceilZ = textop; + floorZ = textop - texheight; + } } diff --git a/src/rendering/swrenderer/line/r_renderdrawsegment.h b/src/rendering/swrenderer/line/r_renderdrawsegment.h index d337192ecf..5a393df32a 100644 --- a/src/rendering/swrenderer/line/r_renderdrawsegment.h +++ b/src/rendering/swrenderer/line/r_renderdrawsegment.h @@ -37,10 +37,12 @@ namespace swrenderer RenderThread *Thread = nullptr; private: - bool RenderWall(DrawSegment *ds, int x1, int x2); - void ClipMidtex(DrawSegment* ds, int x1, int x2); + void RenderWall(DrawSegment *ds, int x1, int x2); void Render3DFloorWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic); void Render3DFloorWallRange(DrawSegment *ds, int x1, int x2); + void RenderFog(DrawSegment* ds, int x1, int x2); + void ClipMidtex(DrawSegment* ds, int x1, int x2); + void GetNoWrapMidTextureZ(DrawSegment* ds, FSoftwareTexture* tex, double& ceilZ, double& floorZ); void GetMaskedWallTopBottom(DrawSegment *ds, double &top, double &bot); sector_t *frontsector = nullptr; diff --git a/src/rendering/swrenderer/scene/r_translucent_pass.cpp b/src/rendering/swrenderer/scene/r_translucent_pass.cpp index 132386a082..bcc91ac39c 100644 --- a/src/rendering/swrenderer/scene/r_translucent_pass.cpp +++ b/src/rendering/swrenderer/scene/r_translucent_pass.cpp @@ -161,11 +161,9 @@ namespace swrenderer { RenderDrawSegment renderer(Thread); renderer.Render(ds, ds->x1, ds->x2, clip3DFloor); + if (renew) - { - ds->ClearFogBoundary(); // don't draw fogboundary again ds->drawsegclip.SetRangeUndrawn(ds->x1, ds->x2); - } } } } diff --git a/src/rendering/swrenderer/segments/r_drawsegment.h b/src/rendering/swrenderer/segments/r_drawsegment.h index 38cd51c7ff..c2b88f79e1 100644 --- a/src/rendering/swrenderer/segments/r_drawsegment.h +++ b/src/rendering/swrenderer/segments/r_drawsegment.h @@ -71,8 +71,6 @@ namespace swrenderer void SetHas3DFloorBackSectorWalls() { flags |= 1; } void SetHasTranslucentMidTexture() { flags |= 4; } - void ClearFogBoundary() { flags &= ~8; } // Note: this shouldn't be needed as fog boundaries should be able to clip same way as 3dfloor walls - private: int flags = 0; // 1=backsector, 2=frontsector, 4=midtexture, 8=fogboundary };