mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-03-06 01:21:55 +00:00
- fix translucent walls when r_models is enabled
This commit is contained in:
parent
d667a0192a
commit
1d929dd79b
9 changed files with 130 additions and 26 deletions
|
@ -346,6 +346,7 @@ namespace swrenderer
|
||||||
draw_segment->x2 = stop;
|
draw_segment->x2 = stop;
|
||||||
draw_segment->curline = mLineSegment;
|
draw_segment->curline = mLineSegment;
|
||||||
draw_segment->foggy = foggy;
|
draw_segment->foggy = foggy;
|
||||||
|
draw_segment->SubsectorDepth = Thread->OpaquePass->GetSubsectorDepth(mSubsector->Index());
|
||||||
|
|
||||||
bool markportal = ShouldMarkPortal();
|
bool markportal = ShouldMarkPortal();
|
||||||
|
|
||||||
|
|
|
@ -497,6 +497,11 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
outersubsector = true;
|
outersubsector = true;
|
||||||
InSubsector = sub;
|
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
|
#ifdef RANGECHECK
|
||||||
|
@ -837,6 +842,11 @@ namespace swrenderer
|
||||||
if (Thread->MainThread)
|
if (Thread->MainThread)
|
||||||
WallCycles.Clock();
|
WallCycles.Clock();
|
||||||
|
|
||||||
|
for (uint32_t sub : PvsSubsectors)
|
||||||
|
SubsectorDepths[sub] = 0xffffffff;
|
||||||
|
SubsectorDepths.resize(level.subsectors.Size(), 0xffffffff);
|
||||||
|
|
||||||
|
PvsSubsectors.clear();
|
||||||
SeenSpriteSectors.clear();
|
SeenSpriteSectors.clear();
|
||||||
SeenActors.clear();
|
SeenActors.clear();
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,8 @@ namespace swrenderer
|
||||||
|
|
||||||
void ClearSeenSprites() { SeenSpriteSectors.clear(); SeenActors.clear(); }
|
void ClearSeenSprites() { SeenSpriteSectors.clear(); SeenActors.clear(); }
|
||||||
|
|
||||||
|
uint32_t GetSubsectorDepth(int index) const { return SubsectorDepths[index]; }
|
||||||
|
|
||||||
short floorclip[MAXWIDTH];
|
short floorclip[MAXWIDTH];
|
||||||
short ceilingclip[MAXWIDTH];
|
short ceilingclip[MAXWIDTH];
|
||||||
|
|
||||||
|
@ -97,5 +99,7 @@ namespace swrenderer
|
||||||
SWRenderLine renderline;
|
SWRenderLine renderline;
|
||||||
std::set<sector_t*> SeenSpriteSectors;
|
std::set<sector_t*> SeenSpriteSectors;
|
||||||
std::set<AActor*> SeenActors;
|
std::set<AActor*> SeenActors;
|
||||||
|
std::vector<uint32_t> PvsSubsectors;
|
||||||
|
std::vector<uint32_t> SubsectorDepths;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,7 +178,7 @@ namespace swrenderer
|
||||||
MaskedCycles.Clock();
|
MaskedCycles.Clock();
|
||||||
|
|
||||||
CollectPortals();
|
CollectPortals();
|
||||||
Thread->SpriteList->Sort();
|
Thread->SpriteList->Sort(Thread);
|
||||||
Thread->DrawSegments->BuildSegmentGroups();
|
Thread->DrawSegments->BuildSegmentGroups();
|
||||||
|
|
||||||
Clip3DFloors *clip3d = Thread->Clip3D.get();
|
Clip3DFloors *clip3d = Thread->Clip3D.get();
|
||||||
|
|
|
@ -53,6 +53,8 @@ namespace swrenderer
|
||||||
|
|
||||||
int CurrentPortalUniq = 0; // [ZZ] to identify the portal that this drawseg is in. used for sprite clipping.
|
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 Has3DFloorWalls() const { return b3DFloorBoundary != 0; }
|
||||||
bool Has3DFloorFrontSectorWalls() const { return (b3DFloorBoundary & 2) == 2; }
|
bool Has3DFloorFrontSectorWalls() const { return (b3DFloorBoundary & 2) == 2; }
|
||||||
bool Has3DFloorBackSectorWalls() const { return (b3DFloorBoundary & 1) == 1; }
|
bool Has3DFloorBackSectorWalls() const { return (b3DFloorBoundary & 1) == 1; }
|
||||||
|
|
|
@ -53,6 +53,22 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
if (IsModel())
|
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);
|
Render(thread, nullptr, nullptr, 0, 0, clip3DFloor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -299,33 +315,52 @@ namespace swrenderer
|
||||||
RenderPortal *renderportal = thread->Portal.get();
|
RenderPortal *renderportal = thread->Portal.get();
|
||||||
|
|
||||||
// Render draw segments behind sprite
|
// Render draw segments behind sprite
|
||||||
for (unsigned int index = 0; index != segmentlist->TranslucentSegmentsCount(); index++)
|
if (r_models)
|
||||||
{
|
{
|
||||||
DrawSegment *ds = segmentlist->TranslucentSegment(index);
|
int subsectordepth = spr->SubsectorDepth;
|
||||||
|
for (unsigned int index = 0; index != segmentlist->TranslucentSegmentsCount(); index++)
|
||||||
if (ds->x1 >= x2 || ds->x2 <= x1)
|
|
||||||
{
|
{
|
||||||
continue;
|
DrawSegment *ds = segmentlist->TranslucentSegment(index);
|
||||||
}
|
if (ds->SubsectorDepth >= subsectordepth && ds->CurrentPortalUniq == renderportal->CurrentPortalUniq)
|
||||||
|
|
||||||
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 r1 = MAX<int>(ds->x1, 0);
|
||||||
int r2 = MIN<int>(ds->x2, x2);
|
int r2 = MIN<int>(ds->x2, viewwidth - 1);
|
||||||
|
|
||||||
RenderDrawSegment renderer(thread);
|
RenderDrawSegment renderer(thread);
|
||||||
renderer.Render(ds, r1, r2, clip3DFloor);
|
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++)
|
for (unsigned int groupIndex = 0; groupIndex < segmentlist->SegmentGroups.Size(); groupIndex++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,10 +43,9 @@ namespace swrenderer
|
||||||
bool IsCurrentPortalUniq(int portalUniq) const { return CurrentPortalUniq == portalUniq; }
|
bool IsCurrentPortalUniq(int portalUniq) const { return CurrentPortalUniq == portalUniq; }
|
||||||
const FVector3 &WorldPos() const { return gpos; }
|
const FVector3 &WorldPos() const { return gpos; }
|
||||||
|
|
||||||
double SortDist2D() const { return DVector2(deltax, deltay).LengthSquared(); }
|
|
||||||
float SortDist() const { return idepth; }
|
float SortDist() const { return idepth; }
|
||||||
|
|
||||||
float DrawSegDepth() const { return depth; }
|
int SubsectorDepth;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool IsParticle() const { return false; }
|
virtual bool IsParticle() const { return false; }
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace swrenderer
|
||||||
Sprites.Push(sprite);
|
Sprites.Push(sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisibleSpriteList::Sort()
|
void VisibleSpriteList::Sort(RenderThread *thread)
|
||||||
{
|
{
|
||||||
unsigned int first = StartIndices.Size() == 0 ? 0 : StartIndices.Last();
|
unsigned int first = StartIndices.Size() == 0 ? 0 : StartIndices.Last();
|
||||||
unsigned int count = Sprites.Size() - first;
|
unsigned int count = Sprites.Size() - first;
|
||||||
|
@ -83,9 +83,59 @@ namespace swrenderer
|
||||||
SortedSprites[i] = Sprites[first + count - i - 1];
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,14 @@ namespace swrenderer
|
||||||
void PushPortal();
|
void PushPortal();
|
||||||
void PopPortal();
|
void PopPortal();
|
||||||
void Push(VisibleSprite *sprite);
|
void Push(VisibleSprite *sprite);
|
||||||
void Sort();
|
void Sort(RenderThread *thread);
|
||||||
|
|
||||||
TArray<VisibleSprite *> SortedSprites;
|
TArray<VisibleSprite *> SortedSprites;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint32_t FindSubsectorDepth(RenderThread *thread, const DVector2 &worldPos);
|
||||||
|
uint32_t FindSubsectorDepth(RenderThread *thread, const DVector2 &worldPos, void *node);
|
||||||
|
|
||||||
TArray<VisibleSprite *> Sprites;
|
TArray<VisibleSprite *> Sprites;
|
||||||
TArray<unsigned int> StartIndices;
|
TArray<unsigned int> StartIndices;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue