mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-27 06:12:19 +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;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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--)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue