mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-23 12:32:34 +00:00
Fix 3d floor rendering bug
This commit is contained in:
parent
a74be69371
commit
642cd2b160
8 changed files with 73 additions and 93 deletions
|
@ -287,9 +287,6 @@ namespace swrenderer
|
|||
// A wall segment will be drawn between start and stop pixels (inclusive).
|
||||
bool SWRenderLine::RenderWallSegment(int start, int stop)
|
||||
{
|
||||
int i;
|
||||
bool maskedtexture = false;
|
||||
|
||||
if (!rw_prepped)
|
||||
{
|
||||
rw_prepped = true;
|
||||
|
@ -320,9 +317,11 @@ namespace swrenderer
|
|||
|
||||
if (markportal)
|
||||
{
|
||||
draw_segment->drawsegclip.SetTopClip(Thread, start, stop, Thread->OpaquePass->ceilingclip);
|
||||
draw_segment->drawsegclip.SetBottomClip(Thread, start, stop, Thread->OpaquePass->floorclip);
|
||||
draw_segment->drawsegclip.silhouette = SIL_BOTH;
|
||||
}
|
||||
else if (mBackSector == NULL)
|
||||
else if (!mBackSector)
|
||||
{
|
||||
draw_segment->drawsegclip.SetTopClip(Thread, start, stop, viewheight);
|
||||
draw_segment->drawsegclip.SetBottomClip(Thread, start, stop, -1);
|
||||
|
@ -331,14 +330,12 @@ namespace swrenderer
|
|||
else
|
||||
{
|
||||
// two sided line
|
||||
if (mFrontFloorZ1 > mBackFloorZ1 || mFrontFloorZ2 > mBackFloorZ2 ||
|
||||
mBackSector->floorplane.PointOnSide(Thread->Viewport->viewpoint.Pos) < 0)
|
||||
if (mFrontFloorZ1 > mBackFloorZ1 || mFrontFloorZ2 > mBackFloorZ2 || mBackSector->floorplane.PointOnSide(Thread->Viewport->viewpoint.Pos) < 0)
|
||||
{
|
||||
draw_segment->drawsegclip.silhouette = SIL_BOTTOM;
|
||||
}
|
||||
|
||||
if (mFrontCeilingZ1 < mBackCeilingZ1 || mFrontCeilingZ2 < mBackCeilingZ2 ||
|
||||
mBackSector->ceilingplane.PointOnSide(Thread->Viewport->viewpoint.Pos) < 0)
|
||||
if (mFrontCeilingZ1 < mBackCeilingZ1 || mFrontCeilingZ2 < mBackCeilingZ2 || mBackSector->ceilingplane.PointOnSide(Thread->Viewport->viewpoint.Pos) < 0)
|
||||
{
|
||||
draw_segment->drawsegclip.silhouette |= SIL_TOP;
|
||||
}
|
||||
|
@ -351,71 +348,65 @@ namespace swrenderer
|
|||
//
|
||||
// killough 4/7/98: make doorclosed external variable
|
||||
|
||||
if (mDoorClosed || (mBackCeilingZ1 <= mFrontFloorZ1 && mBackCeilingZ2 <= mFrontFloorZ2))
|
||||
{
|
||||
if (mDoorClosed || (mBackCeilingZ1 <= mFrontFloorZ1 && mBackCeilingZ2 <= mFrontFloorZ2))
|
||||
{
|
||||
draw_segment->drawsegclip.SetBottomClip(Thread, start, stop, -1);
|
||||
draw_segment->drawsegclip.silhouette |= SIL_BOTTOM;
|
||||
}
|
||||
if (mDoorClosed || (mBackFloorZ1 >= mFrontCeilingZ1 && mBackFloorZ2 >= mFrontCeilingZ2))
|
||||
{
|
||||
draw_segment->drawsegclip.SetTopClip(Thread, start, stop, viewheight);
|
||||
draw_segment->drawsegclip.silhouette |= SIL_TOP;
|
||||
}
|
||||
draw_segment->drawsegclip.SetBottomClip(Thread, start, stop, -1);
|
||||
draw_segment->drawsegclip.silhouette |= SIL_BOTTOM;
|
||||
}
|
||||
if (mDoorClosed || (mBackFloorZ1 >= mFrontCeilingZ1 && mBackFloorZ2 >= mFrontCeilingZ2))
|
||||
{
|
||||
draw_segment->drawsegclip.SetTopClip(Thread, start, stop, viewheight);
|
||||
draw_segment->drawsegclip.silhouette |= SIL_TOP;
|
||||
}
|
||||
|
||||
if (m3DFloor.type == Fake3DOpaque::Normal)
|
||||
{
|
||||
if (r_3dfloors)
|
||||
{
|
||||
if (mBackSector->e && mBackSector->e->XFloor.ffloors.Size()) {
|
||||
for (i = 0; i < (int)mBackSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor *rover = mBackSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (!(rover->flags & FF_INVERTSIDES) || rover->flags & FF_ALLSIDES)) {
|
||||
draw_segment->SetHas3DFloorBackSectorWalls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mFrontSector->e && mFrontSector->e->XFloor.ffloors.Size()) {
|
||||
for (i = 0; i < (int)mFrontSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor *rover = mFrontSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) {
|
||||
draw_segment->SetHas3DFloorFrontSectorWalls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// allocate space for masked texture tables, if needed
|
||||
// [RH] Don't just allocate the space; fill it in too.
|
||||
if ((sidedef->GetTexture(side_t::mid).isValid() || draw_segment->Has3DFloorWalls() || IsFogBoundary(mFrontSector, mBackSector)) &&
|
||||
(mCeilingClipped != ProjectedWallCull::OutsideBelow || !sidedef->GetTexture(side_t::top).isValid()) &&
|
||||
if ((mCeilingClipped != ProjectedWallCull::OutsideBelow || !sidedef->GetTexture(side_t::top).isValid()) &&
|
||||
(mFloorClipped != ProjectedWallCull::OutsideAbove || !sidedef->GetTexture(side_t::bottom).isValid()) &&
|
||||
(WallC.sz1 >= TOO_CLOSE_Z && WallC.sz2 >= TOO_CLOSE_Z))
|
||||
{
|
||||
maskedtexture = true;
|
||||
|
||||
// kg3D - backup for mid and fake walls
|
||||
draw_segment->drawsegclip.SetBackupClip(Thread, start, stop, Thread->OpaquePass->ceilingclip);
|
||||
draw_segment->drawsegclip.bFogBoundary = IsFogBoundary(mFrontSector, mBackSector);
|
||||
if (sidedef->GetTexture(side_t::mid).isValid())
|
||||
if (r_3dfloors)
|
||||
{
|
||||
FTexture *tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true);
|
||||
FSoftwareTexture *pic = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr;
|
||||
if (pic)
|
||||
{
|
||||
draw_segment->SetHas3DFloorMidTexture();
|
||||
draw_segment->texcoords.ProjectTranslucent(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, pic);
|
||||
if (mBackSector->e && mBackSector->e->XFloor.ffloors.Size()) {
|
||||
for (int i = 0; i < (int)mBackSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor* rover = mBackSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (!(rover->flags & FF_INVERTSIDES) || rover->flags & FF_ALLSIDES)) {
|
||||
draw_segment->SetHas3DFloorBackSectorWalls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mFrontSector->e && mFrontSector->e->XFloor.ffloors.Size()) {
|
||||
for (int i = 0; i < (int)mFrontSector->e->XFloor.ffloors.Size(); i++) {
|
||||
F3DFloor* rover = mFrontSector->e->XFloor.ffloors[i];
|
||||
if (rover->flags & FF_RENDERSIDES && (rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) {
|
||||
draw_segment->SetHas3DFloorFrontSectorWalls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw_segment->light = mLight.GetLightPos(start);
|
||||
draw_segment->lightstep = mLight.GetLightStep();
|
||||
if (IsFogBoundary(mFrontSector, mBackSector))
|
||||
draw_segment->SetHasFogBoundary();
|
||||
|
||||
if (draw_segment->drawsegclip.bFogBoundary || draw_segment->texcoords || draw_segment->Has3DFloorWalls())
|
||||
if (mLineSegment->linedef->alpha > 0.0f && sidedef->GetTexture(side_t::mid).isValid())
|
||||
{
|
||||
FTexture* tex = TexMan.GetPalettedTexture(sidedef->GetTexture(side_t::mid), true);
|
||||
FSoftwareTexture* pic = tex && tex->isValid() ? tex->GetSoftwareTexture() : nullptr;
|
||||
if (pic)
|
||||
{
|
||||
draw_segment->SetHasTranslucentMidTexture();
|
||||
draw_segment->texcoords.ProjectTranslucent(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, pic);
|
||||
draw_segment->drawsegclip.silhouette |= SIL_TOP | SIL_BOTTOM;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -435,22 +426,18 @@ namespace swrenderer
|
|||
|
||||
MarkOpaquePassClip(start, stop);
|
||||
|
||||
// save sprite clipping info
|
||||
if (((draw_segment->drawsegclip.silhouette & SIL_TOP) || maskedtexture) && draw_segment->drawsegclip.sprtopclip == nullptr)
|
||||
bool needcliplists = draw_segment->HasFogBoundary() || draw_segment->HasTranslucentMidTexture() || draw_segment->Has3DFloorWalls();
|
||||
|
||||
if (((draw_segment->drawsegclip.silhouette & SIL_TOP) || needcliplists) && !draw_segment->drawsegclip.sprtopclip)
|
||||
{
|
||||
draw_segment->drawsegclip.SetTopClip(Thread, start, stop, Thread->OpaquePass->ceilingclip);
|
||||
}
|
||||
|
||||
if (((draw_segment->drawsegclip.silhouette & SIL_BOTTOM) || maskedtexture) && draw_segment->drawsegclip.sprbottomclip == nullptr)
|
||||
if (((draw_segment->drawsegclip.silhouette & SIL_BOTTOM) || needcliplists) && !draw_segment->drawsegclip.sprbottomclip)
|
||||
{
|
||||
draw_segment->drawsegclip.SetBottomClip(Thread, start, stop, Thread->OpaquePass->floorclip);
|
||||
}
|
||||
|
||||
if (maskedtexture && mLineSegment->sidedef->GetTexture(side_t::mid).isValid())
|
||||
{
|
||||
draw_segment->drawsegclip.silhouette |= SIL_TOP | SIL_BOTTOM;
|
||||
}
|
||||
|
||||
RenderMiddleTexture(start, stop);
|
||||
RenderTopTexture(start, stop);
|
||||
RenderBottomTexture(start, stop);
|
||||
|
|
|
@ -90,27 +90,22 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
float alpha = (float)MIN(curline->linedef->alpha, 1.);
|
||||
bool additive = (curline->linedef->flags & ML_ADDTRANS) != 0;
|
||||
|
||||
bool visible = alpha > 0.0f;
|
||||
if (!visible && !ds->drawsegclip.bFogBoundary && !ds->Has3DFloorWalls())
|
||||
if (!ds->HasTranslucentMidTexture() && !ds->HasFogBoundary() && !ds->Has3DFloorWalls())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// [RH] Draw fog partition
|
||||
if (ds->drawsegclip.bFogBoundary)
|
||||
if (ds->HasFogBoundary())
|
||||
{
|
||||
RenderFogBoundary renderfog;
|
||||
renderfog.Render(Thread, x1, x2, ds->drawsegclip, mLight);
|
||||
}
|
||||
|
||||
bool notrelevant = false;
|
||||
if (ds->texcoords && visible)
|
||||
if (ds->HasTranslucentMidTexture())
|
||||
notrelevant = RenderWall(ds, x1, x2);
|
||||
|
||||
if (ds->Has3DFloorFrontSectorWalls() || ds->Has3DFloorBackSectorWalls())
|
||||
if (ds->Has3DFloorWalls())
|
||||
{
|
||||
Render3DFloorWallRange(ds, x1, x2);
|
||||
}
|
||||
|
|
|
@ -470,7 +470,6 @@ namespace swrenderer
|
|||
this->flipx = flipx;
|
||||
CenterX = viewport->CenterX;
|
||||
WallTMapScale2 = viewport->WallTMapScale2;
|
||||
valid = true;
|
||||
}
|
||||
|
||||
float ProjectedWallTexcoords::VStep(int x) const
|
||||
|
|
|
@ -75,8 +75,6 @@ namespace swrenderer
|
|||
float VStep(int x) const;
|
||||
fixed_t UPos(int x) const;
|
||||
|
||||
explicit operator bool() const { return valid; }
|
||||
|
||||
private:
|
||||
void Project(RenderViewport* viewport, double walxrepeat, int x1, int x2, const FWallTmapVals& WallT, bool flipx = false);
|
||||
|
||||
|
@ -85,7 +83,6 @@ namespace swrenderer
|
|||
static double GetXScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart);
|
||||
static double GetYScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart);
|
||||
|
||||
bool valid = false;
|
||||
double CenterX;
|
||||
double WallTMapScale2;
|
||||
double walxrepeat;
|
||||
|
|
|
@ -214,7 +214,6 @@ namespace swrenderer
|
|||
draw_segment->drawsegclip.silhouette = SIL_BOTH;
|
||||
draw_segment->drawsegclip.SetTopClip(Thread, pl->left, pl->right, ceilingclip);
|
||||
draw_segment->drawsegclip.SetBottomClip(Thread, pl->left, pl->right, floorclip);
|
||||
draw_segment->drawsegclip.bFogBoundary = false;
|
||||
draw_segment->curline = nullptr;
|
||||
drawseglist->Push(draw_segment);
|
||||
|
||||
|
|
|
@ -157,13 +157,13 @@ namespace swrenderer
|
|||
if (ds->drawsegclip.CurrentPortalUniq != renderportal->CurrentPortalUniq)
|
||||
continue;
|
||||
|
||||
if (ds->texcoords || ds->drawsegclip.bFogBoundary)
|
||||
if (ds->HasTranslucentMidTexture() || ds->Has3DFloorWalls() || ds->HasFogBoundary())
|
||||
{
|
||||
RenderDrawSegment renderer(Thread);
|
||||
renderer.Render(ds, ds->x1, ds->x2, clip3DFloor);
|
||||
if (renew)
|
||||
{
|
||||
ds->drawsegclip.bFogBoundary = false; // don't draw fogboundary again
|
||||
ds->ClearFogBoundary(); // don't draw fogboundary again
|
||||
ds->drawsegclip.SetRangeUndrawn(ds->x1, ds->x2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ namespace swrenderer
|
|||
void SetRangeUndrawn(int x1, int x2);
|
||||
|
||||
uint8_t silhouette = 0; // 0=none, 1=bottom, 2=top, 3=both
|
||||
bool bFogBoundary = false;
|
||||
int CurrentPortalUniq = 0; // [ZZ] to identify the portal that this drawseg is in. used for sprite clipping.
|
||||
int SubsectorDepth;
|
||||
|
||||
|
@ -61,17 +60,21 @@ namespace swrenderer
|
|||
|
||||
DrawSegmentClipInfo drawsegclip;
|
||||
|
||||
bool Has3DFloorWalls() const { return b3DFloorBoundary != 0; }
|
||||
bool Has3DFloorFrontSectorWalls() const { return (b3DFloorBoundary & 2) == 2; }
|
||||
bool Has3DFloorBackSectorWalls() const { return (b3DFloorBoundary & 1) == 1; }
|
||||
bool Has3DFloorMidTexture() const { return (b3DFloorBoundary & 4) == 4; }
|
||||
bool HasFogBoundary() const { return (flags & 8) != 0; }
|
||||
bool Has3DFloorWalls() const { return (flags & 3) != 0; }
|
||||
bool Has3DFloorFrontSectorWalls() const { return (flags & 2) != 0; }
|
||||
bool Has3DFloorBackSectorWalls() const { return (flags & 1) != 0; }
|
||||
bool HasTranslucentMidTexture() const { return (flags & 4) != 0; }
|
||||
|
||||
void SetHas3DFloorFrontSectorWalls() { b3DFloorBoundary |= 2; }
|
||||
void SetHas3DFloorBackSectorWalls() { b3DFloorBoundary |= 1; }
|
||||
void SetHas3DFloorMidTexture() { b3DFloorBoundary |= 4; }
|
||||
void SetHasFogBoundary() { flags |= 8; }
|
||||
void SetHas3DFloorFrontSectorWalls() { flags |= 2; }
|
||||
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:
|
||||
uint8_t b3DFloorBoundary = 0; // 1=backsector, 2=frontsector, 4=midtexture
|
||||
int flags = 0; // 1=backsector, 2=frontsector, 4=midtexture, 8=fogboundary
|
||||
};
|
||||
|
||||
struct DrawSegmentGroup
|
||||
|
|
|
@ -405,7 +405,7 @@ namespace swrenderer
|
|||
DrawSegment *ds = segmentlist->Segment(index);
|
||||
|
||||
// determine if the drawseg obscures the sprite
|
||||
if (ds->x1 >= x2 || ds->x2 <= x1 || (!(ds->drawsegclip.silhouette & SIL_BOTH) && !ds->texcoords && !ds->drawsegclip.bFogBoundary))
|
||||
if (ds->x1 >= x2 || ds->x2 <= x1 || (!(ds->drawsegclip.silhouette & SIL_BOTH) && !ds->Has3DFloorWalls() && !ds->HasTranslucentMidTexture() && !ds->HasFogBoundary()))
|
||||
{
|
||||
// does not cover sprite
|
||||
continue;
|
||||
|
|
Loading…
Reference in a new issue