- Fix sprites behind midtextures unrender when near voxel

This commit is contained in:
Magnus Norddahl 2017-07-02 20:09:46 +02:00
parent 6d8281c812
commit 205350e726
4 changed files with 50 additions and 34 deletions

View file

@ -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)
{
// 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();
});
}
}
}

View file

@ -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;
};
}

View file

@ -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++)
@ -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<VoxelBlock>(maxoutblocks);
nextoutblock = 0;
}
@ -646,11 +670,19 @@ namespace swrenderer
}
}
if (flags & DVF_FIND_X1X2)
{
this->x1 = coverageX1;
this->x2 = coverageX2;
}
else
{
if (nextoutblock != 0)
{
drawerargs.DrawVoxelBlocks(thread, outblocks, nextoutblock);
}
}
}
kvxslab_t *RenderVoxel::GetSlabStart(const FVoxelMipLevel &mip, int x, int y)
{

View file

@ -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);