This commit is contained in:
Rachael Alexanderson 2017-07-02 16:36:46 -04:00
commit 6a402c28d8
15 changed files with 194 additions and 200 deletions

View file

@ -319,16 +319,22 @@ namespace swrenderer
side_t *sidedef = mLineSegment->sidedef; side_t *sidedef = mLineSegment->sidedef;
RenderPortal *renderportal = Thread->Portal.get(); RenderPortal *renderportal = Thread->Portal.get();
Clip3DFloors *clip3d = Thread->Clip3D.get();
DrawSegment *draw_segment = Thread->FrameMemory->NewObject<DrawSegment>(); 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->CurrentPortalUniq = renderportal->CurrentPortalUniq;
draw_segment->sx1 = WallC.sx1; draw_segment->sx1 = WallC.sx1;
draw_segment->sx2 = WallC.sx2; draw_segment->sx2 = WallC.sx2;
draw_segment->sz1 = WallC.sz1; draw_segment->sz1 = WallC.sz1;
draw_segment->sz2 = WallC.sz2; 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->cy = WallC.tleft.Y;
draw_segment->cdx = WallC.tright.X - WallC.tleft.X; draw_segment->cdx = WallC.tright.X - WallC.tleft.X;
draw_segment->cdy = WallC.tright.Y - WallC.tleft.Y; draw_segment->cdy = WallC.tright.Y - WallC.tleft.Y;
@ -338,20 +344,8 @@ namespace swrenderer
draw_segment->x1 = start; draw_segment->x1 = start;
draw_segment->x2 = stop; draw_segment->x2 = stop;
draw_segment->curline = mLineSegment; draw_segment->curline = mLineSegment;
draw_segment->bFogBoundary = false;
draw_segment->bFakeBoundary = false;
draw_segment->foggy = foggy; 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(); bool markportal = ShouldMarkPortal();
if (markportal) if (markportal)
@ -369,8 +363,6 @@ namespace swrenderer
else else
{ {
// two sided line // two sided line
draw_segment->silhouette = 0;
if (mFrontFloorZ1 > mBackFloorZ1 || mFrontFloorZ2 > mBackFloorZ2 || if (mFrontFloorZ1 > mBackFloorZ1 || mFrontFloorZ2 > mBackFloorZ2 ||
mBackSector->floorplane.PointOnSide(Thread->Viewport->viewpoint.Pos) < 0) 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()) { if (!onlyUpdatePlaneClip && r_3dfloors)
for (i = 0; i < (int)mBackSector->e->XFloor.ffloors.Size(); i++) { {
F3DFloor *rover = mBackSector->e->XFloor.ffloors[i]; if (mBackSector->e && mBackSector->e->XFloor.ffloors.Size()) {
if (rover->flags & FF_RENDERSIDES && (!(rover->flags & FF_INVERTSIDES) || rover->flags & FF_ALLSIDES)) { for (i = 0; i < (int)mBackSector->e->XFloor.ffloors.Size(); i++) {
draw_segment->bFakeBoundary |= 1; F3DFloor *rover = mBackSector->e->XFloor.ffloors[i];
break; 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++) { if (!onlyUpdatePlaneClip)
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)
// allocate space for masked texture tables, if needed // allocate space for masked texture tables, if needed
// [RH] Don't just allocate the space; fill it in too. // [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()) && (mCeilingClipped != ProjectedWallCull::OutsideBelow || !sidedef->GetTexture(side_t::top).isValid()) &&
(mFloorClipped != ProjectedWallCull::OutsideAbove || !sidedef->GetTexture(side_t::bottom).isValid()) && (mFloorClipped != ProjectedWallCull::OutsideAbove || !sidedef->GetTexture(side_t::bottom).isValid()) &&
(WallC.sz1 >= TOO_CLOSE_Z && WallC.sz2 >= TOO_CLOSE_Z)) (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)); memcpy(draw_segment->bkup, &Thread->OpaquePass->ceilingclip[start], sizeof(short)*(stop - start));
draw_segment->bFogBoundary = IsFogBoundary(mFrontSector, mBackSector); 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()) 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->maskedtexturecol = Thread->FrameMemory->AllocMemory<fixed_t>(stop - start);
draw_segment->swall = Thread->FrameMemory->AllocMemory<float>(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) if (draw_segment->bFogBoundary || draw_segment->maskedtexturecol != nullptr)
{ {
Thread->DrawSegments->PushInteresting(draw_segment); Thread->DrawSegments->PushTranslucent(draw_segment);
} }
} }
} }

View file

@ -79,7 +79,7 @@ namespace swrenderer
FDynamicColormap *patchstylecolormap = nullptr; FDynamicColormap *patchstylecolormap = nullptr;
bool visible = columndrawerargs.SetStyle(viewport, LegacyRenderStyles[additive ? STYLE_Add : STYLE_Translucent], alpha, 0, 0, patchstylecolormap); 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; return;
} }
@ -139,7 +139,7 @@ namespace swrenderer
if (ds->maskedtexturecol == nullptr) if (ds->maskedtexturecol == nullptr)
renderwall = false; renderwall = false;
} }
else if ((ds->bFakeBoundary && !(ds->bFakeBoundary & 4)) || !visible) else if ((ds->Has3DFloorWalls() && !ds->Has3DFloorMidTexture()) || !visible)
{ {
renderwall = false; renderwall = false;
} }
@ -147,7 +147,7 @@ namespace swrenderer
if (renderwall) if (renderwall)
notrelevant = RenderWall(ds, x1, x2, walldrawerargs, columndrawerargs, visible, basecolormap, wallshade, wrap); 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); RenderFakeWallRange(ds, x1, x2, wallshade);
} }
@ -540,7 +540,7 @@ namespace swrenderer
{ {
return; return;
} }
if ((ds->bFakeBoundary & 3) == 2) if (ds->Has3DFloorFrontSectorWalls() && !ds->Has3DFloorBackSectorWalls())
{ {
sector_t *sec = backsector; sector_t *sec = backsector;
backsector = frontsector; backsector = frontsector;
@ -709,7 +709,7 @@ namespace swrenderer
CameraLight *cameraLight = CameraLight::Instance(); CameraLight *cameraLight = CameraLight::Instance();
if (cameraLight->FixedLightLevel() < 0) 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--) for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
{ {
@ -888,7 +888,7 @@ namespace swrenderer
CameraLight *cameraLight = CameraLight::Instance(); CameraLight *cameraLight = CameraLight::Instance();
if (cameraLight->FixedLightLevel() < 0) 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--) for (j = backsector->e->XFloor.lightlist.Size() - 1; j >= 0; j--)
{ {

View file

@ -103,23 +103,28 @@ namespace swrenderer
// calls to GetPixels for this to work. // calls to GetPixels for this to work.
static std::mutex loadmutex; 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(); texture->GetPixelsBgra();
const FTexture::Span *spans; texture->GetColumnBgra(0, &spans);
texture->GetColumn(0, &spans);
if (Viewport->RenderTarget->IsBgra())
{
texture->GetPixelsBgra();
texture->GetColumnBgra(0, &spans);
}
loadmutex.unlock();
} }
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(); sub->BuildPolyBSP();
throw;
} }
} }
} }

View file

@ -83,6 +83,9 @@ namespace swrenderer
// Make sure texture can accessed safely // Make sure texture can accessed safely
void PrepareTexture(FTexture *texture); void PrepareTexture(FTexture *texture);
// Setup poly object in a threadsafe manner
void PreparePolyObject(subsector_t *sub);
private: private:
std::unique_ptr<SWTruecolorDrawers> tc_drawers; std::unique_ptr<SWTruecolorDrawers> tc_drawers;

View file

@ -404,10 +404,8 @@ namespace swrenderer
void RenderOpaquePass::AddPolyobjs(subsector_t *sub) void RenderOpaquePass::AddPolyobjs(subsector_t *sub)
{ {
if (sub->BSP == nullptr || sub->BSP->bDirty) Thread->PreparePolyObject(sub);
{
sub->BuildPolyBSP();
}
if (sub->BSP->Nodes.Size() == 0) if (sub->BSP->Nodes.Size() == 0)
{ {
RenderSubsector(&sub->BSP->Subsectors[0]); RenderSubsector(&sub->BSP->Subsectors[0]);

View file

@ -217,7 +217,6 @@ namespace swrenderer
draw_segment->swall = nullptr; draw_segment->swall = nullptr;
draw_segment->bFogBoundary = false; draw_segment->bFogBoundary = false;
draw_segment->curline = nullptr; draw_segment->curline = nullptr;
draw_segment->fake = 0;
draw_segment->foggy = false; draw_segment->foggy = false;
memcpy(draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left) * sizeof(short)); 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)); memcpy(draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left) * sizeof(short));
@ -528,8 +527,8 @@ namespace swrenderer
void RenderPortal::SetMainPortal() void RenderPortal::SetMainPortal()
{ {
WindowLeft = 0; WindowLeft = Thread->X1;
WindowRight = viewwidth; WindowRight = Thread->X2;
MirrorFlags = 0; MirrorFlags = 0;
CurrentPortal = nullptr; CurrentPortal = nullptr;
CurrentPortalUniq = 0; CurrentPortalUniq = 0;

View file

@ -136,37 +136,11 @@ namespace swrenderer
RenderPortal *renderportal = Thread->Portal.get(); RenderPortal *renderportal = Thread->Portal.get();
DrawSegmentList *drawseglist = Thread->DrawSegments.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; auto &sortedSprites = Thread->SpriteList->SortedSprites;
for (int i = sortedSprites.Size(); i > 0; i--) for (int i = sortedSprites.Size(); i > 0; i--)
{ {
VisibleSprite *sprite = sortedSprites[i - 1]; 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)) if (sprite->IsCurrentPortalUniq(renderportal->CurrentPortalUniq))
{ {
sprite->Render(Thread); sprite->Render(Thread);
@ -187,8 +161,6 @@ namespace swrenderer
// [ZZ] the same as above // [ZZ] the same as above
if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq) if (ds->CurrentPortalUniq != renderportal->CurrentPortalUniq)
continue; continue;
// kg3D - no fake segs
if (ds->fake) continue;
if (ds->maskedtexturecol != nullptr || ds->bFogBoundary) if (ds->maskedtexturecol != nullptr || ds->bFogBoundary)
{ {
RenderDrawSegment renderer(Thread); RenderDrawSegment renderer(Thread);

View file

@ -63,15 +63,15 @@ namespace swrenderer
StartIndices.Clear(); StartIndices.Clear();
StartIndices.Push(0); StartIndices.Push(0);
InterestingSegments.Clear(); TranslucentSegments.Clear();
StartInterestingIndices.Clear(); StartTranslucentIndices.Clear();
StartInterestingIndices.Push(0); StartTranslucentIndices.Push(0);
} }
void DrawSegmentList::PushPortal() void DrawSegmentList::PushPortal()
{ {
StartIndices.Push(Segments.Size()); StartIndices.Push(Segments.Size());
StartInterestingIndices.Push(InterestingSegments.Size()); StartTranslucentIndices.Push(TranslucentSegments.Size());
} }
void DrawSegmentList::PopPortal() void DrawSegmentList::PopPortal()
@ -79,8 +79,8 @@ namespace swrenderer
Segments.Resize(StartIndices.Last()); Segments.Resize(StartIndices.Last());
StartIndices.Pop(); StartIndices.Pop();
InterestingSegments.Resize(StartInterestingIndices.Last()); TranslucentSegments.Resize(StartTranslucentIndices.Last());
StartInterestingIndices.Pop(); StartTranslucentIndices.Pop();
} }
void DrawSegmentList::Push(DrawSegment *segment) void DrawSegmentList::Push(DrawSegment *segment)
@ -88,9 +88,9 @@ namespace swrenderer
Segments.Push(segment); Segments.Push(segment);
} }
void DrawSegmentList::PushInteresting(DrawSegment *segment) void DrawSegmentList::PushTranslucent(DrawSegment *segment)
{ {
InterestingSegments.Push(segment); TranslucentSegments.Push(segment);
} }
void DrawSegmentList::BuildSegmentGroups() void DrawSegmentList::BuildSegmentGroups()
@ -131,9 +131,6 @@ namespace swrenderer
{ {
ds = Segment(groupIndex); ds = Segment(groupIndex);
// kg3D - no clipping on fake segs
if (ds->fake) continue;
if (ds->silhouette & SIL_BOTTOM) if (ds->silhouette & SIL_BOTTOM)
{ {
short *clip1 = clipbottom + ds->x1; short *clip1 = clipbottom + ds->x1;

View file

@ -36,23 +36,33 @@ namespace swrenderer
float siz1, siz2; // 1/z for left, right of parent seg on screen float siz1, siz2; // 1/z for left, right of parent seg on screen
float cx, cy, cdx, cdy; float cx, cy, cdx, cdy;
float yscale; float yscale;
uint8_t silhouette; // 0=none, 1=bottom, 2=top, 3=both uint8_t silhouette = 0; // 0=none, 1=bottom, 2=top, 3=both
uint8_t bFogBoundary; bool bFogBoundary = false;
uint8_t bFakeBoundary; // for fake walls int shade = 0;
int shade; bool foggy = false;
bool foggy;
// Pointers to lists for sprite clipping, all three adjusted so [x1] is first value. // Pointers to lists for sprite clipping, all three adjusted so [x1] is first value.
short *sprtopclip; short *sprtopclip = nullptr;
short *sprbottomclip; short *sprbottomclip = nullptr;
fixed_t *maskedtexturecol; fixed_t *maskedtexturecol = nullptr;
float *swall; float *swall = nullptr;
short *bkup; // sprtopclip backup, for mid and fake textures short *bkup = nullptr; // sprtopclip backup, for mid and fake textures
FWallTmapVals tmapvals; FWallTmapVals tmapvals;
int fake; // ident fake drawseg, don't draw and clip sprites backups int CurrentPortalUniq = 0; // [ZZ] to identify the portal that this drawseg is in. used for sprite clipping.
int CurrentPortalUniq; // [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 struct DrawSegmentGroup
@ -63,7 +73,6 @@ namespace swrenderer
short *sprbottomclip; short *sprbottomclip;
unsigned int BeginIndex; unsigned int BeginIndex;
unsigned int EndIndex; unsigned int EndIndex;
bool GroupDrawn;
}; };
class DrawSegmentList class DrawSegmentList
@ -76,14 +85,14 @@ namespace swrenderer
unsigned int SegmentsCount() const { return Segments.Size() - StartIndices.Last(); } unsigned int SegmentsCount() const { return Segments.Size() - StartIndices.Last(); }
DrawSegment *Segment(unsigned int index) const { return Segments[Segments.Size() - 1 - index]; } DrawSegment *Segment(unsigned int index) const { return Segments[Segments.Size() - 1 - index]; }
unsigned int InterestingSegmentsCount() const { return InterestingSegments.Size() - StartInterestingIndices.Last(); } unsigned int TranslucentSegmentsCount() const { return TranslucentSegments.Size() - StartTranslucentIndices.Last(); }
DrawSegment *InterestingSegment(unsigned int index) const { return InterestingSegments[InterestingSegments.Size() - 1 - index]; } DrawSegment *TranslucentSegment(unsigned int index) const { return TranslucentSegments[TranslucentSegments.Size() - 1 - index]; }
void Clear(); void Clear();
void PushPortal(); void PushPortal();
void PopPortal(); void PopPortal();
void Push(DrawSegment *segment); void Push(DrawSegment *segment);
void PushInteresting(DrawSegment *segment); void PushTranslucent(DrawSegment *segment);
void BuildSegmentGroups(); void BuildSegmentGroups();
@ -93,8 +102,8 @@ namespace swrenderer
TArray<DrawSegment *> Segments; TArray<DrawSegment *> Segments;
TArray<unsigned int> StartIndices; TArray<unsigned int> StartIndices;
TArray<DrawSegment *> InterestingSegments; // drawsegs that have something drawn on them TArray<DrawSegment *> TranslucentSegments; // drawsegs that have something drawn on them
TArray<unsigned int> StartInterestingIndices; TArray<unsigned int> StartTranslucentIndices;
// For building segment groups // For building segment groups
short cliptop[MAXWIDTH]; short cliptop[MAXWIDTH];

View file

@ -275,12 +275,10 @@ namespace swrenderer
// Draw any masked textures behind this particle so that when the // Draw any masked textures behind this particle so that when the
// particle is drawn, it will be in front of them. // particle is drawn, it will be in front of them.
DrawSegmentList *segmentlist = thread->DrawSegments.get(); 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) if (ds->x1 >= x2 || ds->x2 <= x1)
{ {
continue; continue;

View file

@ -58,7 +58,6 @@ namespace swrenderer
int i; int i;
int x1, x2; int x1, x2;
int r1, r2;
short topclip, botclip; short topclip, botclip;
short *clip1, *clip2; short *clip1, *clip2;
FSWColormap *colormap = spr->Light.BaseColormap; FSWColormap *colormap = spr->Light.BaseColormap;
@ -85,10 +84,6 @@ namespace swrenderer
if (x1 >= x2) if (x1 >= x2)
return; 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. // [RH] Sprites split behind a one-sided line can also be discarded.
if (spr->sector == nullptr) if (spr->sector == nullptr)
return; return;
@ -293,16 +288,48 @@ namespace swrenderer
// The first drawseg that is closer than the sprite is the clip seg. // The first drawseg that is closer than the sprite is the clip seg.
DrawSegmentList *segmentlist = thread->DrawSegments.get(); 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++) for (unsigned int groupIndex = 0; groupIndex < segmentlist->SegmentGroups.Size(); groupIndex++)
{ {
auto &group = segmentlist->SegmentGroups[groupIndex]; auto &group = segmentlist->SegmentGroups[groupIndex];
if (group.x1 >= x2 || group.x2 <= x1 || group.neardepth > spr->depth) if (group.x1 >= x2 || group.x2 <= x1 || group.neardepth > spr->depth)
continue; continue;
if (group.fardepth < spr->depth) if (group.fardepth < spr->depth)
{ {
r1 = MAX<int>(group.x1, x1); int r1 = MAX<int>(group.x1, x1);
r2 = MIN<int>(group.x2, x2); int r2 = MIN<int>(group.x2, x2);
// Clip bottom // Clip bottom
clip1 = clipbot + r1; clip1 = clipbot + r1;
@ -330,13 +357,10 @@ namespace swrenderer
} }
else else
{ {
//for (unsigned int index = segmentlist->BeginIndex(); index != segmentlist->EndIndex(); index++)
for (unsigned int index = group.BeginIndex; index != group.EndIndex; index++) for (unsigned int index = group.BeginIndex; index != group.EndIndex; index++)
{ {
DrawSegment *ds = segmentlist->Segment(index); DrawSegment *ds = segmentlist->Segment(index);
// kg3D - no clipping on fake segs
if (ds->fake) continue;
// determine if the drawseg obscures the sprite // determine if the drawseg obscures the sprite
if (ds->x1 >= x2 || ds->x2 <= x1 || if (ds->x1 >= x2 || ds->x2 <= x1 ||
(!(ds->silhouette & SIL_BOTH) && ds->maskedtexturecol == nullptr && (!(ds->silhouette & SIL_BOTH) && ds->maskedtexturecol == nullptr &&
@ -346,41 +370,18 @@ namespace swrenderer
continue; continue;
} }
r1 = MAX<int>(ds->x1, x1); int r1 = MAX<int>(ds->x1, x1);
r2 = MIN<int>(ds->x2, x2); int r2 = MIN<int>(ds->x2, x2);
float neardepth, fardepth; float neardepth = MIN(ds->sz1, ds->sz2);
if (!spr->IsWallSprite()) float fardepth = MAX(ds->sz1, ds->sz2);
{
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;
}
// Check if sprite is in front of draw seg: // Check if sprite is in front of draw seg:
if ((!spr->IsWallSprite() && neardepth > spr->depth) || ((spr->IsWallSprite() || fardepth > spr->depth) && 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.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)) (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
// 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);
}
continue; continue;
} }

View file

@ -41,7 +41,6 @@ namespace swrenderer
Sprites.Clear(); Sprites.Clear();
StartIndices.Clear(); StartIndices.Clear();
SortedSprites.Clear(); SortedSprites.Clear();
DrewAVoxel = false;
} }
void VisibleSpriteList::PushPortal() void VisibleSpriteList::PushPortal()
@ -55,17 +54,13 @@ namespace swrenderer
StartIndices.Pop(); StartIndices.Pop();
} }
void VisibleSpriteList::Push(VisibleSprite *sprite, bool isVoxel) void VisibleSpriteList::Push(VisibleSprite *sprite)
{ {
Sprites.Push(sprite); Sprites.Push(sprite);
if (isVoxel)
DrewAVoxel = true;
} }
void VisibleSpriteList::Sort() void VisibleSpriteList::Sort()
{ {
bool compare2d = DrewAVoxel;
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;
@ -88,25 +83,9 @@ namespace swrenderer
SortedSprites[i] = Sprites[first + count - i - 1]; 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. return a->SortDist() > b->SortDist();
// 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();
});
}
} }
} }

View file

@ -11,7 +11,7 @@ namespace swrenderer
void Clear(); void Clear();
void PushPortal(); void PushPortal();
void PopPortal(); void PopPortal();
void Push(VisibleSprite *sprite, bool isVoxel = false); void Push(VisibleSprite *sprite);
void Sort(); void Sort();
TArray<VisibleSprite *> SortedSprites; TArray<VisibleSprite *> SortedSprites;
@ -19,6 +19,5 @@ namespace swrenderer
private: private:
TArray<VisibleSprite *> Sprites; TArray<VisibleSprite *> Sprites;
TArray<unsigned int> StartIndices; TArray<unsigned int> StartIndices;
bool DrewAVoxel = false;
}; };
} }

View file

@ -124,7 +124,7 @@ namespace swrenderer
vis->yscale = (float)yscale; vis->yscale = (float)yscale;
vis->x1 = renderportal->WindowLeft; vis->x1 = renderportal->WindowLeft;
vis->x2 = renderportal->WindowRight; vis->x2 = renderportal->WindowRight;
vis->idepth = 1 / MINZ; vis->idepth = float(1 / tz);
vis->floorclip = thing->Floorclip; vis->floorclip = thing->Floorclip;
pos.Z -= 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); 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) 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(); bool useSlabDataBgra = !drawerargs.DrawerNeedsPalInput() && viewport->RenderTarget->IsBgra();
int coverageX1 = this->x2;
int coverageX2 = this->x1;
const int maxoutblocks = 100; 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; int nextoutblock = 0;
for (cnt = 0; cnt < 8; cnt++) for (cnt = 0; cnt < 8; cnt++)
@ -457,10 +474,7 @@ namespace swrenderer
if (voxptr >= voxend) continue; if (voxptr >= voxend) continue;
lx = xs_RoundToInt(nx * centerxwide_f / (ny + y1)) + viewport->viewwindow.centerx; 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; 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) if (flags & DVF_MIRRORED)
{ {
@ -469,6 +483,17 @@ namespace swrenderer
rx = t; 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 l1 = xs_RoundToInt(centerxwidebig_f / (ny - yoff));
fixed_t l2 = 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)) for (; voxptr < voxend; voxptr = (kvxslab_t *)((uint8_t *)voxptr + voxptr->zleng + 3))
@ -594,7 +619,7 @@ namespace swrenderer
if (nextoutblock == maxoutblocks) if (nextoutblock == maxoutblocks)
{ {
drawerargs.DrawVoxelBlocks(thread, outblocks, nextoutblock); drawerargs.DrawVoxelBlocks(thread, outblocks, maxoutblocks);
outblocks = thread->FrameMemory->AllocMemory<VoxelBlock>(maxoutblocks); outblocks = thread->FrameMemory->AllocMemory<VoxelBlock>(maxoutblocks);
nextoutblock = 0; 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);
}
} }
} }

View file

@ -73,6 +73,12 @@ namespace swrenderer
FAngle vang = { 0.0f }; // view angle FAngle vang = { 0.0f }; // view angle
}; };
struct VoxelBlockEntry
{
VoxelBlock *block;
VoxelBlockEntry *next;
};
posang pa; posang pa;
DAngle Angle = { 0.0 }; DAngle Angle = { 0.0 };
fixed_t xscale = 0; fixed_t xscale = 0;
@ -82,7 +88,7 @@ namespace swrenderer
uint32_t Translation = 0; uint32_t Translation = 0;
uint32_t FillColor = 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 *GetSlabStart(const FVoxelMipLevel &mip, int x, int y);
static kvxslab_t *GetSlabEnd(const FVoxelMipLevel &mip, int x, int y); static kvxslab_t *GetSlabEnd(const FVoxelMipLevel &mip, int x, int y);