Add sprite shadows for the hardware renderer

This commit is contained in:
nashmuhandes 2021-04-21 22:36:44 +08:00 committed by Rachael Alexanderson
parent 5446a1a355
commit 15159a3c19
3 changed files with 66 additions and 3 deletions

View file

@ -49,6 +49,8 @@
CVAR(Bool, gl_multithread, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, gl_multithread, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
EXTERN_CVAR(Float, r_actorspriteshadowdist)
thread_local bool isWorkerThread; thread_local bool isWorkerThread;
ctpl::thread_pool renderPool(1); ctpl::thread_pool renderPool(1);
bool inited = false; bool inited = false;
@ -547,6 +549,18 @@ void HWDrawInfo::RenderThings(subsector_t * sub, sector_t * sector)
if (CurrentMapSections[thing->subsector->mapsection]) if (CurrentMapSections[thing->subsector->mapsection])
{ {
HWSprite sprite; HWSprite sprite;
// [Nash] draw sprite shadow
if (R_ShouldDrawSpriteShadow(thing))
{
double dist = (thing->Pos() - vp.Pos).LengthSquared();
double check = r_actorspriteshadowdist;
if (dist <= check * check)
{
sprite.Process(this, thing, sector, in_area, false, true);
}
}
sprite.Process(this, thing, sector, in_area, false); sprite.Process(this, thing, sector, in_area, false);
} }
} }
@ -566,6 +580,18 @@ void HWDrawInfo::RenderThings(subsector_t * sub, sector_t * sector)
} }
HWSprite sprite; HWSprite sprite;
// [Nash] draw sprite shadow
if (R_ShouldDrawSpriteShadow(thing))
{
double dist = (thing->Pos() - vp.Pos).LengthSquared();
double check = r_actorspriteshadowdist;
if (dist <= check * check)
{
sprite.Process(this, thing, sector, in_area, true, true);
}
}
sprite.Process(this, thing, sector, in_area, true); sprite.Process(this, thing, sector, in_area, true);
} }
} }

View file

@ -385,7 +385,7 @@ public:
void CreateVertices(HWDrawInfo *di); void CreateVertices(HWDrawInfo *di);
void PutSprite(HWDrawInfo *di, bool translucent); void PutSprite(HWDrawInfo *di, bool translucent);
void Process(HWDrawInfo *di, AActor* thing,sector_t * sector, area_t in_area, int thruportal = false); void Process(HWDrawInfo *di, AActor* thing,sector_t * sector, area_t in_area, int thruportal = false, bool isSpriteShadow = false);
void ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t *sector);//, int shade, int fakeside) void ProcessParticle (HWDrawInfo *di, particle_t *particle, sector_t *sector);//, int shade, int fakeside)
void DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent); void DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent);

View file

@ -678,7 +678,7 @@ void HWSprite::PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingp
// //
//========================================================================== //==========================================================================
void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t in_area, int thruportal) void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t in_area, int thruportal, bool isSpriteShadow)
{ {
sector_t rs; sector_t rs;
sector_t * rendersector; sector_t * rendersector;
@ -795,6 +795,12 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
y = thingpos.Y; y = thingpos.Y;
if (spritetype == RF_FACESPRITE) z -= thing->Floorclip; // wall and flat sprites are to be considered di->Level-> geometry so this may not apply. if (spritetype == RF_FACESPRITE) z -= thing->Floorclip; // wall and flat sprites are to be considered di->Level-> geometry so this may not apply.
// snap shadow Z to the floor
if (isSpriteShadow)
{
z = thing->floorz;
}
// [RH] Make floatbobbing a renderer-only effect. // [RH] Make floatbobbing a renderer-only effect.
if (thing->flags2 & MF2_FLOATBOB) if (thing->flags2 & MF2_FLOATBOB)
{ {
@ -803,6 +809,13 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
} }
modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED)); modelframe = isPicnumOverride ? nullptr : FindModelFrame(thing->GetClass(), spritenum, thing->frame, !!(thing->flags & MF_DROPPED));
// don't bother drawing sprite shadows if this is a model (it will never look right)
if (modelframe && isSpriteShadow)
{
return;
}
if (!modelframe) if (!modelframe)
{ {
bool mirror = false; bool mirror = false;
@ -897,7 +910,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
if (thing->renderflags & RF_SPRITEFLIP) // [SP] Flip back if (thing->renderflags & RF_SPRITEFLIP) // [SP] Flip back
thing->renderflags ^= RF_XFLIP; thing->renderflags ^= RF_XFLIP;
r.Scale(sprscale.X, sprscale.Y); r.Scale(sprscale.X, isSpriteShadow ? sprscale.Y * 0.15 : sprscale.Y);
float SpriteOffY = thing->SpriteOffset.Y; float SpriteOffY = thing->SpriteOffset.Y;
float rightfac = -r.left - thing->SpriteOffset.X; float rightfac = -r.left - thing->SpriteOffset.X;
@ -1118,12 +1131,29 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
} }
} }
// for sprite shadow, use a translucent stencil renderstyle
if (isSpriteShadow)
{
RenderStyle = STYLE_Stencil;
ThingColor = MAKEARGB(ColorMatcher.Pick(0, 0, 0), 0, 0, 0);
trans = 0.5f;
hw_styleflags = STYLEHW_NoAlphaTest;
}
if (trans == 0.0f) return; if (trans == 0.0f) return;
// end of light calculation // end of light calculation
actor = thing; actor = thing;
index = thing->SpawnOrder; index = thing->SpawnOrder;
// sprite shadows should have a fixed index of -1 (ensuring they're drawn behind particles which have index 0)
// sorting should be irrelevant since they're always translucent
if (isSpriteShadow)
{
index = -1;
}
particle = nullptr; particle = nullptr;
const bool drawWithXYBillboard = (!(actor->renderflags & RF_FORCEYBILLBOARD) const bool drawWithXYBillboard = (!(actor->renderflags & RF_FORCEYBILLBOARD)
@ -1348,6 +1378,13 @@ void HWDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area)
th->Prev += newpos - savedpos; th->Prev += newpos - savedpos;
HWSprite spr; HWSprite spr;
// [Nash] draw sprite shadow
if (R_ShouldDrawSpriteShadow(th))
{
spr.Process(this, th, hw_FakeFlat(th->Sector, in_area, false, &fakesector), in_area, 2, true);
}
// This is called from the worker thread and must not alter the fake sector cache. // This is called from the worker thread and must not alter the fake sector cache.
spr.Process(this, th, hw_FakeFlat(th->Sector, in_area, false, &fakesector), in_area, 2); spr.Process(this, th, hw_FakeFlat(th->Sector, in_area, false, &fakesector), in_area, 2);
th->Angles.Yaw = savedangle; th->Angles.Yaw = savedangle;