diff --git a/src/swrenderer/things/r_visiblespritelist.cpp b/src/swrenderer/things/r_visiblespritelist.cpp index 7161507dd..ef91e6bed 100644 --- a/src/swrenderer/things/r_visiblespritelist.cpp +++ b/src/swrenderer/things/r_visiblespritelist.cpp @@ -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(); + }); } } diff --git a/src/swrenderer/things/r_visiblespritelist.h b/src/swrenderer/things/r_visiblespritelist.h index 30d27cc67..52ee1772c 100644 --- a/src/swrenderer/things/r_visiblespritelist.h +++ b/src/swrenderer/things/r_visiblespritelist.h @@ -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 SortedSprites; @@ -19,6 +19,5 @@ namespace swrenderer private: TArray Sprites; TArray StartIndices; - bool DrewAVoxel = false; }; } diff --git a/src/swrenderer/things/r_voxel.cpp b/src/swrenderer/things/r_voxel.cpp index a11846abe..f32452399 100644 --- a/src/swrenderer/things/r_voxel.cpp +++ b/src/swrenderer/things/r_voxel.cpp @@ -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(maxoutblocks); + VoxelBlock *outblocks = nullptr; + if ((flags & DVF_FIND_X1X2) == 0) + outblocks = thread->FrameMemory->AllocMemory(maxoutblocks); int nextoutblock = 0; for (cnt = 0; cnt < 8; cnt++) @@ -470,6 +487,13 @@ namespace swrenderer 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)) @@ -595,7 +619,7 @@ namespace swrenderer if (nextoutblock == maxoutblocks) { - drawerargs.DrawVoxelBlocks(thread, outblocks, nextoutblock); + drawerargs.DrawVoxelBlocks(thread, outblocks, maxoutblocks); outblocks = thread->FrameMemory->AllocMemory(maxoutblocks); nextoutblock = 0; } @@ -646,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); + } } } diff --git a/src/swrenderer/things/r_voxel.h b/src/swrenderer/things/r_voxel.h index a97ee5196..bef22d480 100644 --- a/src/swrenderer/things/r_voxel.h +++ b/src/swrenderer/things/r_voxel.h @@ -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);