- fix translucent walls when r_models is enabled

This commit is contained in:
Magnus Norddahl 2018-05-06 02:54:03 +02:00
parent d667a0192a
commit 1d929dd79b
9 changed files with 130 additions and 26 deletions

View file

@ -346,6 +346,7 @@ namespace swrenderer
draw_segment->x2 = stop;
draw_segment->curline = mLineSegment;
draw_segment->foggy = foggy;
draw_segment->SubsectorDepth = Thread->OpaquePass->GetSubsectorDepth(mSubsector->Index());
bool markportal = ShouldMarkPortal();

View file

@ -497,6 +497,11 @@ namespace swrenderer
{
outersubsector = true;
InSubsector = sub;
// Mark the visual sorting depth of this subsector
uint32_t subsectorDepth = (uint32_t)PvsSubsectors.size();
SubsectorDepths[sub->Index()] = subsectorDepth;
PvsSubsectors.push_back(sub->Index());
}
#ifdef RANGECHECK
@ -837,6 +842,11 @@ namespace swrenderer
if (Thread->MainThread)
WallCycles.Clock();
for (uint32_t sub : PvsSubsectors)
SubsectorDepths[sub] = 0xffffffff;
SubsectorDepths.resize(level.subsectors.Size(), 0xffffffff);
PvsSubsectors.clear();
SeenSpriteSectors.clear();
SeenActors.clear();

View file

@ -71,6 +71,8 @@ namespace swrenderer
void ClearSeenSprites() { SeenSpriteSectors.clear(); SeenActors.clear(); }
uint32_t GetSubsectorDepth(int index) const { return SubsectorDepths[index]; }
short floorclip[MAXWIDTH];
short ceilingclip[MAXWIDTH];
@ -97,5 +99,7 @@ namespace swrenderer
SWRenderLine renderline;
std::set<sector_t*> SeenSpriteSectors;
std::set<AActor*> SeenActors;
std::vector<uint32_t> PvsSubsectors;
std::vector<uint32_t> SubsectorDepths;
};
}

View file

@ -178,7 +178,7 @@ namespace swrenderer
MaskedCycles.Clock();
CollectPortals();
Thread->SpriteList->Sort();
Thread->SpriteList->Sort(Thread);
Thread->DrawSegments->BuildSegmentGroups();
Clip3DFloors *clip3d = Thread->Clip3D.get();

View file

@ -53,6 +53,8 @@ namespace swrenderer
int CurrentPortalUniq = 0; // [ZZ] to identify the portal that this drawseg is in. used for sprite clipping.
int SubsectorDepth;
bool Has3DFloorWalls() const { return b3DFloorBoundary != 0; }
bool Has3DFloorFrontSectorWalls() const { return (b3DFloorBoundary & 2) == 2; }
bool Has3DFloorBackSectorWalls() const { return (b3DFloorBoundary & 1) == 1; }

View file

@ -53,6 +53,22 @@ namespace swrenderer
{
if (IsModel())
{
// Draw segments behind model
DrawSegmentList *segmentlist = thread->DrawSegments.get();
RenderPortal *renderportal = thread->Portal.get();
for (unsigned int index = 0; index != segmentlist->TranslucentSegmentsCount(); index++)
{
DrawSegment *ds = segmentlist->TranslucentSegment(index);
if (ds->SubsectorDepth >= SubsectorDepth && ds->CurrentPortalUniq == renderportal->CurrentPortalUniq)
{
int r1 = MAX<int>(ds->x1, 0);
int r2 = MIN<int>(ds->x2, viewwidth - 1);
RenderDrawSegment renderer(thread);
renderer.Render(ds, r1, r2, clip3DFloor);
}
}
Render(thread, nullptr, nullptr, 0, 0, clip3DFloor);
return;
}
@ -299,33 +315,52 @@ namespace swrenderer
RenderPortal *renderportal = thread->Portal.get();
// Render draw segments behind sprite
for (unsigned int index = 0; index != segmentlist->TranslucentSegmentsCount(); index++)
if (r_models)
{
DrawSegment *ds = segmentlist->TranslucentSegment(index);
if (ds->x1 >= x2 || ds->x2 <= x1)
int subsectordepth = spr->SubsectorDepth;
for (unsigned int index = 0; index != segmentlist->TranslucentSegmentsCount(); index++)
{
continue;
}
float neardepth = MIN(ds->sz1, ds->sz2);
float fardepth = MAX(ds->sz1, ds->sz2);
// Check if sprite is in front of draw seg:
if ((!spr->IsWallSprite() && neardepth > spr->depth) || ((spr->IsWallSprite() || fardepth > spr->depth) &&
(spr->gpos.Y - ds->curline->v1->fY()) * (ds->curline->v2->fX() - ds->curline->v1->fX()) -
(spr->gpos.X - ds->curline->v1->fX()) * (ds->curline->v2->fY() - ds->curline->v1->fY()) <= 0))
{
if (ds->CurrentPortalUniq == renderportal->CurrentPortalUniq)
DrawSegment *ds = segmentlist->TranslucentSegment(index);
if (ds->SubsectorDepth >= subsectordepth && ds->CurrentPortalUniq == renderportal->CurrentPortalUniq)
{
int r1 = MAX<int>(ds->x1, x1);
int r2 = MIN<int>(ds->x2, x2);
int r1 = MAX<int>(ds->x1, 0);
int r2 = MIN<int>(ds->x2, viewwidth - 1);
RenderDrawSegment renderer(thread);
renderer.Render(ds, r1, r2, clip3DFloor);
}
}
}
else
{
for (unsigned int index = 0; index != segmentlist->TranslucentSegmentsCount(); index++)
{
DrawSegment *ds = segmentlist->TranslucentSegment(index);
if (ds->x1 >= x2 || ds->x2 <= x1)
{
continue;
}
float neardepth = MIN(ds->sz1, ds->sz2);
float fardepth = MAX(ds->sz1, ds->sz2);
// Check if sprite is in front of draw seg:
if ((!spr->IsWallSprite() && neardepth > spr->depth) || ((spr->IsWallSprite() || fardepth > spr->depth) &&
(spr->gpos.Y - ds->curline->v1->fY()) * (ds->curline->v2->fX() - ds->curline->v1->fX()) -
(spr->gpos.X - ds->curline->v1->fX()) * (ds->curline->v2->fY() - ds->curline->v1->fY()) <= 0))
{
if (ds->CurrentPortalUniq == renderportal->CurrentPortalUniq)
{
int r1 = MAX<int>(ds->x1, x1);
int r2 = MIN<int>(ds->x2, x2);
RenderDrawSegment renderer(thread);
renderer.Render(ds, r1, r2, clip3DFloor);
}
}
}
}
for (unsigned int groupIndex = 0; groupIndex < segmentlist->SegmentGroups.Size(); groupIndex++)
{

View file

@ -43,10 +43,9 @@ namespace swrenderer
bool IsCurrentPortalUniq(int portalUniq) const { return CurrentPortalUniq == portalUniq; }
const FVector3 &WorldPos() const { return gpos; }
double SortDist2D() const { return DVector2(deltax, deltay).LengthSquared(); }
float SortDist() const { return idepth; }
float DrawSegDepth() const { return depth; }
int SubsectorDepth;
protected:
virtual bool IsParticle() const { return false; }

View file

@ -59,7 +59,7 @@ namespace swrenderer
Sprites.Push(sprite);
}
void VisibleSpriteList::Sort()
void VisibleSpriteList::Sort(RenderThread *thread)
{
unsigned int first = StartIndices.Size() == 0 ? 0 : StartIndices.Last();
unsigned int count = Sprites.Size() - first;
@ -83,9 +83,59 @@ namespace swrenderer
SortedSprites[i] = Sprites[first + count - i - 1];
}
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](VisibleSprite *a, VisibleSprite *b) -> bool
if (r_models) // To do: only do this if models are spotted - just in case there's some lame renderhack somewhere that relies on Carmacks algorithm
{
return a->SortDist() > b->SortDist();
});
for (unsigned int i = 0; i < count; i++)
{
FVector2 worldPos = SortedSprites[i]->WorldPos().XY();
SortedSprites[i]->SubsectorDepth = FindSubsectorDepth(thread, { worldPos.X, worldPos.Y });
}
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](VisibleSprite *a, VisibleSprite *b) -> bool
{
if (a->SubsectorDepth != b->SubsectorDepth)
return a->SubsectorDepth < b->SubsectorDepth;
else
return a->SortDist() > b->SortDist();
});
}
else
{
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](VisibleSprite *a, VisibleSprite *b) -> bool
{
return a->SortDist() > b->SortDist();
});
}
}
uint32_t VisibleSpriteList::FindSubsectorDepth(RenderThread *thread, const DVector2 &worldPos)
{
if (level.nodes.Size() == 0)
{
subsector_t *sub = &level.subsectors[0];
return thread->OpaquePass->GetSubsectorDepth(sub->Index());
}
else
{
return FindSubsectorDepth(thread, worldPos, level.HeadNode());
}
}
uint32_t VisibleSpriteList::FindSubsectorDepth(RenderThread *thread, const DVector2 &worldPos, void *node)
{
while (!((size_t)node & 1)) // Keep going until found a subsector
{
node_t *bsp = (node_t *)node;
DVector2 planePos(FIXED2DBL(bsp->x), FIXED2DBL(bsp->y));
DVector2 planeNormal = DVector2(FIXED2DBL(-bsp->dy), FIXED2DBL(bsp->dx));
double planeD = planeNormal | planePos;
int side = (worldPos | planeNormal) > planeD;
node = bsp->children[side];
}
subsector_t *sub = (subsector_t *)((uint8_t *)node - 1);
return thread->OpaquePass->GetSubsectorDepth(sub->Index());
}
}

View file

@ -12,11 +12,14 @@ namespace swrenderer
void PushPortal();
void PopPortal();
void Push(VisibleSprite *sprite);
void Sort();
void Sort(RenderThread *thread);
TArray<VisibleSprite *> SortedSprites;
private:
uint32_t FindSubsectorDepth(RenderThread *thread, const DVector2 &worldPos);
uint32_t FindSubsectorDepth(RenderThread *thread, const DVector2 &worldPos, void *node);
TArray<VisibleSprite *> Sprites;
TArray<unsigned int> StartIndices;
};