diff --git a/src/rendering/swrenderer/line/r_fogboundary.cpp b/src/rendering/swrenderer/line/r_fogboundary.cpp index c17f90019..09a6bce20 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 4f7696cd6..312393f9c 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_line.cpp b/src/rendering/swrenderer/line/r_line.cpp index e6b3c03c1..6780bb10c 100644 --- a/src/rendering/swrenderer/line/r_line.cpp +++ b/src/rendering/swrenderer/line/r_line.cpp @@ -62,7 +62,6 @@ CVAR(Bool, r_fogboundary, true, 0) CVAR(Bool, r_drawmirrors, true, 0) -EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); namespace swrenderer { @@ -405,8 +404,6 @@ namespace swrenderer if (draw_segment->HasFogBoundary() || draw_segment->HasTranslucentMidTexture() || draw_segment->Has3DFloorWalls()) { draw_segment->drawsegclip.SetBackupClip(Thread, start, stop, Thread->OpaquePass->ceilingclip); - draw_segment->light = mLight.GetLightPos(start); - draw_segment->lightstep = mLight.GetLightStep(); Thread->DrawSegments->PushTranslucent(draw_segment); } } @@ -446,7 +443,7 @@ namespace swrenderer // [ZZ] Only if not an active mirror if (!markportal) { - RenderDecal::RenderDecals(Thread, mLineSegment->sidedef, draw_segment, mLineSegment, mLight, walltop.ScreenY, wallbottom.ScreenY, false); + RenderDecal::RenderDecals(Thread, draw_segment, mLineSegment, mFrontSector, walltop.ScreenY, wallbottom.ScreenY, false); } if (markportal) @@ -661,22 +658,6 @@ namespace swrenderer } } } - - FTexture *ftex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true); - FSoftwareTexture *midtex = ftex && ftex->isValid() ? ftex->GetSoftwareTexture() : nullptr; - - bool segtextured = ftex != NULL || mTopTexture != NULL || mBottomTexture != NULL; - - if (m3DFloor.type == Fake3DOpaque::Normal) - { - mLight.SetColormap(mFrontSector, mLineSegment); - } - - // calculate light table - if (segtextured || (mBackSector && IsFogBoundary(mFrontSector, mBackSector))) - { - mLight.SetLightLeft(Thread, WallC); - } } void SWRenderLine::SetTextures() @@ -900,7 +881,7 @@ namespace swrenderer texcoords.ProjectTop(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, mTopTexture); RenderWallPart renderWallpart(Thread); - renderWallpart.Render(mFrontSector, mLineSegment, WallC, mTopTexture, x1, x2, walltop.ScreenY, wallupper.ScreenY, texcoords, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mBackCeilingZ1, mBackCeilingZ2), false, false, OPAQUE, mLight, GetLightList()); + renderWallpart.Render(mFrontSector, mLineSegment, WallC, mTopTexture, x1, x2, walltop.ScreenY, wallupper.ScreenY, texcoords, false, false, OPAQUE); } void SWRenderLine::RenderMiddleTexture(int x1, int x2) @@ -912,7 +893,7 @@ namespace swrenderer texcoords.ProjectMid(Thread->Viewport.get(), mFrontSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, mMiddleTexture); RenderWallPart renderWallpart(Thread); - renderWallpart.Render(mFrontSector, mLineSegment, WallC, mMiddleTexture, x1, x2, walltop.ScreenY, wallbottom.ScreenY, texcoords, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, mLight, GetLightList()); + renderWallpart.Render(mFrontSector, mLineSegment, WallC, mMiddleTexture, x1, x2, walltop.ScreenY, wallbottom.ScreenY, texcoords, false, false, OPAQUE); } void SWRenderLine::RenderBottomTexture(int x1, int x2) @@ -925,18 +906,7 @@ namespace swrenderer texcoords.ProjectBottom(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, mBottomTexture); RenderWallPart renderWallpart(Thread); - renderWallpart.Render(mFrontSector, mLineSegment, WallC, mBottomTexture, x1, x2, walllower.ScreenY, wallbottom.ScreenY, texcoords, MAX(mBackFloorZ1, mBackFloorZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, mLight, GetLightList()); - } - - FLightNode *SWRenderLine::GetLightList() - { - CameraLight *cameraLight = CameraLight::Instance(); - if ((cameraLight->FixedLightLevel() >= 0) || cameraLight->FixedColormap()) - return nullptr; // [SP] Don't draw dynlights if invul/lightamp active - else if (mLineSegment && mLineSegment->sidedef) - return mLineSegment->sidedef->lighthead; - else - return nullptr; + renderWallpart.Render(mFrontSector, mLineSegment, WallC, mBottomTexture, x1, x2, walllower.ScreenY, wallbottom.ScreenY, texcoords, false, false, OPAQUE); } //////////////////////////////////////////////////////////////////////////// diff --git a/src/rendering/swrenderer/line/r_line.h b/src/rendering/swrenderer/line/r_line.h index 2944a550f..a4edca524 100644 --- a/src/rendering/swrenderer/line/r_line.h +++ b/src/rendering/swrenderer/line/r_line.h @@ -74,8 +74,6 @@ namespace swrenderer void RenderMiddleTexture(int x1, int x2); void RenderBottomTexture(int x1, int x2); - FLightNode *GetLightList(); - bool IsFogBoundary(sector_t *front, sector_t *back) const; bool SkyboxCompare(sector_t *frontsector, sector_t *backsector) const; @@ -115,8 +113,6 @@ namespace swrenderer bool rw_prepped; - ProjectedWallLight mLight; - bool markfloor; // False if the back side is the same plane. bool markceiling; diff --git a/src/rendering/swrenderer/line/r_renderdrawsegment.cpp b/src/rendering/swrenderer/line/r_renderdrawsegment.cpp index a28d8f4c4..b6d990133 100644 --- a/src/rendering/swrenderer/line/r_renderdrawsegment.cpp +++ b/src/rendering/swrenderer/line/r_renderdrawsegment.cpp @@ -71,60 +71,25 @@ namespace swrenderer frontsector = curline->frontsector; backsector = curline->backsector; - // killough 4/13/98: get correct lightlevel for 2s normal textures - sector_t tempsec; - const sector_t *sec = Thread->OpaquePass->FakeFlat(frontsector, &tempsec, nullptr, nullptr, nullptr, 0, 0, 0, 0); - - mLight.SetColormap(sec, curline); - mLight.SetLightLeft(ds->light, ds->lightstep, ds->x1); - - Clip3DFloors *clip3d = Thread->Clip3D.get(); - - double clipTop = m3DFloor.clipTop ? m3DFloor.sclipTop : sec->ceilingplane.ZatPoint(Thread->Viewport->viewpoint.Pos); - for (int i = frontsector->e->XFloor.lightlist.Size() - 1; i >= 0; i--) - { - if (clipTop <= frontsector->e->XFloor.lightlist[i].plane.Zat0()) - { - mLight.SetColormap(frontsector, curline, &frontsector->e->XFloor.lightlist[i]); - break; - } - } - - 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 +104,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,35 +182,25 @@ 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; } } - double top, bot; - GetMaskedWallTopBottom(ds, top, bot); + sector_t tempsec; + const sector_t* lightsector = Thread->OpaquePass->FakeFlat(frontsector, &tempsec, nullptr, nullptr, nullptr, 0, 0, 0, 0); - float alpha = FLOAT2FIXED((float)MIN(curline->linedef->alpha, 1.)); + fixed_t alpha = FLOAT2FIXED((float)MIN(curline->linedef->alpha, 1.)); bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0; 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; + renderWallpart.Render(lightsector, curline, ds->WallC, tex, x1, x2, mceilingclip, mfloorclip, ds->texcoords, true, additive, alpha); } void RenderDrawSegment::Render3DFloorWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic) @@ -278,9 +209,8 @@ namespace swrenderer if (Alpha <= 0) return; - mLight.SetLightLeft(ds->light, ds->lightstep, ds->x1); + sector_t* lightsector = (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls()) ? backsector : frontsector; - 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); @@ -290,13 +220,10 @@ namespace swrenderer ProjectedWallTexcoords walltexcoords; walltexcoords.Project3DFloor(Thread->Viewport.get(), rover, curline, ds->WallC.sx1, ds->WallC.sx2, ds->tmapvals, rw_pic); - double top, bot; - GetMaskedWallTopBottom(ds, top, bot); - RenderWallPart renderWallpart(Thread); - renderWallpart.Render(frontsector, curline, ds->WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, walltexcoords, top, bot, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha, mLight, nullptr); + renderWallpart.Render(lightsector, curline, ds->WallC, rw_pic, x1, x2, wallupper.ScreenY, walllower.ScreenY, walltexcoords, true, (rover->flags & FF_ADDITIVETRANS) != 0, Alpha); - RenderDecal::RenderDecals(Thread, curline->sidedef, ds, curline, mLight, wallupper.ScreenY, walllower.ScreenY, true); + RenderDecal::RenderDecals(Thread, ds, curline, lightsector, wallupper.ScreenY, walllower.ScreenY, true); } void RenderDrawSegment::Render3DFloorWallRange(DrawSegment *ds, int x1, int x2) @@ -312,16 +239,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(); @@ -490,38 +412,6 @@ namespace swrenderer if (rw_pic && !swimmable_found) { - // correct colors now - lightlist_t *lit = nullptr; - CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedLightLevel() < 0) - { - if (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls()) - { - for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--) - { - if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0()) - { - lit = &backsector->e->XFloor.lightlist[j]; - break; - } - } - } - else - { - for (j = frontsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--) - { - if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0()) - { - lit = &frontsector->e->XFloor.lightlist[j]; - break; - } - } - } - } - - //mLight.lightlevel = ds->lightlevel; - mLight.SetColormap(frontsector, curline, lit); - Render3DFloorWall(ds, x1, x2, fover ? fover : rover, clipTop, clipBottom, rw_pic); } break; @@ -673,37 +563,6 @@ namespace swrenderer if (rw_pic && !swimmable_found) { - // correct colors now - lightlist_t *lit = nullptr; - CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedLightLevel() < 0) - { - if (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls()) - { - for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--) - { - if (clipTop <= backsector->e->XFloor.lightlist[j].plane.Zat0()) - { - lit = &backsector->e->XFloor.lightlist[j]; - break; - } - } - } - else - { - for (j = frontsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--) - { - if (clipTop <= frontsector->e->XFloor.lightlist[j].plane.Zat0()) - { - lit = &frontsector->e->XFloor.lightlist[j]; - break; - } - } - } - } - //mLight.lightlevel = ds->lightlevel; - mLight.SetColormap(frontsector, curline, lit); - Render3DFloorWall(ds, x1, x2, fover ? fover : rover, clipTop, clipBottom, rw_pic); } break; @@ -711,6 +570,36 @@ 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; + } + + sector_t tempsec; + const sector_t* lightsector = Thread->OpaquePass->FakeFlat(frontsector, &tempsec, nullptr, nullptr, nullptr, 0, 0, 0, 0); + + ProjectedWallLight walllight; + walllight.SetColormap(lightsector, curline); + walllight.SetLightLeft(Thread, ds->WallC); + + RenderFogBoundary renderfog; + renderfog.Render(Thread, x1, x2, mceilingclip, mfloorclip, walllight); + } + // 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 +639,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 d337192ec..6e39a54d5 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; @@ -49,8 +51,6 @@ namespace swrenderer seg_t *curline = nullptr; Fake3DTranslucent m3DFloor; - ProjectedWallLight mLight; - ProjectedWallLine wallupper; ProjectedWallLine walllower; }; diff --git a/src/rendering/swrenderer/line/r_walldraw.cpp b/src/rendering/swrenderer/line/r_walldraw.cpp index da4323546..ee0ce6238 100644 --- a/src/rendering/swrenderer/line/r_walldraw.cpp +++ b/src/rendering/swrenderer/line/r_walldraw.cpp @@ -54,12 +54,75 @@ namespace swrenderer { - void RenderWallPart::ProcessNormalWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords) + RenderWallPart::RenderWallPart(RenderThread* thread) { - if (rw_pic == nullptr) + Thread = thread; + } + + void RenderWallPart::Render(const sector_t* lightsector, seg_t* curline, const FWallCoords& WallC, FSoftwareTexture* pic, int x1, int x2, const short* walltop, const short* wallbottom, const ProjectedWallTexcoords& texcoords, bool mask, bool additive, fixed_t alpha) + { + if (pic == nullptr) return; - int fracbits = 32 - rw_pic->GetHeightBits(); + this->x1 = x1; + this->x2 = x2; + this->lightsector = lightsector; + this->curline = curline; + this->WallC = WallC; + this->pic = pic; + this->mask = mask; + this->additive = additive; + this->alpha = alpha; + + light_list = GetLightList(); + + mLight.SetColormap(lightsector, curline); + mLight.SetLightLeft(Thread, WallC); + + Thread->PrepareTexture(pic, DefaultRenderStyle()); // Get correct render style? Shaded won't get here. + + CameraLight* cameraLight = CameraLight::Instance(); + if (cameraLight->FixedColormap() || cameraLight->FixedLightLevel() >= 0 || !(lightsector->e && lightsector->e->XFloor.lightlist.Size())) + { + ProcessNormalWall(walltop, wallbottom, texcoords); + } + else + { + ProcessStripedWall(walltop, wallbottom, texcoords); + } + } + + void RenderWallPart::ProcessStripedWall(const short* uwal, const short* dwal, const ProjectedWallTexcoords& texcoords) + { + RenderPortal* renderportal = Thread->Portal.get(); + + ProjectedWallLine most1, most2, most3; + const short* up = uwal; + short* down = most1.ScreenY; + + for (unsigned int i = 0; i < lightsector->e->XFloor.lightlist.Size(); i++) + { + ProjectedWallCull j = most3.Project(Thread->Viewport.get(), lightsector->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.ScreenY[j], up[j], dwal[j]); + } + ProcessNormalWall(up, down, texcoords); + up = down; + down = (down == most1.ScreenY) ? most2.ScreenY : most1.ScreenY; + } + + mLight.SetColormap(lightsector, curline, &lightsector->e->XFloor.lightlist[i]); + } + + ProcessNormalWall(up, dwal, texcoords); + } + + void RenderWallPart::ProcessNormalWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords) + { + int fracbits = 32 - pic->GetHeightBits(); if (fracbits == 32) { // Hack for one pixel tall textures fracbits = 0; @@ -69,7 +132,7 @@ namespace swrenderer drawerargs.SetTextureFracBits(Thread->Viewport->RenderTarget->IsBgra() ? FRACBITS : fracbits); // Textures that aren't masked can use the faster opaque drawer - if (!rw_pic->GetTexture()->isMasked() && mask && alpha >= OPAQUE && !additive) + if (!pic->GetTexture()->isMasked() && mask && alpha >= OPAQUE && !additive) { drawerargs.SetStyle(true, false, OPAQUE, mLight.GetBaseColormap()); } @@ -114,13 +177,13 @@ namespace swrenderer if (x + 1 < x2) xmagnitude = fabs(FIXED2DBL(texcoords.UPos(x + 1)) - FIXED2DBL(texcoords.UPos(x))); - fixed_t xxoffset = (texcoords.UPos(x) + FLOAT2FIXED(xmagnitude * 0.5)) * rw_pic->GetPhysicalScale(); + fixed_t xxoffset = (texcoords.UPos(x) + FLOAT2FIXED(xmagnitude * 0.5)) * pic->GetPhysicalScale(); // Normalize to 0-1 range: double uv_stepd = texcoords.VStep(x) * texcoords.yscale; - double v = (texcoords.texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / rw_pic->GetHeight(); + double v = (texcoords.texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / pic->GetHeight(); v = v - floor(v); - double v_step = uv_stepd / rw_pic->GetHeight(); + double v_step = uv_stepd / pic->GetHeight(); if (std::isnan(v) || std::isnan(v_step)) // this should never happen, but it apparently does.. { @@ -141,9 +204,9 @@ namespace swrenderer bool magnifying = lod < 0.0f; int mipmap_offset = 0; - int mip_width = rw_pic->GetPhysicalWidth(); - int mip_height = rw_pic->GetPhysicalHeight(); - if (r_mipmap && rw_pic->Mipmapped() && mip_width > 1 && mip_height > 1) + int mip_width = pic->GetPhysicalWidth(); + int mip_height = pic->GetPhysicalHeight(); + if (r_mipmap && pic->Mipmapped() && mip_width > 1 && mip_height > 1) { uint32_t xpos = (uint32_t)((((uint64_t)xxoffset) << FRACBITS) / mip_width); @@ -158,7 +221,7 @@ namespace swrenderer xxoffset = (xpos >> FRACBITS) * mip_width; } - const uint32_t *pixels = rw_pic->GetPixelsBgra() + mipmap_offset; + const uint32_t *pixels = pic->GetPixelsBgra() + mipmap_offset; const uint8_t *source; const uint8_t *source2; @@ -208,10 +271,10 @@ namespace swrenderer } else { - uint32_t height = rw_pic->GetPhysicalHeight(); + uint32_t height = pic->GetPhysicalHeight(); uint32_t uv_max; - int uv_fracbits = 32 - rw_pic->GetHeightBits(); + int uv_fracbits = 32 - pic->GetHeightBits(); if (uv_fracbits != 32) uv_max = height << uv_fracbits; @@ -230,20 +293,20 @@ namespace swrenderer uint32_t uv_pos; uint32_t uv_step; - fixed_t xxoffset = (texcoords.UPos(x) + FLOAT2FIXED(xmagnitude * 0.5)) * rw_pic->GetPhysicalScale(); + fixed_t xxoffset = (texcoords.UPos(x) + FLOAT2FIXED(xmagnitude * 0.5)) * pic->GetPhysicalScale(); if (uv_fracbits != 32) { // Find start uv in [0-base_height[ range. // Not using xs_ToFixed because it rounds the result and we need something that always rounds down to stay within the range. double uv_stepd = texcoords.VStep(x) * texcoords.yscale; - double v = (texcoords.texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / rw_pic->GetHeight(); + double v = (texcoords.texturemid + uv_stepd * (y1 - viewport->CenterY + 0.5)) / pic->GetHeight(); v = v - floor(v); v *= height; v *= (1 << uv_fracbits); uv_pos = (uint32_t)(int64_t)v; - uv_step = xs_ToFixed(uv_fracbits, uv_stepd * rw_pic->GetPhysicalScale()); + uv_step = xs_ToFixed(uv_fracbits, uv_stepd * pic->GetPhysicalScale()); if (uv_step == 0) // To prevent divide by zero elsewhere uv_step = 1; } @@ -259,12 +322,12 @@ namespace swrenderer // If the texture's width isn't a power of 2, then we need to make it a // positive offset for proper clamping. int width; - if (col < 0 && (width = rw_pic->GetPhysicalWidth()) != (1 << rw_pic->GetWidthBits())) + if (col < 0 && (width = pic->GetPhysicalWidth()) != (1 << pic->GetWidthBits())) { col = width + (col % width); } - drawerargs.SetTexture(rw_pic->GetColumn(DefaultRenderStyle(), col, nullptr), nullptr, height); + drawerargs.SetTexture(pic->GetColumn(DefaultRenderStyle(), col, nullptr), nullptr, height); if (haslights) SetLights(drawerargs, x, y1); @@ -408,154 +471,14 @@ namespace swrenderer } } - void RenderWallPart::ProcessStripedWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords) + FLightNode* RenderWallPart::GetLightList() { - ProjectedWallLine most1, most2, most3; - const short *up; - short *down; - - up = uwal; - down = most1.ScreenY; - - assert(WallC.sx1 <= x1); - assert(WallC.sx2 >= x2); - - RenderPortal *renderportal = Thread->Portal.get(); - - // kg3D - fake floors instead of zdoom light list - for (unsigned int i = 0; i < frontsector->e->XFloor.lightlist.Size(); i++) - { - ProjectedWallCull j = most3.Project(Thread->Viewport.get(), 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.ScreenY[j], up[j], dwal[j]); - } - ProcessNormalWall(up, down, texcoords); - up = down; - down = (down == most1.ScreenY) ? most2.ScreenY : most1.ScreenY; - } - - mLight.SetColormap(frontsector, curline, &frontsector->e->XFloor.lightlist[i]); - } - - ProcessNormalWall(up, dwal, texcoords); - } - - void RenderWallPart::ProcessWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords) - { - CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedColormap() != NULL || cameraLight->FixedLightLevel() >= 0 || !(frontsector->e && frontsector->e->XFloor.lightlist.Size())) - { - ProcessNormalWall(uwal, dwal, texcoords); - } + CameraLight* cameraLight = CameraLight::Instance(); + if ((cameraLight->FixedLightLevel() >= 0) || cameraLight->FixedColormap()) + return nullptr; // [SP] Don't draw dynlights if invul/lightamp active + else if (curline && curline->sidedef) + return curline->sidedef->lighthead; else - { - ProcessStripedWall(uwal, dwal, texcoords); - } - } - - //============================================================================= - // - // ProcessWallNP2 - // - // This is a wrapper around ProcessWall that helps it tile textures whose heights - // are not powers of 2. It divides the wall into texture-sized strips and calls - // ProcessNormalWall for each of those. Since only one repetition of the texture fits - // in each strip, ProcessWall will not tile. - // - //============================================================================= - - void RenderWallPart::ProcessWallNP2(const short *uwal, const short *dwal, ProjectedWallTexcoords texcoords, double top, double bot) - { - ProjectedWallLine most1, most2, most3; - double texheight = rw_pic->GetHeight(); - double partition; - double scaledtexheight = texheight / texcoords.yscale; - - if (texcoords.yscale >= 0) - { // normal orientation: draw strips from top to bottom - partition = top - fmod(top - texcoords.texturemid / texcoords.yscale - Thread->Viewport->viewpoint.Pos.Z, scaledtexheight); - if (partition == top) - { - partition -= scaledtexheight; - } - const short *up = uwal; - short *down = most1.ScreenY; - texcoords.texturemid = (partition - Thread->Viewport->viewpoint.Pos.Z) * texcoords.yscale + texheight; - while (partition > bot) - { - ProjectedWallCull j = most3.Project(Thread->Viewport.get(), partition - Thread->Viewport->viewpoint.Pos.Z, &WallC); - if (j != ProjectedWallCull::OutsideAbove) - { - for (int j = x1; j < x2; ++j) - { - down[j] = clamp(most3.ScreenY[j], up[j], dwal[j]); - } - ProcessWall(up, down, texcoords); - up = down; - down = (down == most1.ScreenY) ? most2.ScreenY : most1.ScreenY; - } - partition -= scaledtexheight; - texcoords.texturemid -= texheight; - } - ProcessWall(up, dwal, texcoords); - } - else - { // upside down: draw strips from bottom to top - partition = bot - fmod(bot - texcoords.texturemid / texcoords.yscale - Thread->Viewport->viewpoint.Pos.Z, scaledtexheight); - short *up = most1.ScreenY; - const short *down = dwal; - texcoords.texturemid = (partition - Thread->Viewport->viewpoint.Pos.Z) * texcoords.yscale + texheight; - while (partition < top) - { - ProjectedWallCull j = most3.Project(Thread->Viewport.get(), partition - Thread->Viewport->viewpoint.Pos.Z, &WallC); - if (j != ProjectedWallCull::OutsideBelow) - { - for (int j = x1; j < x2; ++j) - { - up[j] = clamp(most3.ScreenY[j], uwal[j], down[j]); - } - ProcessWall(up, down, texcoords); - down = up; - up = (up == most1.ScreenY) ? most2.ScreenY : most1.ScreenY; - } - partition -= scaledtexheight; - texcoords.texturemid -= texheight; - } - ProcessWall(uwal, down, texcoords); - } - } - - void RenderWallPart::Render(sector_t *frontsector, seg_t *curline, const FWallCoords &WallC, FSoftwareTexture *pic, int x1, int x2, const short *walltop, const short *wallbottom, const ProjectedWallTexcoords& texcoords, double top, double bottom, bool mask, bool additive, fixed_t alpha, const ProjectedWallLight &light, FLightNode *light_list) - { - this->x1 = x1; - this->x2 = x2; - this->frontsector = frontsector; - this->curline = curline; - this->WallC = WallC; - this->mLight = light; - 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, texcoords, top, bottom); - } - else - { - ProcessWall(walltop, wallbottom, texcoords); - } - } - - RenderWallPart::RenderWallPart(RenderThread *thread) - { - Thread = thread; + return nullptr; } } diff --git a/src/rendering/swrenderer/line/r_walldraw.h b/src/rendering/swrenderer/line/r_walldraw.h index e8f104dcb..812908c32 100644 --- a/src/rendering/swrenderer/line/r_walldraw.h +++ b/src/rendering/swrenderer/line/r_walldraw.h @@ -46,36 +46,31 @@ namespace swrenderer RenderWallPart(RenderThread *thread); void Render( - sector_t *frontsector, + const sector_t *lightsector, seg_t *curline, const FWallCoords &WallC, - FSoftwareTexture *rw_pic, + FSoftwareTexture *pic, int x1, int x2, const short *walltop, const short *wallbottom, const ProjectedWallTexcoords &texcoords, - double top, - double bottom, bool mask, bool additive, - fixed_t alpha, - const ProjectedWallLight &light, - FLightNode *light_list); - - RenderThread *Thread = nullptr; + fixed_t alpha); private: - void ProcessWallNP2(const short *uwal, const short *dwal, ProjectedWallTexcoords texcoords, double top, double bot); - void ProcessWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords); void ProcessStripedWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords); void ProcessNormalWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords); void SetLights(WallDrawerArgs &drawerargs, int x, int y1); + FLightNode* GetLightList(); + + RenderThread* Thread = nullptr; int x1 = 0; int x2 = 0; - FSoftwareTexture *rw_pic = nullptr; - sector_t *frontsector = nullptr; + FSoftwareTexture *pic = nullptr; + const sector_t *lightsector = nullptr; seg_t *curline = nullptr; FWallCoords WallC; diff --git a/src/rendering/swrenderer/line/r_wallsetup.h b/src/rendering/swrenderer/line/r_wallsetup.h index f7b78c248..923d33fec 100644 --- a/src/rendering/swrenderer/line/r_wallsetup.h +++ b/src/rendering/swrenderer/line/r_wallsetup.h @@ -110,8 +110,6 @@ namespace swrenderer float GetLightStep() const { return lightstep; } void SetColormap(const sector_t *frontsector, seg_t *lineseg, lightlist_t *lit = nullptr); - - void SetLightLeft(float left, float step, int startx) { lightleft = left; lightstep = step; x1 = startx; } void SetLightLeft(RenderThread *thread, const FWallCoords &wallc); private: diff --git a/src/rendering/swrenderer/scene/r_translucent_pass.cpp b/src/rendering/swrenderer/scene/r_translucent_pass.cpp index 132386a08..bcc91ac39 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 38cd51c7f..43c33b0b4 100644 --- a/src/rendering/swrenderer/segments/r_drawsegment.h +++ b/src/rendering/swrenderer/segments/r_drawsegment.h @@ -51,8 +51,7 @@ namespace swrenderer struct DrawSegment { seg_t *curline; - float light, lightstep; - short x1, x2; // Same as sx1 and sx2, but clipped to the drawseg + short x1, x2; FWallCoords WallC; FWallTmapVals tmapvals; @@ -71,8 +70,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 }; diff --git a/src/rendering/swrenderer/things/r_decal.cpp b/src/rendering/swrenderer/things/r_decal.cpp index 8953b727e..49edf5e19 100644 --- a/src/rendering/swrenderer/things/r_decal.cpp +++ b/src/rendering/swrenderer/things/r_decal.cpp @@ -53,19 +53,17 @@ #include "swrenderer/r_memory.h" #include "swrenderer/r_renderthread.h" -EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor); - namespace swrenderer { - void RenderDecal::RenderDecals(RenderThread *thread, side_t *sidedef, DrawSegment *draw_segment, seg_t *curline, const ProjectedWallLight &light, const short *walltop, const short *wallbottom, bool drawsegPass) + void RenderDecal::RenderDecals(RenderThread *thread, DrawSegment *draw_segment, seg_t *curline, const sector_t* lightsector, const short *walltop, const short *wallbottom, bool drawsegPass) { - for (DBaseDecal *decal = sidedef->AttachedDecals; decal != NULL; decal = decal->WallNext) + for (DBaseDecal *decal = curline->sidedef->AttachedDecals; decal != NULL; decal = decal->WallNext) { - Render(thread, sidedef, decal, draw_segment, curline, light, walltop, wallbottom, drawsegPass); + Render(thread, decal, draw_segment, curline, lightsector, walltop, wallbottom, drawsegPass); } } - void RenderDecal::Render(RenderThread *thread, side_t *wall, DBaseDecal *decal, DrawSegment *clipper, seg_t *curline, const ProjectedWallLight &light, const short *walltop, const short *wallbottom, bool drawsegPass) + void RenderDecal::Render(RenderThread *thread, DBaseDecal *decal, DrawSegment *clipper, seg_t *curline, const sector_t* lightsector, const short *walltop, const short *wallbottom, bool drawsegPass) { DVector2 decal_left, decal_right, decal_pos; int x1, x2; @@ -142,7 +140,7 @@ namespace swrenderer edge_left *= decal->ScaleX; double dcx, dcy; - decal->GetXY(wall, dcx, dcy); + decal->GetXY(curline->sidedef, dcx, dcy); decal_pos = { dcx, dcy }; DVector2 angvec = (curline->v2->fPos() - curline->v1->fPos()).Unit(); @@ -231,6 +229,9 @@ namespace swrenderer } // Prepare lighting + ProjectedWallLight light; + light.SetColormap(lightsector, curline); + light.SetLightLeft(thread, WallC); usecolormap = light.GetBaseColormap(); // Decals that are added to the scene must fade to black. diff --git a/src/rendering/swrenderer/things/r_decal.h b/src/rendering/swrenderer/things/r_decal.h index e6f647501..71db29f97 100644 --- a/src/rendering/swrenderer/things/r_decal.h +++ b/src/rendering/swrenderer/things/r_decal.h @@ -12,9 +12,9 @@ namespace swrenderer class RenderDecal { public: - static void RenderDecals(RenderThread *thread, side_t *wall, DrawSegment *draw_segment, seg_t *curline, const ProjectedWallLight &light, const short *walltop, const short *wallbottom, bool drawsegPass); + static void RenderDecals(RenderThread *thread, DrawSegment *draw_segment, seg_t *curline, const sector_t* lightsector, const short *walltop, const short *wallbottom, bool drawsegPass); 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, DBaseDecal *first, DrawSegment *clipper, seg_t *curline, const sector_t* lightsector, const short *walltop, const short *wallbottom, bool drawsegPass); }; }