mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-01-18 14:41:40 +00:00
Moved DrawSprite to VisibleSprite and marked all its variables as protected
This commit is contained in:
parent
55131a7a6d
commit
433eb77c37
9 changed files with 428 additions and 410 deletions
|
@ -107,7 +107,7 @@ namespace swrenderer
|
|||
// (all checks that are already done in R_CollectPortals have been removed for performance reasons.)
|
||||
|
||||
// don't clip if the sprite is in front of the portal
|
||||
if (!P_PointOnLineSidePrecise(spr->gpos.X, spr->gpos.Y, seg->curline->linedef))
|
||||
if (!P_PointOnLineSidePrecise(spr->WorldPos().X, spr->WorldPos().Y, seg->curline->linedef))
|
||||
continue;
|
||||
|
||||
// now if current column is covered by this drawseg, we clip it away
|
||||
|
@ -118,405 +118,6 @@ namespace swrenderer
|
|||
return false;
|
||||
}
|
||||
|
||||
void RenderTranslucentPass::DrawSprite(VisibleSprite *spr)
|
||||
{
|
||||
static short clipbot[MAXWIDTH];
|
||||
static short cliptop[MAXWIDTH];
|
||||
drawseg_t *ds;
|
||||
int i;
|
||||
int x1, x2;
|
||||
int r1, r2;
|
||||
short topclip, botclip;
|
||||
short *clip1, *clip2;
|
||||
FSWColormap *colormap = spr->Style.BaseColormap;
|
||||
int colormapnum = spr->Style.ColormapNum;
|
||||
F3DFloor *rover;
|
||||
FDynamicColormap *mybasecolormap;
|
||||
|
||||
Clip3DFloors *clip3d = Clip3DFloors::Instance();
|
||||
|
||||
// [RH] Check for particles
|
||||
if (spr->IsParticle())
|
||||
{
|
||||
// kg3D - reject invisible parts
|
||||
if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && spr->gpos.Z <= clip3d->sclipBottom) return;
|
||||
if ((clip3d->fake3D & FAKE3D_CLIPTOP) && spr->gpos.Z >= clip3d->sclipTop) return;
|
||||
|
||||
spr->Render(nullptr, nullptr, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
x1 = spr->x1;
|
||||
x2 = spr->x2;
|
||||
|
||||
// [RH] Quickly reject sprites with bad x ranges.
|
||||
if (x1 >= x2)
|
||||
return;
|
||||
|
||||
// [RH] Sprites split behind a one-sided line can also be discarded.
|
||||
if (spr->sector == nullptr)
|
||||
return;
|
||||
|
||||
// kg3D - reject invisible parts
|
||||
if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && spr->gzt <= clip3d->sclipBottom) return;
|
||||
if ((clip3d->fake3D & FAKE3D_CLIPTOP) && spr->gzb >= clip3d->sclipTop) return;
|
||||
|
||||
// kg3D - correct colors now
|
||||
if (!fixedcolormap && fixedlightlev < 0 && spr->sector->e && spr->sector->e->XFloor.lightlist.Size())
|
||||
{
|
||||
if (!(clip3d->fake3D & FAKE3D_CLIPTOP))
|
||||
{
|
||||
clip3d->sclipTop = spr->sector->ceilingplane.ZatPoint(ViewPos);
|
||||
}
|
||||
sector_t *sec = nullptr;
|
||||
for (i = spr->sector->e->XFloor.lightlist.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (clip3d->sclipTop <= spr->sector->e->XFloor.lightlist[i].plane.Zat0())
|
||||
{
|
||||
rover = spr->sector->e->XFloor.lightlist[i].caster;
|
||||
if (rover)
|
||||
{
|
||||
if (rover->flags & FF_DOUBLESHADOW && clip3d->sclipTop <= rover->bottom.plane->Zat0())
|
||||
{
|
||||
break;
|
||||
}
|
||||
sec = rover->model;
|
||||
if (rover->flags & FF_FADEWALLS)
|
||||
{
|
||||
mybasecolormap = sec->ColorMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
mybasecolormap = spr->sector->e->XFloor.lightlist[i].extra_colormap;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// found new values, recalculate
|
||||
if (sec)
|
||||
{
|
||||
INTBOOL invertcolormap = (spr->Style.RenderStyle.Flags & STYLEF_InvertOverlay);
|
||||
|
||||
if (spr->Style.RenderStyle.Flags & STYLEF_InvertSource)
|
||||
{
|
||||
invertcolormap = !invertcolormap;
|
||||
}
|
||||
|
||||
// Sprites that are added to the scene must fade to black.
|
||||
if (spr->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && mybasecolormap->Fade != 0)
|
||||
{
|
||||
mybasecolormap = GetSpecialLights(mybasecolormap->Color, 0, mybasecolormap->Desaturate);
|
||||
}
|
||||
|
||||
if (spr->Style.RenderStyle.Flags & STYLEF_FadeToBlack)
|
||||
{
|
||||
if (invertcolormap)
|
||||
{ // Fade to white
|
||||
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(255, 255, 255), mybasecolormap->Desaturate);
|
||||
invertcolormap = false;
|
||||
}
|
||||
else
|
||||
{ // Fade to black
|
||||
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(0, 0, 0), mybasecolormap->Desaturate);
|
||||
}
|
||||
}
|
||||
|
||||
// get light level
|
||||
if (invertcolormap)
|
||||
{
|
||||
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
|
||||
}
|
||||
if (fixedlightlev >= 0)
|
||||
{
|
||||
spr->Style.BaseColormap = mybasecolormap;
|
||||
spr->Style.ColormapNum = fixedlightlev >> COLORMAPSHIFT;
|
||||
}
|
||||
else if (!spr->foggy && (spr->renderflags & RF_FULLBRIGHT))
|
||||
{ // full bright
|
||||
spr->Style.BaseColormap = (r_fullbrightignoresectorcolor) ? &FullNormalLight : mybasecolormap;
|
||||
spr->Style.ColormapNum = 0;
|
||||
}
|
||||
else
|
||||
{ // diminished light
|
||||
int spriteshade = LIGHT2SHADE(sec->lightlevel + R_ActualExtraLight(spr->foggy));
|
||||
spr->Style.BaseColormap = mybasecolormap;
|
||||
spr->Style.ColormapNum = GETPALOOKUP(r_SpriteVisibility / MAX(MINZ, (double)spr->depth), spriteshade);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// [RH] Initialize the clipping arrays to their largest possible range
|
||||
// instead of using a special "not clipped" value. This eliminates
|
||||
// visual anomalies when looking down and should be faster, too.
|
||||
topclip = 0;
|
||||
botclip = viewheight;
|
||||
|
||||
// killough 3/27/98:
|
||||
// Clip the sprite against deep water and/or fake ceilings.
|
||||
// [RH] rewrote this to be based on which part of the sector is really visible
|
||||
|
||||
double scale = InvZtoScale * spr->idepth;
|
||||
double hzb = DBL_MIN, hzt = DBL_MAX;
|
||||
|
||||
if (spr->IsVoxel() && spr->floorclip != 0)
|
||||
{
|
||||
hzb = spr->gzb;
|
||||
}
|
||||
|
||||
if (spr->heightsec && !(spr->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC))
|
||||
{ // only things in specially marked sectors
|
||||
if (spr->FakeFlatStat != WaterFakeSide::AboveCeiling)
|
||||
{
|
||||
double hz = spr->heightsec->floorplane.ZatPoint(spr->gpos);
|
||||
int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale);
|
||||
|
||||
if (spr->FakeFlatStat == WaterFakeSide::BelowFloor)
|
||||
{ // seen below floor: clip top
|
||||
if (!spr->IsVoxel() && h > topclip)
|
||||
{
|
||||
topclip = short(MIN(h, viewheight));
|
||||
}
|
||||
hzt = MIN(hzt, hz);
|
||||
}
|
||||
else
|
||||
{ // seen in the middle: clip bottom
|
||||
if (!spr->IsVoxel() && h < botclip)
|
||||
{
|
||||
botclip = MAX<short>(0, h);
|
||||
}
|
||||
hzb = MAX(hzb, hz);
|
||||
}
|
||||
}
|
||||
if (spr->FakeFlatStat != WaterFakeSide::BelowFloor && !(spr->heightsec->MoreFlags & SECF_FAKEFLOORONLY))
|
||||
{
|
||||
double hz = spr->heightsec->ceilingplane.ZatPoint(spr->gpos);
|
||||
int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale);
|
||||
|
||||
if (spr->FakeFlatStat == WaterFakeSide::AboveCeiling)
|
||||
{ // seen above ceiling: clip bottom
|
||||
if (!spr->IsVoxel() && h < botclip)
|
||||
{
|
||||
botclip = MAX<short>(0, h);
|
||||
}
|
||||
hzb = MAX(hzb, hz);
|
||||
}
|
||||
else
|
||||
{ // seen in the middle: clip top
|
||||
if (!spr->IsVoxel() && h > topclip)
|
||||
{
|
||||
topclip = MIN(h, viewheight);
|
||||
}
|
||||
hzt = MIN(hzt, hz);
|
||||
}
|
||||
}
|
||||
}
|
||||
// killough 3/27/98: end special clipping for deep water / fake ceilings
|
||||
else if (!spr->IsVoxel() && spr->floorclip)
|
||||
{ // [RH] Move floorclip stuff from R_DrawVisSprite to here
|
||||
//int clip = ((FLOAT2FIXED(CenterY) - FixedMul (spr->texturemid - (spr->pic->GetHeight() << FRACBITS) + spr->floorclip, spr->yscale)) >> FRACBITS);
|
||||
int clip = xs_RoundToInt(CenterY - (spr->texturemid - spr->pic->GetHeight() + spr->floorclip) * spr->yscale);
|
||||
if (clip < botclip)
|
||||
{
|
||||
botclip = MAX<short>(0, clip);
|
||||
}
|
||||
}
|
||||
|
||||
if (clip3d->fake3D & FAKE3D_CLIPBOTTOM)
|
||||
{
|
||||
if (!spr->IsVoxel())
|
||||
{
|
||||
double hz = clip3d->sclipBottom;
|
||||
if (spr->fakefloor)
|
||||
{
|
||||
double floorz = spr->fakefloor->top.plane->Zat0();
|
||||
if (ViewPos.Z > floorz && floorz == clip3d->sclipBottom)
|
||||
{
|
||||
hz = spr->fakefloor->bottom.plane->Zat0();
|
||||
}
|
||||
}
|
||||
int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale);
|
||||
if (h < botclip)
|
||||
{
|
||||
botclip = MAX<short>(0, h);
|
||||
}
|
||||
}
|
||||
hzb = MAX(hzb, clip3d->sclipBottom);
|
||||
}
|
||||
if (clip3d->fake3D & FAKE3D_CLIPTOP)
|
||||
{
|
||||
if (!spr->IsVoxel())
|
||||
{
|
||||
double hz = clip3d->sclipTop;
|
||||
if (spr->fakeceiling != nullptr)
|
||||
{
|
||||
double ceilingZ = spr->fakeceiling->bottom.plane->Zat0();
|
||||
if (ViewPos.Z < ceilingZ && ceilingZ == clip3d->sclipTop)
|
||||
{
|
||||
hz = spr->fakeceiling->top.plane->Zat0();
|
||||
}
|
||||
}
|
||||
int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale);
|
||||
if (h > topclip)
|
||||
{
|
||||
topclip = short(MIN(h, viewheight));
|
||||
}
|
||||
}
|
||||
hzt = MIN(hzt, clip3d->sclipTop);
|
||||
}
|
||||
|
||||
if (topclip >= botclip)
|
||||
{
|
||||
spr->Style.BaseColormap = colormap;
|
||||
spr->Style.ColormapNum = colormapnum;
|
||||
return;
|
||||
}
|
||||
|
||||
i = x2 - x1;
|
||||
clip1 = clipbot + x1;
|
||||
clip2 = cliptop + x1;
|
||||
do
|
||||
{
|
||||
*clip1++ = botclip;
|
||||
*clip2++ = topclip;
|
||||
} while (--i);
|
||||
|
||||
// Scan drawsegs from end to start for obscuring segs.
|
||||
// The first drawseg that is closer than the sprite is the clip seg.
|
||||
|
||||
// Modified by Lee Killough:
|
||||
// (pointer check was originally nonportable
|
||||
// and buggy, by going past LEFT end of array):
|
||||
|
||||
// for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code
|
||||
|
||||
for (ds = ds_p; ds-- > firstdrawseg; ) // new -- killough
|
||||
{
|
||||
// [ZZ] portal handling here
|
||||
//if (ds->CurrentPortalUniq != spr->CurrentPortalUniq)
|
||||
// continue;
|
||||
// [ZZ] WARNING: uncommenting the two above lines, totally breaks sprite clipping
|
||||
|
||||
// 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 &&
|
||||
!ds->bFogBoundary))
|
||||
{
|
||||
// does not cover sprite
|
||||
continue;
|
||||
}
|
||||
|
||||
r1 = MAX<int>(ds->x1, x1);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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 = RenderPortal::Instance();
|
||||
|
||||
// seg is behind sprite, so draw the mid texture if it has one
|
||||
if (ds->CurrentPortalUniq == renderportal->CurrentPortalUniq && // [ZZ] instead, portal uniq check is made here
|
||||
(ds->maskedtexturecol != nullptr || ds->bFogBoundary))
|
||||
R_RenderMaskedSegRange(ds, r1, r2);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// clip this piece of the sprite
|
||||
// killough 3/27/98: optimized and made much shorter
|
||||
// [RH] Optimized further (at least for VC++;
|
||||
// other compilers should be at least as good as before)
|
||||
|
||||
if (ds->silhouette & SIL_BOTTOM) //bottom sil
|
||||
{
|
||||
clip1 = clipbot + r1;
|
||||
clip2 = ds->sprbottomclip + r1 - ds->x1;
|
||||
i = r2 - r1;
|
||||
do
|
||||
{
|
||||
if (*clip1 > *clip2)
|
||||
*clip1 = *clip2;
|
||||
clip1++;
|
||||
clip2++;
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
if (ds->silhouette & SIL_TOP) // top sil
|
||||
{
|
||||
clip1 = cliptop + r1;
|
||||
clip2 = ds->sprtopclip + r1 - ds->x1;
|
||||
i = r2 - r1;
|
||||
do
|
||||
{
|
||||
if (*clip1 < *clip2)
|
||||
*clip1 = *clip2;
|
||||
clip1++;
|
||||
clip2++;
|
||||
} while (--i);
|
||||
}
|
||||
}
|
||||
|
||||
// all clipping has been performed, so draw the sprite
|
||||
|
||||
if (!spr->IsVoxel())
|
||||
{
|
||||
spr->Render(clipbot, cliptop, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it is completely clipped away, don't bother drawing it.
|
||||
if (cliptop[x2] >= clipbot[x2])
|
||||
{
|
||||
for (i = x1; i < x2; ++i)
|
||||
{
|
||||
if (cliptop[i] < clipbot[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == x2)
|
||||
{
|
||||
spr->Style.BaseColormap = colormap;
|
||||
spr->Style.ColormapNum = colormapnum;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Add everything outside the left and right edges to the clipping array
|
||||
// for R_DrawVisVoxel().
|
||||
if (x1 > 0)
|
||||
{
|
||||
fillshort(cliptop, x1, viewheight);
|
||||
}
|
||||
if (x2 < viewwidth - 1)
|
||||
{
|
||||
fillshort(cliptop + x2, viewwidth - x2, viewheight);
|
||||
}
|
||||
int minvoxely = spr->gzt <= hzt ? 0 : xs_RoundToInt((spr->gzt - hzt) / spr->yscale);
|
||||
int maxvoxely = spr->gzb > hzb ? INT_MAX : xs_RoundToInt((spr->gzt - hzb) / spr->yscale);
|
||||
spr->Render(cliptop, clipbot, minvoxely, maxvoxely);
|
||||
}
|
||||
spr->Style.BaseColormap = colormap;
|
||||
spr->Style.ColormapNum = colormapnum;
|
||||
}
|
||||
|
||||
void RenderTranslucentPass::DrawMaskedSingle(bool renew)
|
||||
{
|
||||
RenderPortal *renderportal = RenderPortal::Instance();
|
||||
|
@ -524,9 +125,10 @@ namespace swrenderer
|
|||
auto &sortedSprites = VisibleSpriteList::Instance()->SortedSprites;
|
||||
for (int i = sortedSprites.Size(); i > 0; i--)
|
||||
{
|
||||
if (sortedSprites[i - 1]->CurrentPortalUniq != renderportal->CurrentPortalUniq)
|
||||
continue; // probably another time
|
||||
DrawSprite(sortedSprites[i - 1]);
|
||||
if (sortedSprites[i - 1]->IsCurrentPortalUniq(renderportal->CurrentPortalUniq))
|
||||
{
|
||||
sortedSprites[i - 1]->Render();
|
||||
}
|
||||
}
|
||||
|
||||
// render any remaining masked mid textures
|
||||
|
|
|
@ -38,7 +38,6 @@ namespace swrenderer
|
|||
|
||||
private:
|
||||
static void CollectPortals();
|
||||
static void DrawSprite(VisibleSprite *spr);
|
||||
static void DrawMaskedSingle(bool renew);
|
||||
|
||||
static TArray<drawseg_t *> portaldrawsegs;
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "r_visiblesprite.h"
|
||||
#include "swrenderer/scene/r_opaque_pass.h"
|
||||
|
||||
struct particle_t;
|
||||
|
||||
namespace swrenderer
|
||||
{
|
||||
class RenderParticle : public VisibleSprite
|
||||
|
@ -23,6 +25,7 @@ namespace swrenderer
|
|||
public:
|
||||
static void Project(particle_t *, const sector_t *sector, int shade, WaterFakeSide fakeside, bool foggy);
|
||||
|
||||
protected:
|
||||
bool IsParticle() const override { return true; }
|
||||
void Render(short *cliptop, short *clipbottom, int minZ, int maxZ) override;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace swrenderer
|
|||
public:
|
||||
static void Project(AActor *thing, const DVector3 &pos, FTexture *tex, const DVector2 &spriteScale, int renderflags, WaterFakeSide fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector, int spriteshade, bool foggy, FDynamicColormap *basecolormap);
|
||||
|
||||
protected:
|
||||
void Render(short *cliptop, short *clipbottom, int minZ, int maxZ) override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -29,10 +29,415 @@
|
|||
#include "swrenderer/things/r_wallsprite.h"
|
||||
#include "swrenderer/things/r_playersprite.h"
|
||||
#include "swrenderer/segments/r_drawsegment.h"
|
||||
#include "swrenderer/scene/r_portal.h"
|
||||
#include "swrenderer/plane/r_visibleplane.h"
|
||||
#include "swrenderer/scene/r_portal.h"
|
||||
#include "swrenderer/scene/r_light.h"
|
||||
#include "swrenderer/scene/r_viewport.h"
|
||||
#include "swrenderer/r_memory.h"
|
||||
|
||||
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
|
||||
|
||||
namespace swrenderer
|
||||
{
|
||||
void VisibleSprite::Render()
|
||||
{
|
||||
static short clipbot[MAXWIDTH];
|
||||
static short cliptop[MAXWIDTH];
|
||||
|
||||
VisibleSprite *spr = this;
|
||||
|
||||
drawseg_t *ds;
|
||||
int i;
|
||||
int x1, x2;
|
||||
int r1, r2;
|
||||
short topclip, botclip;
|
||||
short *clip1, *clip2;
|
||||
FSWColormap *colormap = spr->Style.BaseColormap;
|
||||
int colormapnum = spr->Style.ColormapNum;
|
||||
F3DFloor *rover;
|
||||
FDynamicColormap *mybasecolormap;
|
||||
|
||||
Clip3DFloors *clip3d = Clip3DFloors::Instance();
|
||||
|
||||
// [RH] Check for particles
|
||||
if (spr->IsParticle())
|
||||
{
|
||||
// kg3D - reject invisible parts
|
||||
if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && spr->gpos.Z <= clip3d->sclipBottom) return;
|
||||
if ((clip3d->fake3D & FAKE3D_CLIPTOP) && spr->gpos.Z >= clip3d->sclipTop) return;
|
||||
|
||||
spr->Render(nullptr, nullptr, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
x1 = spr->x1;
|
||||
x2 = spr->x2;
|
||||
|
||||
// [RH] Quickly reject sprites with bad x ranges.
|
||||
if (x1 >= x2)
|
||||
return;
|
||||
|
||||
// [RH] Sprites split behind a one-sided line can also be discarded.
|
||||
if (spr->sector == nullptr)
|
||||
return;
|
||||
|
||||
// kg3D - reject invisible parts
|
||||
if ((clip3d->fake3D & FAKE3D_CLIPBOTTOM) && spr->gzt <= clip3d->sclipBottom) return;
|
||||
if ((clip3d->fake3D & FAKE3D_CLIPTOP) && spr->gzb >= clip3d->sclipTop) return;
|
||||
|
||||
// kg3D - correct colors now
|
||||
if (!fixedcolormap && fixedlightlev < 0 && spr->sector->e && spr->sector->e->XFloor.lightlist.Size())
|
||||
{
|
||||
if (!(clip3d->fake3D & FAKE3D_CLIPTOP))
|
||||
{
|
||||
clip3d->sclipTop = spr->sector->ceilingplane.ZatPoint(ViewPos);
|
||||
}
|
||||
sector_t *sec = nullptr;
|
||||
for (i = spr->sector->e->XFloor.lightlist.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (clip3d->sclipTop <= spr->sector->e->XFloor.lightlist[i].plane.Zat0())
|
||||
{
|
||||
rover = spr->sector->e->XFloor.lightlist[i].caster;
|
||||
if (rover)
|
||||
{
|
||||
if (rover->flags & FF_DOUBLESHADOW && clip3d->sclipTop <= rover->bottom.plane->Zat0())
|
||||
{
|
||||
break;
|
||||
}
|
||||
sec = rover->model;
|
||||
if (rover->flags & FF_FADEWALLS)
|
||||
{
|
||||
mybasecolormap = sec->ColorMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
mybasecolormap = spr->sector->e->XFloor.lightlist[i].extra_colormap;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// found new values, recalculate
|
||||
if (sec)
|
||||
{
|
||||
INTBOOL invertcolormap = (spr->Style.RenderStyle.Flags & STYLEF_InvertOverlay);
|
||||
|
||||
if (spr->Style.RenderStyle.Flags & STYLEF_InvertSource)
|
||||
{
|
||||
invertcolormap = !invertcolormap;
|
||||
}
|
||||
|
||||
// Sprites that are added to the scene must fade to black.
|
||||
if (spr->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && mybasecolormap->Fade != 0)
|
||||
{
|
||||
mybasecolormap = GetSpecialLights(mybasecolormap->Color, 0, mybasecolormap->Desaturate);
|
||||
}
|
||||
|
||||
if (spr->Style.RenderStyle.Flags & STYLEF_FadeToBlack)
|
||||
{
|
||||
if (invertcolormap)
|
||||
{ // Fade to white
|
||||
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(255, 255, 255), mybasecolormap->Desaturate);
|
||||
invertcolormap = false;
|
||||
}
|
||||
else
|
||||
{ // Fade to black
|
||||
mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(0, 0, 0), mybasecolormap->Desaturate);
|
||||
}
|
||||
}
|
||||
|
||||
// get light level
|
||||
if (invertcolormap)
|
||||
{
|
||||
mybasecolormap = GetSpecialLights(mybasecolormap->Color, mybasecolormap->Fade.InverseColor(), mybasecolormap->Desaturate);
|
||||
}
|
||||
if (fixedlightlev >= 0)
|
||||
{
|
||||
spr->Style.BaseColormap = mybasecolormap;
|
||||
spr->Style.ColormapNum = fixedlightlev >> COLORMAPSHIFT;
|
||||
}
|
||||
else if (!spr->foggy && (spr->renderflags & RF_FULLBRIGHT))
|
||||
{ // full bright
|
||||
spr->Style.BaseColormap = (r_fullbrightignoresectorcolor) ? &FullNormalLight : mybasecolormap;
|
||||
spr->Style.ColormapNum = 0;
|
||||
}
|
||||
else
|
||||
{ // diminished light
|
||||
int spriteshade = LIGHT2SHADE(sec->lightlevel + R_ActualExtraLight(spr->foggy));
|
||||
spr->Style.BaseColormap = mybasecolormap;
|
||||
spr->Style.ColormapNum = GETPALOOKUP(r_SpriteVisibility / MAX(MINZ, (double)spr->depth), spriteshade);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// [RH] Initialize the clipping arrays to their largest possible range
|
||||
// instead of using a special "not clipped" value. This eliminates
|
||||
// visual anomalies when looking down and should be faster, too.
|
||||
topclip = 0;
|
||||
botclip = viewheight;
|
||||
|
||||
// killough 3/27/98:
|
||||
// Clip the sprite against deep water and/or fake ceilings.
|
||||
// [RH] rewrote this to be based on which part of the sector is really visible
|
||||
|
||||
double scale = InvZtoScale * spr->idepth;
|
||||
double hzb = DBL_MIN, hzt = DBL_MAX;
|
||||
|
||||
if (spr->IsVoxel() && spr->floorclip != 0)
|
||||
{
|
||||
hzb = spr->gzb;
|
||||
}
|
||||
|
||||
if (spr->heightsec && !(spr->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC))
|
||||
{ // only things in specially marked sectors
|
||||
if (spr->FakeFlatStat != WaterFakeSide::AboveCeiling)
|
||||
{
|
||||
double hz = spr->heightsec->floorplane.ZatPoint(spr->gpos);
|
||||
int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale);
|
||||
|
||||
if (spr->FakeFlatStat == WaterFakeSide::BelowFloor)
|
||||
{ // seen below floor: clip top
|
||||
if (!spr->IsVoxel() && h > topclip)
|
||||
{
|
||||
topclip = short(MIN(h, viewheight));
|
||||
}
|
||||
hzt = MIN(hzt, hz);
|
||||
}
|
||||
else
|
||||
{ // seen in the middle: clip bottom
|
||||
if (!spr->IsVoxel() && h < botclip)
|
||||
{
|
||||
botclip = MAX<short>(0, h);
|
||||
}
|
||||
hzb = MAX(hzb, hz);
|
||||
}
|
||||
}
|
||||
if (spr->FakeFlatStat != WaterFakeSide::BelowFloor && !(spr->heightsec->MoreFlags & SECF_FAKEFLOORONLY))
|
||||
{
|
||||
double hz = spr->heightsec->ceilingplane.ZatPoint(spr->gpos);
|
||||
int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale);
|
||||
|
||||
if (spr->FakeFlatStat == WaterFakeSide::AboveCeiling)
|
||||
{ // seen above ceiling: clip bottom
|
||||
if (!spr->IsVoxel() && h < botclip)
|
||||
{
|
||||
botclip = MAX<short>(0, h);
|
||||
}
|
||||
hzb = MAX(hzb, hz);
|
||||
}
|
||||
else
|
||||
{ // seen in the middle: clip top
|
||||
if (!spr->IsVoxel() && h > topclip)
|
||||
{
|
||||
topclip = MIN(h, viewheight);
|
||||
}
|
||||
hzt = MIN(hzt, hz);
|
||||
}
|
||||
}
|
||||
}
|
||||
// killough 3/27/98: end special clipping for deep water / fake ceilings
|
||||
else if (!spr->IsVoxel() && spr->floorclip)
|
||||
{ // [RH] Move floorclip stuff from R_DrawVisSprite to here
|
||||
//int clip = ((FLOAT2FIXED(CenterY) - FixedMul (spr->texturemid - (spr->pic->GetHeight() << FRACBITS) + spr->floorclip, spr->yscale)) >> FRACBITS);
|
||||
int clip = xs_RoundToInt(CenterY - (spr->texturemid - spr->pic->GetHeight() + spr->floorclip) * spr->yscale);
|
||||
if (clip < botclip)
|
||||
{
|
||||
botclip = MAX<short>(0, clip);
|
||||
}
|
||||
}
|
||||
|
||||
if (clip3d->fake3D & FAKE3D_CLIPBOTTOM)
|
||||
{
|
||||
if (!spr->IsVoxel())
|
||||
{
|
||||
double hz = clip3d->sclipBottom;
|
||||
if (spr->fakefloor)
|
||||
{
|
||||
double floorz = spr->fakefloor->top.plane->Zat0();
|
||||
if (ViewPos.Z > floorz && floorz == clip3d->sclipBottom)
|
||||
{
|
||||
hz = spr->fakefloor->bottom.plane->Zat0();
|
||||
}
|
||||
}
|
||||
int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale);
|
||||
if (h < botclip)
|
||||
{
|
||||
botclip = MAX<short>(0, h);
|
||||
}
|
||||
}
|
||||
hzb = MAX(hzb, clip3d->sclipBottom);
|
||||
}
|
||||
if (clip3d->fake3D & FAKE3D_CLIPTOP)
|
||||
{
|
||||
if (!spr->IsVoxel())
|
||||
{
|
||||
double hz = clip3d->sclipTop;
|
||||
if (spr->fakeceiling != nullptr)
|
||||
{
|
||||
double ceilingZ = spr->fakeceiling->bottom.plane->Zat0();
|
||||
if (ViewPos.Z < ceilingZ && ceilingZ == clip3d->sclipTop)
|
||||
{
|
||||
hz = spr->fakeceiling->top.plane->Zat0();
|
||||
}
|
||||
}
|
||||
int h = xs_RoundToInt(CenterY - (hz - ViewPos.Z) * scale);
|
||||
if (h > topclip)
|
||||
{
|
||||
topclip = short(MIN(h, viewheight));
|
||||
}
|
||||
}
|
||||
hzt = MIN(hzt, clip3d->sclipTop);
|
||||
}
|
||||
|
||||
if (topclip >= botclip)
|
||||
{
|
||||
spr->Style.BaseColormap = colormap;
|
||||
spr->Style.ColormapNum = colormapnum;
|
||||
return;
|
||||
}
|
||||
|
||||
i = x2 - x1;
|
||||
clip1 = clipbot + x1;
|
||||
clip2 = cliptop + x1;
|
||||
do
|
||||
{
|
||||
*clip1++ = botclip;
|
||||
*clip2++ = topclip;
|
||||
} while (--i);
|
||||
|
||||
// Scan drawsegs from end to start for obscuring segs.
|
||||
// The first drawseg that is closer than the sprite is the clip seg.
|
||||
|
||||
// Modified by Lee Killough:
|
||||
// (pointer check was originally nonportable
|
||||
// and buggy, by going past LEFT end of array):
|
||||
|
||||
// for (ds=ds_p-1 ; ds >= drawsegs ; ds--) old buggy code
|
||||
|
||||
for (ds = ds_p; ds-- > firstdrawseg; ) // new -- killough
|
||||
{
|
||||
// [ZZ] portal handling here
|
||||
//if (ds->CurrentPortalUniq != spr->CurrentPortalUniq)
|
||||
// continue;
|
||||
// [ZZ] WARNING: uncommenting the two above lines, totally breaks sprite clipping
|
||||
|
||||
// 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 &&
|
||||
!ds->bFogBoundary))
|
||||
{
|
||||
// does not cover sprite
|
||||
continue;
|
||||
}
|
||||
|
||||
r1 = MAX<int>(ds->x1, x1);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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 = RenderPortal::Instance();
|
||||
|
||||
// seg is behind sprite, so draw the mid texture if it has one
|
||||
if (ds->CurrentPortalUniq == renderportal->CurrentPortalUniq && // [ZZ] instead, portal uniq check is made here
|
||||
(ds->maskedtexturecol != nullptr || ds->bFogBoundary))
|
||||
R_RenderMaskedSegRange(ds, r1, r2);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// clip this piece of the sprite
|
||||
// killough 3/27/98: optimized and made much shorter
|
||||
// [RH] Optimized further (at least for VC++;
|
||||
// other compilers should be at least as good as before)
|
||||
|
||||
if (ds->silhouette & SIL_BOTTOM) //bottom sil
|
||||
{
|
||||
clip1 = clipbot + r1;
|
||||
clip2 = ds->sprbottomclip + r1 - ds->x1;
|
||||
i = r2 - r1;
|
||||
do
|
||||
{
|
||||
if (*clip1 > *clip2)
|
||||
*clip1 = *clip2;
|
||||
clip1++;
|
||||
clip2++;
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
if (ds->silhouette & SIL_TOP) // top sil
|
||||
{
|
||||
clip1 = cliptop + r1;
|
||||
clip2 = ds->sprtopclip + r1 - ds->x1;
|
||||
i = r2 - r1;
|
||||
do
|
||||
{
|
||||
if (*clip1 < *clip2)
|
||||
*clip1 = *clip2;
|
||||
clip1++;
|
||||
clip2++;
|
||||
} while (--i);
|
||||
}
|
||||
}
|
||||
|
||||
// all clipping has been performed, so draw the sprite
|
||||
|
||||
if (!spr->IsVoxel())
|
||||
{
|
||||
spr->Render(clipbot, cliptop, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it is completely clipped away, don't bother drawing it.
|
||||
if (cliptop[x2] >= clipbot[x2])
|
||||
{
|
||||
for (i = x1; i < x2; ++i)
|
||||
{
|
||||
if (cliptop[i] < clipbot[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == x2)
|
||||
{
|
||||
spr->Style.BaseColormap = colormap;
|
||||
spr->Style.ColormapNum = colormapnum;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Add everything outside the left and right edges to the clipping array
|
||||
// for R_DrawVisVoxel().
|
||||
if (x1 > 0)
|
||||
{
|
||||
fillshort(cliptop, x1, viewheight);
|
||||
}
|
||||
if (x2 < viewwidth - 1)
|
||||
{
|
||||
fillshort(cliptop + x2, viewwidth - x2, viewheight);
|
||||
}
|
||||
int minvoxely = spr->gzt <= hzt ? 0 : xs_RoundToInt((spr->gzt - hzt) / spr->yscale);
|
||||
int maxvoxely = spr->gzb > hzb ? INT_MAX : xs_RoundToInt((spr->gzt - hzb) / spr->yscale);
|
||||
spr->Render(cliptop, clipbot, minvoxely, maxvoxely);
|
||||
}
|
||||
spr->Style.BaseColormap = colormap;
|
||||
spr->Style.ColormapNum = colormapnum;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,14 +19,20 @@
|
|||
|
||||
#define MINZ double((2048*4) / double(1 << 20))
|
||||
|
||||
struct particle_t;
|
||||
struct FVoxel;
|
||||
|
||||
namespace swrenderer
|
||||
{
|
||||
class VisibleSprite
|
||||
{
|
||||
public:
|
||||
void Render();
|
||||
|
||||
bool IsCurrentPortalUniq(int portalUniq) const { return CurrentPortalUniq == portalUniq; }
|
||||
const FVector3 &WorldPos() const { return gpos; }
|
||||
|
||||
double SortDist2D() const { return DVector2(deltax, deltay).LengthSquared(); }
|
||||
float SortDist() const { return idepth; }
|
||||
|
||||
protected:
|
||||
virtual bool IsParticle() const { return false; }
|
||||
virtual bool IsVoxel() const { return false; }
|
||||
virtual bool IsWallSprite() const { return false; }
|
||||
|
|
|
@ -89,7 +89,7 @@ namespace swrenderer
|
|||
|
||||
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](VisibleSprite *a, VisibleSprite *b) -> bool
|
||||
{
|
||||
return DVector2(a->deltax, a->deltay).LengthSquared() < DVector2(b->deltax, b->deltay).LengthSquared();
|
||||
return a->SortDist2D() < b->SortDist2D();
|
||||
});
|
||||
}
|
||||
else
|
||||
|
@ -98,7 +98,7 @@ namespace swrenderer
|
|||
|
||||
std::stable_sort(&SortedSprites[0], &SortedSprites[count], [](VisibleSprite *a, VisibleSprite *b) -> bool
|
||||
{
|
||||
return a->idepth > b->idepth;
|
||||
return a->SortDist() > b->SortDist();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ namespace swrenderer
|
|||
|
||||
static void Deinit();
|
||||
|
||||
protected:
|
||||
bool IsVoxel() const override { return true; }
|
||||
void Render(short *cliptop, short *clipbottom, int minZ, int maxZ) override;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace swrenderer
|
|||
public:
|
||||
static void Project(AActor *thing, const DVector3 &pos, FTextureID picnum, const DVector2 &scale, int renderflags, int spriteshade, bool foggy, FDynamicColormap *basecolormap);
|
||||
|
||||
protected:
|
||||
bool IsWallSprite() const override { return true; }
|
||||
void Render(short *cliptop, short *clipbottom, int minZ, int maxZ) override;
|
||||
|
||||
|
|
Loading…
Reference in a new issue