mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-29 07:22:05 +00:00
Create SetTopTexture, SetMiddleTexture and SetBottomTexture
This commit is contained in:
parent
b5c5bd9a1c
commit
bb749c032a
2 changed files with 185 additions and 162 deletions
|
@ -737,24 +737,132 @@ namespace swrenderer
|
||||||
markfloor = ShouldMarkFloor();
|
markfloor = ShouldMarkFloor();
|
||||||
markceiling = ShouldMarkCeiling();
|
markceiling = ShouldMarkCeiling();
|
||||||
|
|
||||||
mTopPart.Texture = nullptr;
|
SetTopTexture();
|
||||||
mMiddlePart.Texture = nullptr;
|
SetMiddleTexture();
|
||||||
mBottomPart.Texture = nullptr;
|
SetBottomTexture();
|
||||||
|
|
||||||
if (sidedef == linedef->sidedef[0] &&
|
if (mBackSector && !(sidedef == linedef->sidedef[0] && (linedef->special == Line_Mirror && r_drawmirrors)))
|
||||||
(linedef->special == Line_Mirror && r_drawmirrors)) // [ZZ] compatibility with r_drawmirrors cvar that existed way before portals
|
|
||||||
{
|
{
|
||||||
|
// skyhack to allow height changes in outdoor areas
|
||||||
|
if (mFrontSector->GetTexture(sector_t::ceiling) == skyflatnum &&
|
||||||
|
mBackSector->GetTexture(sector_t::ceiling) == skyflatnum)
|
||||||
|
{
|
||||||
|
if (rw_havehigh)
|
||||||
|
{ // front ceiling is above back ceiling
|
||||||
|
memcpy(&walltop.ScreenY[WallC.sx1], &wallupper.ScreenY[WallC.sx1], (WallC.sx2 - WallC.sx1) * sizeof(walltop.ScreenY[0]));
|
||||||
|
rw_havehigh = false;
|
||||||
}
|
}
|
||||||
else if (mBackSector == NULL)
|
else if (rw_havelow && mFrontSector->ceilingplane != mBackSector->ceilingplane)
|
||||||
|
{ // back ceiling is above front ceiling
|
||||||
|
// The check for rw_havelow is not Doom-compliant, but it avoids HoM that
|
||||||
|
// would otherwise occur because there is space made available for this
|
||||||
|
// wall but nothing to draw for it.
|
||||||
|
// Recalculate walltop so that the wall is clipped by the back sector's
|
||||||
|
// ceiling instead of the front sector's ceiling.
|
||||||
|
walltop.Project(mBackSector->ceilingplane, &WallC, mLineSegment, Thread->Portal->MirrorFlags & RF_XFLIP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FTexture *midtex = TexMan(sidedef->GetTexture(side_t::mid), true);
|
||||||
|
|
||||||
|
bool segtextured = midtex != NULL || mTopPart.Texture != NULL || mBottomPart.Texture != NULL;
|
||||||
|
|
||||||
|
// calculate light table
|
||||||
|
if (needlights && (segtextured || (mBackSector && IsFogBoundary(mFrontSector, mBackSector))))
|
||||||
{
|
{
|
||||||
// single sided line
|
lwallscale =
|
||||||
|
midtex ? (midtex->Scale.X * sidedef->GetTextureXScale(side_t::mid)) :
|
||||||
|
mTopPart.Texture ? (mTopPart.Texture->Scale.X * sidedef->GetTextureXScale(side_t::top)) :
|
||||||
|
mBottomPart.Texture ? (mBottomPart.Texture->Scale.X * sidedef->GetTextureXScale(side_t::bottom)) :
|
||||||
|
1.;
|
||||||
|
|
||||||
|
walltexcoords.Project(sidedef->TexelLength * lwallscale, WallC.sx1, WallC.sx2, WallT);
|
||||||
|
|
||||||
|
CameraLight *cameraLight = CameraLight::Instance();
|
||||||
|
if (cameraLight->FixedColormap() == nullptr && cameraLight->FixedLightLevel() < 0)
|
||||||
|
{
|
||||||
|
wallshade = LIGHT2SHADE(mLineSegment->sidedef->GetLightLevel(foggy, mFrontSector->lightlevel) + R_ActualExtraLight(foggy));
|
||||||
|
double GlobVis = LightVisibility::Instance()->WallGlobVis();
|
||||||
|
rw_lightleft = float(GlobVis / WallC.sz1);
|
||||||
|
rw_lightstep = float((GlobVis / WallC.sz2 - rw_lightleft) / (WallC.sx2 - WallC.sx1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rw_lightleft = 1;
|
||||||
|
rw_lightstep = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SWRenderLine::SetTopTexture()
|
||||||
|
{
|
||||||
|
mTopPart.Texture = nullptr;
|
||||||
|
|
||||||
|
if (!(mFrontCeilingZ1 > mBackCeilingZ1 || mFrontCeilingZ2 > mBackCeilingZ2)) return;
|
||||||
|
|
||||||
|
side_t *sidedef = mLineSegment->sidedef;
|
||||||
|
line_t *linedef = mLineSegment->linedef;
|
||||||
|
if (sidedef == linedef->sidedef[0] && (linedef->special == Line_Mirror && r_drawmirrors)) return;
|
||||||
|
if (!mBackSector) return;
|
||||||
|
|
||||||
|
mTopPart.Texture = TexMan(sidedef->GetTexture(side_t::top), true);
|
||||||
|
|
||||||
|
mTopPart.TextureOffsetU = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::top));
|
||||||
|
double rowoffset = sidedef->GetTextureYOffset(side_t::top);
|
||||||
|
mTopPart.TextureScaleU = sidedef->GetTextureXScale(side_t::top);
|
||||||
|
mTopPart.TextureScaleV = sidedef->GetTextureYScale(side_t::top);
|
||||||
|
double yrepeat = mTopPart.Texture->Scale.Y * mTopPart.TextureScaleV;
|
||||||
|
if (yrepeat >= 0)
|
||||||
|
{ // normal orientation
|
||||||
|
if (linedef->flags & ML_DONTPEGTOP)
|
||||||
|
{ // top of texture at top
|
||||||
|
mTopPart.TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - ViewPos.Z) * yrepeat;
|
||||||
|
if (rowoffset < 0 && mTopPart.Texture != NULL)
|
||||||
|
{
|
||||||
|
rowoffset += mTopPart.Texture->GetHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // bottom of texture at bottom
|
||||||
|
mTopPart.TextureMid = (mBackSector->GetPlaneTexZ(sector_t::ceiling) - ViewPos.Z) * yrepeat + mTopPart.Texture->GetHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // upside down
|
||||||
|
rowoffset = -rowoffset;
|
||||||
|
if (linedef->flags & ML_DONTPEGTOP)
|
||||||
|
{ // bottom of texture at top
|
||||||
|
mTopPart.TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - ViewPos.Z) * yrepeat + mTopPart.Texture->GetHeight();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // top of texture at bottom
|
||||||
|
mTopPart.TextureMid = (mBackSector->GetPlaneTexZ(sector_t::ceiling) - ViewPos.Z) * yrepeat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mTopPart.Texture->bWorldPanning)
|
||||||
|
{
|
||||||
|
mTopPart.TextureMid += rowoffset * yrepeat;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mTopPart.TextureMid += rowoffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SWRenderLine::SetMiddleTexture()
|
||||||
|
{
|
||||||
|
mMiddlePart.Texture = nullptr;
|
||||||
|
|
||||||
|
side_t *sidedef = mLineSegment->sidedef;
|
||||||
|
line_t *linedef = mLineSegment->linedef;
|
||||||
|
if (sidedef == linedef->sidedef[0] && (linedef->special == Line_Mirror && r_drawmirrors)) return;
|
||||||
|
if (mBackSector) return;
|
||||||
|
|
||||||
// [RH] Horizon lines do not need to be textured
|
// [RH] Horizon lines do not need to be textured
|
||||||
if (linedef->isVisualPortal())
|
if (linedef->isVisualPortal()) return;
|
||||||
{
|
if (linedef->special == Line_Horizon) return;
|
||||||
}
|
|
||||||
else if (linedef->special != Line_Horizon)
|
|
||||||
{
|
|
||||||
mMiddlePart.Texture = TexMan(sidedef->GetTexture(side_t::mid), true);
|
mMiddlePart.Texture = TexMan(sidedef->GetTexture(side_t::mid), true);
|
||||||
mMiddlePart.TextureOffsetU = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid));
|
mMiddlePart.TextureOffsetU = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid));
|
||||||
double rowoffset = sidedef->GetTextureYOffset(side_t::mid);
|
double rowoffset = sidedef->GetTextureYOffset(side_t::mid);
|
||||||
|
@ -799,82 +907,26 @@ namespace swrenderer
|
||||||
mMiddlePart.TextureMid += rowoffset;
|
mMiddlePart.TextureMid += rowoffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // two-sided line
|
|
||||||
// hack to allow height changes in outdoor areas
|
|
||||||
|
|
||||||
double rw_frontlowertop = mFrontSector->GetPlaneTexZ(sector_t::ceiling);
|
void SWRenderLine::SetBottomTexture()
|
||||||
|
{
|
||||||
if (mFrontSector->GetTexture(sector_t::ceiling) == skyflatnum &&
|
mBottomPart.Texture = nullptr;
|
||||||
mBackSector->GetTexture(sector_t::ceiling) == skyflatnum)
|
|
||||||
|
if (!(mFrontFloorZ1 < mBackFloorZ1 || mFrontFloorZ2 < mBackFloorZ2)) return;
|
||||||
|
|
||||||
|
side_t *sidedef = mLineSegment->sidedef;
|
||||||
|
line_t *linedef = mLineSegment->linedef;
|
||||||
|
if (sidedef == linedef->sidedef[0] && (linedef->special == Line_Mirror && r_drawmirrors)) return;
|
||||||
|
if (!mBackSector) return;
|
||||||
|
|
||||||
|
double frontlowertop = mFrontSector->GetPlaneTexZ(sector_t::ceiling);
|
||||||
|
if (mFrontSector->GetTexture(sector_t::ceiling) == skyflatnum && mBackSector->GetTexture(sector_t::ceiling) == skyflatnum)
|
||||||
{
|
{
|
||||||
if (rw_havehigh)
|
|
||||||
{ // front ceiling is above back ceiling
|
|
||||||
memcpy(&walltop.ScreenY[WallC.sx1], &wallupper.ScreenY[WallC.sx1], (WallC.sx2 - WallC.sx1) * sizeof(walltop.ScreenY[0]));
|
|
||||||
rw_havehigh = false;
|
|
||||||
}
|
|
||||||
else if (rw_havelow && mFrontSector->ceilingplane != mBackSector->ceilingplane)
|
|
||||||
{ // back ceiling is above front ceiling
|
|
||||||
// The check for rw_havelow is not Doom-compliant, but it avoids HoM that
|
|
||||||
// would otherwise occur because there is space made available for this
|
|
||||||
// wall but nothing to draw for it.
|
|
||||||
// Recalculate walltop so that the wall is clipped by the back sector's
|
|
||||||
// ceiling instead of the front sector's ceiling.
|
|
||||||
walltop.Project(mBackSector->ceilingplane, &WallC, mLineSegment, Thread->Portal->MirrorFlags & RF_XFLIP);
|
|
||||||
}
|
|
||||||
// Putting sky ceilings on the front and back of a line alters the way unpegged
|
// Putting sky ceilings on the front and back of a line alters the way unpegged
|
||||||
// positioning works.
|
// positioning works.
|
||||||
rw_frontlowertop = mBackSector->GetPlaneTexZ(sector_t::ceiling);
|
frontlowertop = mBackSector->GetPlaneTexZ(sector_t::ceiling);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rw_havehigh)
|
|
||||||
{ // top texture
|
|
||||||
mTopPart.Texture = TexMan(sidedef->GetTexture(side_t::top), true);
|
|
||||||
|
|
||||||
mTopPart.TextureOffsetU = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::top));
|
|
||||||
double rowoffset = sidedef->GetTextureYOffset(side_t::top);
|
|
||||||
mTopPart.TextureScaleU = sidedef->GetTextureXScale(side_t::top);
|
|
||||||
mTopPart.TextureScaleV = sidedef->GetTextureYScale(side_t::top);
|
|
||||||
double yrepeat = mTopPart.Texture->Scale.Y * mTopPart.TextureScaleV;
|
|
||||||
if (yrepeat >= 0)
|
|
||||||
{ // normal orientation
|
|
||||||
if (linedef->flags & ML_DONTPEGTOP)
|
|
||||||
{ // top of texture at top
|
|
||||||
mTopPart.TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - ViewPos.Z) * yrepeat;
|
|
||||||
if (rowoffset < 0 && mTopPart.Texture != NULL)
|
|
||||||
{
|
|
||||||
rowoffset += mTopPart.Texture->GetHeight();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // bottom of texture at bottom
|
|
||||||
mTopPart.TextureMid = (mBackSector->GetPlaneTexZ(sector_t::ceiling) - ViewPos.Z) * yrepeat + mTopPart.Texture->GetHeight();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // upside down
|
|
||||||
rowoffset = -rowoffset;
|
|
||||||
if (linedef->flags & ML_DONTPEGTOP)
|
|
||||||
{ // bottom of texture at top
|
|
||||||
mTopPart.TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - ViewPos.Z) * yrepeat + mTopPart.Texture->GetHeight();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // top of texture at bottom
|
|
||||||
mTopPart.TextureMid = (mBackSector->GetPlaneTexZ(sector_t::ceiling) - ViewPos.Z) * yrepeat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mTopPart.Texture->bWorldPanning)
|
|
||||||
{
|
|
||||||
mTopPart.TextureMid += rowoffset * yrepeat;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mTopPart.TextureMid += rowoffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rw_havelow)
|
|
||||||
{ // bottom texture
|
|
||||||
mBottomPart.Texture = TexMan(sidedef->GetTexture(side_t::bottom), true);
|
mBottomPart.Texture = TexMan(sidedef->GetTexture(side_t::bottom), true);
|
||||||
|
|
||||||
mBottomPart.TextureOffsetU = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::bottom));
|
mBottomPart.TextureOffsetU = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::bottom));
|
||||||
|
@ -886,7 +938,7 @@ namespace swrenderer
|
||||||
{ // normal orientation
|
{ // normal orientation
|
||||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||||
{ // bottom of texture at bottom
|
{ // bottom of texture at bottom
|
||||||
mBottomPart.TextureMid = (rw_frontlowertop - ViewPos.Z) * yrepeat;
|
mBottomPart.TextureMid = (frontlowertop - ViewPos.Z) * yrepeat;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // top of texture at top
|
{ // top of texture at top
|
||||||
|
@ -902,7 +954,7 @@ namespace swrenderer
|
||||||
rowoffset = -rowoffset;
|
rowoffset = -rowoffset;
|
||||||
if (linedef->flags & ML_DONTPEGBOTTOM)
|
if (linedef->flags & ML_DONTPEGBOTTOM)
|
||||||
{ // top of texture at bottom
|
{ // top of texture at bottom
|
||||||
mBottomPart.TextureMid = (rw_frontlowertop - ViewPos.Z) * yrepeat;
|
mBottomPart.TextureMid = (frontlowertop - ViewPos.Z) * yrepeat;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // bottom of texture at top
|
{ // bottom of texture at top
|
||||||
|
@ -918,38 +970,6 @@ namespace swrenderer
|
||||||
mBottomPart.TextureMid += rowoffset;
|
mBottomPart.TextureMid += rowoffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
FTexture *midtex = TexMan(sidedef->GetTexture(side_t::mid), true);
|
|
||||||
|
|
||||||
bool segtextured = midtex != NULL || mTopPart.Texture != NULL || mBottomPart.Texture != NULL;
|
|
||||||
|
|
||||||
// calculate light table
|
|
||||||
if (needlights && (segtextured || (mBackSector && IsFogBoundary(mFrontSector, mBackSector))))
|
|
||||||
{
|
|
||||||
lwallscale =
|
|
||||||
midtex ? (midtex->Scale.X * sidedef->GetTextureXScale(side_t::mid)) :
|
|
||||||
mTopPart.Texture ? (mTopPart.Texture->Scale.X * sidedef->GetTextureXScale(side_t::top)) :
|
|
||||||
mBottomPart.Texture ? (mBottomPart.Texture->Scale.X * sidedef->GetTextureXScale(side_t::bottom)) :
|
|
||||||
1.;
|
|
||||||
|
|
||||||
walltexcoords.Project(sidedef->TexelLength * lwallscale, WallC.sx1, WallC.sx2, WallT);
|
|
||||||
|
|
||||||
CameraLight *cameraLight = CameraLight::Instance();
|
|
||||||
if (cameraLight->FixedColormap() == nullptr && cameraLight->FixedLightLevel() < 0)
|
|
||||||
{
|
|
||||||
wallshade = LIGHT2SHADE(mLineSegment->sidedef->GetLightLevel(foggy, mFrontSector->lightlevel) + R_ActualExtraLight(foggy));
|
|
||||||
double GlobVis = LightVisibility::Instance()->WallGlobVis();
|
|
||||||
rw_lightleft = float(GlobVis / WallC.sz1);
|
|
||||||
rw_lightstep = float((GlobVis / WallC.sz2 - rw_lightleft) / (WallC.sx2 - WallC.sx1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rw_lightleft = 1;
|
|
||||||
rw_lightstep = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SWRenderLine::IsFogBoundary(sector_t *front, sector_t *back) const
|
bool SWRenderLine::IsFogBoundary(sector_t *front, sector_t *back) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,6 +69,9 @@ namespace swrenderer
|
||||||
private:
|
private:
|
||||||
bool RenderWallSegment(int x1, int x2) override;
|
bool RenderWallSegment(int x1, int x2) override;
|
||||||
void SetWallVariables(bool needlights);
|
void SetWallVariables(bool needlights);
|
||||||
|
void SetTopTexture();
|
||||||
|
void SetMiddleTexture();
|
||||||
|
void SetBottomTexture();
|
||||||
void ClipSegmentTopBottom(int x1, int x2);
|
void ClipSegmentTopBottom(int x1, int x2);
|
||||||
void RenderWallSegmentTextures(int x1, int x2);
|
void RenderWallSegmentTextures(int x1, int x2);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue