diff --git a/src/rendering/swrenderer/line/r_walldraw.cpp b/src/rendering/swrenderer/line/r_walldraw.cpp index 3e7818348e..ee0ce62387 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,54 +471,6 @@ namespace swrenderer } } - void RenderWallPart::ProcessStripedWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords) - { - 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 < 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::ProcessWall(const short *uwal, const short *dwal, const ProjectedWallTexcoords& texcoords) - { - CameraLight *cameraLight = CameraLight::Instance(); - if (cameraLight->FixedColormap() || cameraLight->FixedLightLevel() >= 0 || !(lightsector->e && lightsector->e->XFloor.lightlist.Size())) - { - ProcessNormalWall(uwal, dwal, texcoords); - } - else - { - ProcessStripedWall(uwal, dwal, texcoords); - } - } - FLightNode* RenderWallPart::GetLightList() { CameraLight* cameraLight = CameraLight::Instance(); @@ -466,31 +481,4 @@ namespace swrenderer else return nullptr; } - - 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) - { - this->x1 = x1; - this->x2 = x2; - this->lightsector = lightsector; - this->curline = curline; - this->WallC = WallC; - this->rw_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. - - ProcessWall(walltop, wallbottom, texcoords); - } - - RenderWallPart::RenderWallPart(RenderThread *thread) - { - Thread = thread; - } } diff --git a/src/rendering/swrenderer/line/r_walldraw.h b/src/rendering/swrenderer/line/r_walldraw.h index ebf71834c3..812908c329 100644 --- a/src/rendering/swrenderer/line/r_walldraw.h +++ b/src/rendering/swrenderer/line/r_walldraw.h @@ -49,7 +49,7 @@ namespace swrenderer const sector_t *lightsector, seg_t *curline, const FWallCoords &WallC, - FSoftwareTexture *rw_pic, + FSoftwareTexture *pic, int x1, int x2, const short *walltop, @@ -59,18 +59,17 @@ namespace swrenderer bool additive, fixed_t alpha); - RenderThread *Thread = nullptr; - private: - 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; + FSoftwareTexture *pic = nullptr; const sector_t *lightsector = nullptr; seg_t *curline = nullptr; FWallCoords WallC;