mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-23 04:22:34 +00:00
This commit is contained in:
commit
6a402c28d8
15 changed files with 194 additions and 200 deletions
|
@ -319,16 +319,22 @@ namespace swrenderer
|
|||
side_t *sidedef = mLineSegment->sidedef;
|
||||
|
||||
RenderPortal *renderportal = Thread->Portal.get();
|
||||
Clip3DFloors *clip3d = Thread->Clip3D.get();
|
||||
|
||||
DrawSegment *draw_segment = Thread->FrameMemory->NewObject<DrawSegment>();
|
||||
Thread->DrawSegments->Push(draw_segment);
|
||||
|
||||
// 3D floors code abuses the line render code to update plane clipping
|
||||
// lists but doesn't actually draw anything.
|
||||
bool onlyUpdatePlaneClip = (clip3d->fake3D & FAKE3D_FAKEMASK) ? true : false;
|
||||
if (!onlyUpdatePlaneClip)
|
||||
Thread->DrawSegments->Push(draw_segment);
|
||||
|
||||
draw_segment->CurrentPortalUniq = renderportal->CurrentPortalUniq;
|
||||
draw_segment->sx1 = WallC.sx1;
|
||||
draw_segment->sx2 = WallC.sx2;
|
||||
draw_segment->sz1 = WallC.sz1;
|
||||
draw_segment->sz2 = WallC.sz2;
|
||||
draw_segment->cx = WallC.tleft.X;;
|
||||
draw_segment->cx = WallC.tleft.X;
|
||||
draw_segment->cy = WallC.tleft.Y;
|
||||
draw_segment->cdx = WallC.tright.X - WallC.tleft.X;
|
||||
draw_segment->cdy = WallC.tright.Y - WallC.tleft.Y;
|
||||
|
@ -338,20 +344,8 @@ namespace swrenderer
|
|||
draw_segment->x1 = start;
|
||||
draw_segment->x2 = stop;
|
||||
draw_segment->curline = mLineSegment;
|
||||
draw_segment->bFogBoundary = false;
|
||||
draw_segment->bFakeBoundary = false;
|
||||
draw_segment->foggy = foggy;
|
||||
|
||||
Clip3DFloors *clip3d = Thread->Clip3D.get();
|
||||
if (clip3d->fake3D & FAKE3D_FAKEMASK) draw_segment->fake = 1;
|
||||
else draw_segment->fake = 0;
|
||||
|
||||
draw_segment->sprtopclip = nullptr;
|
||||
draw_segment->sprbottomclip = nullptr;
|
||||
draw_segment->maskedtexturecol = nullptr;
|
||||
draw_segment->bkup = nullptr;
|
||||
draw_segment->swall = nullptr;
|
||||
|
||||
bool markportal = ShouldMarkPortal();
|
||||
|
||||
if (markportal)
|
||||
|
@ -369,8 +363,6 @@ namespace swrenderer
|
|||
else
|
||||
{
|
||||
// two sided line
|
||||
draw_segment->silhouette = 0;
|
||||
|
||||
if (mFrontFloorZ1 > mBackFloorZ1 || mFrontFloorZ2 > mBackFloorZ2 ||
|
||||
mBackSector->floorplane.PointOnSide(Thread->Viewport->viewpoint.Pos) < 0)
|
||||
{
|
||||
|
@ -406,29 +398,32 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
if (!draw_segment->fake && r_3dfloors && 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->bFakeBoundary |= 1;
|
||||
break;
|
||||
if (!onlyUpdatePlaneClip && 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!draw_segment->fake && r_3dfloors && 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->bFakeBoundary |= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// kg3D - no for fakes
|
||||
if (!draw_segment->fake)
|
||||
|
||||
if (!onlyUpdatePlaneClip)
|
||||
// allocate space for masked texture tables, if needed
|
||||
// [RH] Don't just allocate the space; fill it in too.
|
||||
if ((TexMan(sidedef->GetTexture(side_t::mid), true)->UseType != FTexture::TEX_Null || draw_segment->bFakeBoundary || IsFogBoundary(mFrontSector, mBackSector)) &&
|
||||
if ((TexMan(sidedef->GetTexture(side_t::mid), true)->UseType != FTexture::TEX_Null || draw_segment->Has3DFloorWalls() || IsFogBoundary(mFrontSector, mBackSector)) &&
|
||||
(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))
|
||||
|
@ -444,10 +439,10 @@ namespace swrenderer
|
|||
memcpy(draw_segment->bkup, &Thread->OpaquePass->ceilingclip[start], sizeof(short)*(stop - start));
|
||||
|
||||
draw_segment->bFogBoundary = IsFogBoundary(mFrontSector, mBackSector);
|
||||
if (sidedef->GetTexture(side_t::mid).isValid() || draw_segment->bFakeBoundary)
|
||||
if (sidedef->GetTexture(side_t::mid).isValid() || draw_segment->Has3DFloorWalls())
|
||||
{
|
||||
if (sidedef->GetTexture(side_t::mid).isValid())
|
||||
draw_segment->bFakeBoundary |= 4; // it is also mid texture
|
||||
draw_segment->SetHas3DFloorMidTexture();
|
||||
|
||||
draw_segment->maskedtexturecol = Thread->FrameMemory->AllocMemory<fixed_t>(stop - start);
|
||||
draw_segment->swall = Thread->FrameMemory->AllocMemory<float>(stop - start);
|
||||
|
@ -510,7 +505,7 @@ namespace swrenderer
|
|||
|
||||
if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr)
|
||||
{
|
||||
Thread->DrawSegments->PushInteresting(draw_segment);
|
||||
Thread->DrawSegments->PushTranslucent(draw_segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace swrenderer
|
|||
FDynamicColormap *patchstylecolormap = nullptr;
|
||||
bool visible = columndrawerargs.SetStyle(viewport, LegacyRenderStyles[additive ? STYLE_Add : STYLE_Translucent], alpha, 0, 0, patchstylecolormap);
|
||||
|
||||
if (!visible && !ds->bFogBoundary && !ds->bFakeBoundary)
|
||||
if (!visible && !ds->bFogBoundary && !ds->Has3DFloorWalls())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ namespace swrenderer
|
|||
if (ds->maskedtexturecol == nullptr)
|
||||
renderwall = false;
|
||||
}
|
||||
else if ((ds->bFakeBoundary && !(ds->bFakeBoundary & 4)) || !visible)
|
||||
else if ((ds->Has3DFloorWalls() && !ds->Has3DFloorMidTexture()) || !visible)
|
||||
{
|
||||
renderwall = false;
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ namespace swrenderer
|
|||
if (renderwall)
|
||||
notrelevant = RenderWall(ds, x1, x2, walldrawerargs, columndrawerargs, visible, basecolormap, wallshade, wrap);
|
||||
|
||||
if (ds->bFakeBoundary & 3)
|
||||
if (ds->Has3DFloorFrontSectorWalls() || ds->Has3DFloorBackSectorWalls())
|
||||
{
|
||||
RenderFakeWallRange(ds, x1, x2, wallshade);
|
||||
}
|
||||
|
@ -540,7 +540,7 @@ namespace swrenderer
|
|||
{
|
||||
return;
|
||||
}
|
||||
if ((ds->bFakeBoundary & 3) == 2)
|
||||
if (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls())
|
||||
{
|
||||
sector_t *sec = backsector;
|
||||
backsector = frontsector;
|
||||
|
@ -709,7 +709,7 @@ namespace swrenderer
|
|||
CameraLight *cameraLight = CameraLight::Instance();
|
||||
if (cameraLight->FixedLightLevel() < 0)
|
||||
{
|
||||
if ((ds->bFakeBoundary & 3) == 2)
|
||||
if (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls())
|
||||
{
|
||||
for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
|
@ -888,7 +888,7 @@ namespace swrenderer
|
|||
CameraLight *cameraLight = CameraLight::Instance();
|
||||
if (cameraLight->FixedLightLevel() < 0)
|
||||
{
|
||||
if ((ds->bFakeBoundary & 3) == 2)
|
||||
if (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls())
|
||||
{
|
||||
for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
|
|
|
@ -103,23 +103,28 @@ namespace swrenderer
|
|||
// calls to GetPixels for this to work.
|
||||
|
||||
static std::mutex loadmutex;
|
||||
loadmutex.lock();
|
||||
try
|
||||
|
||||
std::unique_lock<std::mutex> lock(loadmutex);
|
||||
|
||||
texture->GetPixels();
|
||||
const FTexture::Span *spans;
|
||||
texture->GetColumn(0, &spans);
|
||||
if (Viewport->RenderTarget->IsBgra())
|
||||
{
|
||||
texture->GetPixels();
|
||||
const FTexture::Span *spans;
|
||||
texture->GetColumn(0, &spans);
|
||||
if (Viewport->RenderTarget->IsBgra())
|
||||
{
|
||||
texture->GetPixelsBgra();
|
||||
texture->GetColumnBgra(0, &spans);
|
||||
}
|
||||
loadmutex.unlock();
|
||||
texture->GetPixelsBgra();
|
||||
texture->GetColumnBgra(0, &spans);
|
||||
}
|
||||
catch (...)
|
||||
}
|
||||
|
||||
void RenderThread::PreparePolyObject(subsector_t *sub)
|
||||
{
|
||||
static std::mutex polyobjmutex;
|
||||
|
||||
std::unique_lock<std::mutex> lock(polyobjmutex);
|
||||
|
||||
if (sub->BSP == nullptr || sub->BSP->bDirty)
|
||||
{
|
||||
loadmutex.unlock();
|
||||
throw;
|
||||
sub->BuildPolyBSP();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,9 @@ namespace swrenderer
|
|||
|
||||
// Make sure texture can accessed safely
|
||||
void PrepareTexture(FTexture *texture);
|
||||
|
||||
// Setup poly object in a threadsafe manner
|
||||
void PreparePolyObject(subsector_t *sub);
|
||||
|
||||
private:
|
||||
std::unique_ptr<SWTruecolorDrawers> tc_drawers;
|
||||
|
|
|
@ -404,10 +404,8 @@ namespace swrenderer
|
|||
|
||||
void RenderOpaquePass::AddPolyobjs(subsector_t *sub)
|
||||
{
|
||||
if (sub->BSP == nullptr || sub->BSP->bDirty)
|
||||
{
|
||||
sub->BuildPolyBSP();
|
||||
}
|
||||
Thread->PreparePolyObject(sub);
|
||||
|
||||
if (sub->BSP->Nodes.Size() == 0)
|
||||
{
|
||||
RenderSubsector(&sub->BSP->Subsectors[0]);
|
||||
|
|
|
@ -217,7 +217,6 @@ namespace swrenderer
|
|||
draw_segment->swall = nullptr;
|
||||
draw_segment->bFogBoundary = false;
|
||||
draw_segment->curline = nullptr;
|
||||
draw_segment->fake = 0;
|
||||
draw_segment->foggy = false;
|
||||
memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short));
|
||||
memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
|
||||
|
@ -528,8 +527,8 @@ namespace swrenderer
|
|||
|
||||
void RenderPortal::SetMainPortal()
|
||||
{
|
||||
WindowLeft = 0;
|
||||
WindowRight = viewwidth;
|
||||
WindowLeft = Thread->X1;
|
||||
WindowRight = Thread->X2;
|
||||
MirrorFlags = 0;
|
||||
CurrentPortal = nullptr;
|
||||
CurrentPortalUniq = 0;
|
||||
|
|
|
@ -136,37 +136,11 @@ namespace swrenderer
|
|||
RenderPortal *renderportal = Thread->Portal.get();
|
||||
DrawSegmentList *drawseglist = Thread->DrawSegments.get();
|
||||
|
||||
int numGroups = drawseglist->SegmentGroups.Size();
|
||||
for (int j = 0; j < numGroups; j++)
|
||||
drawseglist->SegmentGroups[j].GroupDrawn = false;
|
||||
|
||||
auto &sortedSprites = Thread->SpriteList->SortedSprites;
|
||||
for (int i = sortedSprites.Size(); i > 0; i--)
|
||||
{
|
||||
VisibleSprite *sprite = sortedSprites[i - 1];
|
||||
|
||||
// Draw the draw segments known to be behind us now.
|
||||
for (int j = numGroups; j > 0; j--)
|
||||
{
|
||||
auto &group = drawseglist->SegmentGroups[j - 1];
|
||||
if (!group.GroupDrawn && group.neardepth > sprite->DrawSegDepth())
|
||||
{
|
||||
for (unsigned int index = group.BeginIndex; index != group.EndIndex; index++)
|
||||
{
|
||||
DrawSegment *ds = drawseglist->Segment(index);
|
||||
|
||||
if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq) continue;
|
||||
if (ds->fake) continue;
|
||||
if (ds->maskedtexturecol != nullptr || ds->bFogBoundary)
|
||||
{
|
||||
RenderDrawSegment renderer(Thread);
|
||||
renderer.Render(ds, ds->x1, ds->x2);
|
||||
}
|
||||
}
|
||||
group.GroupDrawn = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (sprite->IsCurrentPortalUniq(renderportal->CurrentPortalUniq))
|
||||
{
|
||||
sprite->Render(Thread);
|
||||
|
@ -187,8 +161,6 @@ namespace swrenderer
|
|||
// [ZZ] the same as above
|
||||
if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq)
|
||||
continue;
|
||||
// kg3D - no fake segs
|
||||
if (ds->fake) continue;
|
||||
if (ds->maskedtexturecol != nullptr || ds->bFogBoundary)
|
||||
{
|
||||
RenderDrawSegment renderer(Thread);
|
||||
|
|
|
@ -63,15 +63,15 @@ namespace swrenderer
|
|||
StartIndices.Clear();
|
||||
StartIndices.Push(0);
|
||||
|
||||
InterestingSegments.Clear();
|
||||
StartInterestingIndices.Clear();
|
||||
StartInterestingIndices.Push(0);
|
||||
TranslucentSegments.Clear();
|
||||
StartTranslucentIndices.Clear();
|
||||
StartTranslucentIndices.Push(0);
|
||||
}
|
||||
|
||||
void DrawSegmentList::PushPortal()
|
||||
{
|
||||
StartIndices.Push(Segments.Size());
|
||||
StartInterestingIndices.Push(InterestingSegments.Size());
|
||||
StartTranslucentIndices.Push(TranslucentSegments.Size());
|
||||
}
|
||||
|
||||
void DrawSegmentList::PopPortal()
|
||||
|
@ -79,8 +79,8 @@ namespace swrenderer
|
|||
Segments.Resize(StartIndices.Last());
|
||||
StartIndices.Pop();
|
||||
|
||||
InterestingSegments.Resize(StartInterestingIndices.Last());
|
||||
StartInterestingIndices.Pop();
|
||||
TranslucentSegments.Resize(StartTranslucentIndices.Last());
|
||||
StartTranslucentIndices.Pop();
|
||||
}
|
||||
|
||||
void DrawSegmentList::Push(DrawSegment *segment)
|
||||
|
@ -88,9 +88,9 @@ namespace swrenderer
|
|||
Segments.Push(segment);
|
||||
}
|
||||
|
||||
void DrawSegmentList::PushInteresting(DrawSegment *segment)
|
||||
void DrawSegmentList::PushTranslucent(DrawSegment *segment)
|
||||
{
|
||||
InterestingSegments.Push(segment);
|
||||
TranslucentSegments.Push(segment);
|
||||
}
|
||||
|
||||
void DrawSegmentList::BuildSegmentGroups()
|
||||
|
@ -131,9 +131,6 @@ namespace swrenderer
|
|||
{
|
||||
ds = Segment(groupIndex);
|
||||
|
||||
// kg3D - no clipping on fake segs
|
||||
if (ds->fake) continue;
|
||||
|
||||
if (ds->silhouette & SIL_BOTTOM)
|
||||
{
|
||||
short *clip1 = clipbottom + ds->x1;
|
||||
|
|
|
@ -36,23 +36,33 @@ namespace swrenderer
|
|||
float siz1, siz2; // 1/z for left, right of parent seg on screen
|
||||
float cx, cy, cdx, cdy;
|
||||
float yscale;
|
||||
uint8_t silhouette; // 0=none, 1=bottom, 2=top, 3=both
|
||||
uint8_t bFogBoundary;
|
||||
uint8_t bFakeBoundary; // for fake walls
|
||||
int shade;
|
||||
bool foggy;
|
||||
uint8_t silhouette = 0; // 0=none, 1=bottom, 2=top, 3=both
|
||||
bool bFogBoundary = false;
|
||||
int shade = 0;
|
||||
bool foggy = false;
|
||||
|
||||
// Pointers to lists for sprite clipping, all three adjusted so [x1] is first value.
|
||||
short *sprtopclip;
|
||||
short *sprbottomclip;
|
||||
fixed_t *maskedtexturecol;
|
||||
float *swall;
|
||||
short *bkup; // sprtopclip backup, for mid and fake textures
|
||||
short *sprtopclip = nullptr;
|
||||
short *sprbottomclip = nullptr;
|
||||
fixed_t *maskedtexturecol = nullptr;
|
||||
float *swall = nullptr;
|
||||
short *bkup = nullptr; // sprtopclip backup, for mid and fake textures
|
||||
|
||||
FWallTmapVals tmapvals;
|
||||
|
||||
int fake; // ident fake drawseg, don't draw and clip sprites backups
|
||||
int CurrentPortalUniq; // [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.
|
||||
|
||||
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; }
|
||||
|
||||
void SetHas3DFloorFrontSectorWalls() { b3DFloorBoundary |= 2; }
|
||||
void SetHas3DFloorBackSectorWalls() { b3DFloorBoundary |= 1; }
|
||||
void SetHas3DFloorMidTexture() { b3DFloorBoundary |= 4; }
|
||||
|
||||
private:
|
||||
uint8_t b3DFloorBoundary = 0; // 1=backsector, 2=frontsector, 4=midtexture
|
||||
};
|
||||
|
||||
struct DrawSegmentGroup
|
||||
|
@ -63,7 +73,6 @@ namespace swrenderer
|
|||
short *sprbottomclip;
|
||||
unsigned int BeginIndex;
|
||||
unsigned int EndIndex;
|
||||
bool GroupDrawn;
|
||||
};
|
||||
|
||||
class DrawSegmentList
|
||||
|
@ -76,14 +85,14 @@ namespace swrenderer
|
|||
unsigned int SegmentsCount() const { return Segments.Size() - StartIndices.Last(); }
|
||||
DrawSegment *Segment(unsigned int index) const { return Segments[Segments.Size() - 1 - index]; }
|
||||
|
||||
unsigned int InterestingSegmentsCount() const { return InterestingSegments.Size() - StartInterestingIndices.Last(); }
|
||||
DrawSegment *InterestingSegment(unsigned int index) const { return InterestingSegments[InterestingSegments.Size() - 1 - index]; }
|
||||
unsigned int TranslucentSegmentsCount() const { return TranslucentSegments.Size() - StartTranslucentIndices.Last(); }
|
||||
DrawSegment *TranslucentSegment(unsigned int index) const { return TranslucentSegments[TranslucentSegments.Size() - 1 - index]; }
|
||||
|
||||
void Clear();
|
||||
void PushPortal();
|
||||
void PopPortal();
|
||||
void Push(DrawSegment *segment);
|
||||
void PushInteresting(DrawSegment *segment);
|
||||
void PushTranslucent(DrawSegment *segment);
|
||||
|
||||
void BuildSegmentGroups();
|
||||
|
||||
|
@ -93,8 +102,8 @@ namespace swrenderer
|
|||
TArray<DrawSegment *> Segments;
|
||||
TArray<unsigned int> StartIndices;
|
||||
|
||||
TArray<DrawSegment *> InterestingSegments; // drawsegs that have something drawn on them
|
||||
TArray<unsigned int> StartInterestingIndices;
|
||||
TArray<DrawSegment *> TranslucentSegments; // drawsegs that have something drawn on them
|
||||
TArray<unsigned int> StartTranslucentIndices;
|
||||
|
||||
// For building segment groups
|
||||
short cliptop[MAXWIDTH];
|
||||
|
|
|
@ -275,12 +275,10 @@ namespace swrenderer
|
|||
// Draw any masked textures behind this particle so that when the
|
||||
// particle is drawn, it will be in front of them.
|
||||
DrawSegmentList *segmentlist = thread->DrawSegments.get();
|
||||
for (unsigned int index = 0; index != segmentlist->InterestingSegmentsCount(); index++)
|
||||
for (unsigned int index = 0; index != segmentlist->TranslucentSegmentsCount(); index++)
|
||||
{
|
||||
DrawSegment *ds = segmentlist->InterestingSegment(index);
|
||||
DrawSegment *ds = segmentlist->TranslucentSegment(index);
|
||||
|
||||
// kg3D - no fake segs
|
||||
if (ds->fake) continue;
|
||||
if (ds->x1 >= x2 || ds->x2 <= x1)
|
||||
{
|
||||
continue;
|
||||
|
|
|
@ -58,7 +58,6 @@ namespace swrenderer
|
|||
|
||||
int i;
|
||||
int x1, x2;
|
||||
int r1, r2;
|
||||
short topclip, botclip;
|
||||
short *clip1, *clip2;
|
||||
FSWColormap *colormap = spr->Light.BaseColormap;
|
||||
|
@ -85,10 +84,6 @@ namespace swrenderer
|
|||
if (x1 >= x2)
|
||||
return;
|
||||
|
||||
// Reject sprites outside the slice rendered by the thread
|
||||
if (x2 < thread->X1 || x1 > thread->X2)
|
||||
return;
|
||||
|
||||
// [RH] Sprites split behind a one-sided line can also be discarded.
|
||||
if (spr->sector == nullptr)
|
||||
return;
|
||||
|
@ -293,16 +288,48 @@ namespace swrenderer
|
|||
// The first drawseg that is closer than the sprite is the clip seg.
|
||||
|
||||
DrawSegmentList *segmentlist = thread->DrawSegments.get();
|
||||
RenderPortal *renderportal = thread->Portal.get();
|
||||
|
||||
// Render draw segments behind sprite
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int groupIndex = 0; groupIndex < segmentlist->SegmentGroups.Size(); groupIndex++)
|
||||
{
|
||||
auto &group = segmentlist->SegmentGroups[groupIndex];
|
||||
|
||||
if (group.x1 >= x2 || group.x2 <= x1 || group.neardepth > spr->depth)
|
||||
continue;
|
||||
|
||||
if (group.fardepth < spr->depth)
|
||||
{
|
||||
r1 = MAX<int>(group.x1, x1);
|
||||
r2 = MIN<int>(group.x2, x2);
|
||||
int r1 = MAX<int>(group.x1, x1);
|
||||
int r2 = MIN<int>(group.x2, x2);
|
||||
|
||||
// Clip bottom
|
||||
clip1 = clipbot + r1;
|
||||
|
@ -330,13 +357,10 @@ namespace swrenderer
|
|||
}
|
||||
else
|
||||
{
|
||||
//for (unsigned int index = segmentlist->BeginIndex(); index != segmentlist->EndIndex(); index++)
|
||||
for (unsigned int index = group.BeginIndex; index != group.EndIndex; index++)
|
||||
{
|
||||
DrawSegment *ds = segmentlist->Segment(index);
|
||||
|
||||
// kg3D - no clipping on fake segs
|
||||
if (ds->fake) continue;
|
||||
// determine if the drawseg obscures the sprite
|
||||
if (ds->x1 >= x2 || ds->x2 <= x1 ||
|
||||
(!(ds->silhouette & SIL_BOTH) && ds->maskedtexturecol == nullptr &&
|
||||
|
@ -346,41 +370,18 @@ namespace swrenderer
|
|||
continue;
|
||||
}
|
||||
|
||||
r1 = MAX<int>(ds->x1, x1);
|
||||
r2 = MIN<int>(ds->x2, x2);
|
||||
int r1 = MAX<int>(ds->x1, x1);
|
||||
int r2 = MIN<int>(ds->x2, x2);
|
||||
|
||||
float neardepth, fardepth;
|
||||
if (!spr->IsWallSprite())
|
||||
{
|
||||
if (ds->sz1 < ds->sz2)
|
||||
{
|
||||
neardepth = ds->sz1, fardepth = ds->sz2;
|
||||
}
|
||||
else
|
||||
{
|
||||
neardepth = ds->sz2, fardepth = ds->sz1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// GCC complained about this case, is there something missing here?
|
||||
fardepth = neardepth = 0;
|
||||
}
|
||||
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))
|
||||
{
|
||||
RenderPortal *renderportal = thread->Portal.get();
|
||||
|
||||
// seg is behind sprite, so draw the mid texture if it has one
|
||||
if (ds->CurrentPortalUniq == renderportal->CurrentPortalUniq && (ds->maskedtexturecol != nullptr || ds->bFogBoundary))
|
||||
{
|
||||
RenderDrawSegment renderer(thread);
|
||||
renderer.Render(ds, r1, r2);
|
||||
}
|
||||
|
||||
// seg is behind sprite
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ namespace swrenderer
|
|||
Sprites.Clear();
|
||||
StartIndices.Clear();
|
||||
SortedSprites.Clear();
|
||||
DrewAVoxel = false;
|
||||
}
|
||||
|
||||
void VisibleSpriteList::PushPortal()
|
||||
|
@ -55,17 +54,13 @@ namespace swrenderer
|
|||
StartIndices.Pop();
|
||||
}
|
||||
|
||||
void VisibleSpriteList::Push(VisibleSprite *sprite, bool isVoxel)
|
||||
void VisibleSpriteList::Push(VisibleSprite *sprite)
|
||||
{
|
||||
Sprites.Push(sprite);
|
||||
if (isVoxel)
|
||||
DrewAVoxel = true;
|
||||
}
|
||||
|
||||
void VisibleSpriteList::Sort()
|
||||
{
|
||||
bool compare2d = DrewAVoxel;
|
||||
|
||||
unsigned int first = StartIndices.Size() == 0 ? 0 : StartIndices.Last();
|
||||
unsigned int count = Sprites.Size() - first;
|
||||
|
||||
|
@ -88,25 +83,9 @@ namespace swrenderer
|
|||
SortedSprites[i] = Sprites[first + count - i - 1];
|
||||
}
|
||||
|
||||
if (compare2d)
|
||||
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](VisibleSprite *a, VisibleSprite *b) -> bool
|
||||
{
|
||||
// This is an alternate version, for when one or more voxel is in view.
|
||||
// It does a 2D distance test based on whichever one is furthest from
|
||||
// the viewpoint.
|
||||
|
||||
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](VisibleSprite *a, VisibleSprite *b) -> bool
|
||||
{
|
||||
return a->SortDist2D() < b->SortDist2D();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the standard version, which does a simple test based on depth.
|
||||
|
||||
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](VisibleSprite *a, VisibleSprite *b) -> bool
|
||||
{
|
||||
return a->SortDist() > b->SortDist();
|
||||
});
|
||||
}
|
||||
return a->SortDist() > b->SortDist();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace swrenderer
|
|||
void Clear();
|
||||
void PushPortal();
|
||||
void PopPortal();
|
||||
void Push(VisibleSprite *sprite, bool isVoxel = false);
|
||||
void Push(VisibleSprite *sprite);
|
||||
void Sort();
|
||||
|
||||
TArray<VisibleSprite *> SortedSprites;
|
||||
|
@ -19,6 +19,5 @@ namespace swrenderer
|
|||
private:
|
||||
TArray<VisibleSprite *> Sprites;
|
||||
TArray<unsigned int> StartIndices;
|
||||
bool DrewAVoxel = false;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace swrenderer
|
|||
vis->yscale = (float)yscale;
|
||||
vis->x1 = renderportal->WindowLeft;
|
||||
vis->x2 = renderportal->WindowRight;
|
||||
vis->idepth = 1 / MINZ;
|
||||
vis->idepth = float(1 / tz);
|
||||
vis->floorclip = thing->Floorclip;
|
||||
|
||||
pos.Z -= thing->Floorclip;
|
||||
|
@ -189,7 +189,19 @@ namespace swrenderer
|
|||
|
||||
vis->Light.SetColormap(thread->Light->SpriteGlobVis(foggy) / MAX(tz, MINZ), spriteshade, basecolormap, fullbright, invertcolormap, fadeToBlack);
|
||||
|
||||
thread->SpriteList->Push(vis, true);
|
||||
// Fake a voxel drawing to find its extents..
|
||||
SpriteDrawerArgs drawerargs;
|
||||
drawerargs.SetLight(vis->Light.BaseColormap, 0, vis->Light.ColormapNum << FRACBITS);
|
||||
basecolormap = (FDynamicColormap*)vis->Light.BaseColormap;
|
||||
bool visible = drawerargs.SetStyle(thread->Viewport.get(), vis->RenderStyle, vis->Alpha, vis->Translation, vis->FillColor, basecolormap);
|
||||
if (!visible)
|
||||
return;
|
||||
int flags = vis->bInMirror ? (DVF_MIRRORED | DVF_FIND_X1X2) : DVF_FIND_X1X2;
|
||||
vis->DrawVoxel(thread, drawerargs, vis->pa.vpos, vis->pa.vang, vis->gpos, vis->Angle, vis->xscale, FLOAT2FIXED(vis->yscale), vis->voxel, nullptr, nullptr, 0, 0, flags);
|
||||
if (vis->x1 >= vis->x2)
|
||||
return;
|
||||
|
||||
thread->SpriteList->Push(vis);
|
||||
}
|
||||
|
||||
void RenderVoxel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ)
|
||||
|
@ -379,8 +391,13 @@ namespace swrenderer
|
|||
|
||||
bool useSlabDataBgra = !drawerargs.DrawerNeedsPalInput() && viewport->RenderTarget->IsBgra();
|
||||
|
||||
int coverageX1 = this->x2;
|
||||
int coverageX2 = this->x1;
|
||||
|
||||
const int maxoutblocks = 100;
|
||||
VoxelBlock *outblocks = thread->FrameMemory->AllocMemory<VoxelBlock>(maxoutblocks);
|
||||
VoxelBlock *outblocks = nullptr;
|
||||
if ((flags & DVF_FIND_X1X2) == 0)
|
||||
outblocks = thread->FrameMemory->AllocMemory<VoxelBlock>(maxoutblocks);
|
||||
int nextoutblock = 0;
|
||||
|
||||
for (cnt = 0; cnt < 8; cnt++)
|
||||
|
@ -457,10 +474,7 @@ namespace swrenderer
|
|||
if (voxptr >= voxend) continue;
|
||||
|
||||
lx = xs_RoundToInt(nx * centerxwide_f / (ny + y1)) + viewport->viewwindow.centerx;
|
||||
if (lx < 0) lx = 0;
|
||||
rx = xs_RoundToInt((nx + nxoff) * centerxwide_f / (ny + y2)) + viewport->viewwindow.centerx;
|
||||
if (rx > viewwidth) rx = viewwidth;
|
||||
if (rx <= lx) continue;
|
||||
|
||||
if (flags & DVF_MIRRORED)
|
||||
{
|
||||
|
@ -469,6 +483,17 @@ namespace swrenderer
|
|||
rx = t;
|
||||
}
|
||||
|
||||
if (lx < this->x1) lx = this->x1;
|
||||
if (rx > this->x2) rx = this->x2;
|
||||
if (rx <= lx) continue;
|
||||
|
||||
if (flags & DVF_FIND_X1X2)
|
||||
{
|
||||
coverageX1 = MIN(coverageX1, lx);
|
||||
coverageX2 = MAX(coverageX2, rx);
|
||||
continue;
|
||||
}
|
||||
|
||||
fixed_t l1 = xs_RoundToInt(centerxwidebig_f / (ny - yoff));
|
||||
fixed_t l2 = xs_RoundToInt(centerxwidebig_f / (ny + yoff));
|
||||
for (; voxptr < voxend; voxptr = (kvxslab_t *)((uint8_t *)voxptr + voxptr->zleng + 3))
|
||||
|
@ -594,7 +619,7 @@ namespace swrenderer
|
|||
|
||||
if (nextoutblock == maxoutblocks)
|
||||
{
|
||||
drawerargs.DrawVoxelBlocks(thread, outblocks, nextoutblock);
|
||||
drawerargs.DrawVoxelBlocks(thread, outblocks, maxoutblocks);
|
||||
outblocks = thread->FrameMemory->AllocMemory<VoxelBlock>(maxoutblocks);
|
||||
nextoutblock = 0;
|
||||
}
|
||||
|
@ -645,9 +670,17 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
if (nextoutblock != 0)
|
||||
if (flags & DVF_FIND_X1X2)
|
||||
{
|
||||
drawerargs.DrawVoxelBlocks(thread, outblocks, nextoutblock);
|
||||
this->x1 = coverageX1;
|
||||
this->x2 = coverageX2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nextoutblock != 0)
|
||||
{
|
||||
drawerargs.DrawVoxelBlocks(thread, outblocks, nextoutblock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,12 @@ namespace swrenderer
|
|||
FAngle vang = { 0.0f }; // view angle
|
||||
};
|
||||
|
||||
struct VoxelBlockEntry
|
||||
{
|
||||
VoxelBlock *block;
|
||||
VoxelBlockEntry *next;
|
||||
};
|
||||
|
||||
posang pa;
|
||||
DAngle Angle = { 0.0 };
|
||||
fixed_t xscale = 0;
|
||||
|
@ -82,7 +88,7 @@ namespace swrenderer
|
|||
uint32_t Translation = 0;
|
||||
uint32_t FillColor = 0;
|
||||
|
||||
enum { DVF_OFFSCREEN = 1, DVF_SPANSONLY = 2, DVF_MIRRORED = 4 };
|
||||
enum { DVF_OFFSCREEN = 1, DVF_SPANSONLY = 2, DVF_MIRRORED = 4, DVF_FIND_X1X2 = 8 };
|
||||
|
||||
static kvxslab_t *GetSlabStart(const FVoxelMipLevel &mip, int x, int y);
|
||||
static kvxslab_t *GetSlabEnd(const FVoxelMipLevel &mip, int x, int y);
|
||||
|
|
Loading…
Reference in a new issue