mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-25 13:41:05 +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->curline = mLineSegment;
|
||||
draw_segment->foggy = foggy;
|
||||
draw_segment->SubsectorDepth = Thread->OpaquePass->GetSubsectorDepth(mSubsector->Index());
|
||||
|
||||
bool markportal = ShouldMarkPortal();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -178,7 +178,7 @@ namespace swrenderer
|
|||
MaskedCycles.Clock();
|
||||
|
||||
CollectPortals();
|
||||
Thread->SpriteList->Sort();
|
||||
Thread->SpriteList->Sort(Thread);
|
||||
Thread->DrawSegments->BuildSegmentGroups();
|
||||
|
||||
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 SubsectorDepth;
|
||||
|
||||
bool Has3DFloorWalls() const { return b3DFloorBoundary != 0; }
|
||||
bool Has3DFloorFrontSectorWalls() const { return (b3DFloorBoundary & 2) == 2; }
|
||||
bool Has3DFloorBackSectorWalls() const { return (b3DFloorBoundary & 1) == 1; }
|
||||
|
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue