Update shadow code

Thing brings over scale based on object height and interp amoung other things.
This commit is contained in:
NepDisk 2025-12-07 20:32:18 -05:00
parent 9a8b5b37bc
commit 09bfc6506a
3 changed files with 70 additions and 32 deletions

View file

@ -3138,17 +3138,17 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
FOutVector shadowVerts[4];
FSurfaceInfo sSurf;
float fscale; float fx; float fy; float offset;
float ph;
extracolormap_t *colormap = NULL;
FBITFIELD blendmode = PF_ReverseSubtract;
INT32 shader = SHADER_NONE;
UINT8 i;
INT32 heightsec, phs;
SINT8 flip = P_MobjFlip(thing);
INT32 light;
fixed_t scalemul;
fixed_t floordiff;
fixed_t groundz;
fixed_t slopez;
pslope_t *groundslope;
// uncapped/interpolation
@ -3163,6 +3163,26 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
groundz = R_GetShadowZ(thing, &groundslope);
heightsec = thing->subsector->sector->heightsec;
if (viewplayer->mo && viewplayer->mo->subsector)
phs = viewplayer->mo->subsector->sector->heightsec;
else
phs = -1;
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
{
if (gl_viewz < FIXED_TO_FLOAT(sectors[phs].floorheight) ?
thing->z >= sectors[heightsec].floorheight :
thing->z < sectors[heightsec].floorheight)
return;
if (gl_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ?
thing->z < sectors[heightsec].ceilingheight && gl_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) :
thing->z >= sectors[heightsec].ceilingheight)
return;
}
floordiff = abs((flip < 0 ? interp.height : 0) + interp.z - groundz);
if (!shadowpatch || !shadowpatch->hardware)
{
CONS_Debug(DBG_RENDER, "Recaching shadow patch\n");
@ -3170,34 +3190,26 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
}
gpatch = shadowpatch;
if (!gpatch || !gpatch->hardware || !((GLPatch_t *)gpatch->hardware)->mipmap->format)
return;
if (!gpatch || !gpatch->hardware || !((GLPatch_t *)gpatch->hardware)->mipmap->format) return;
HWR_GetPatch(gpatch);
scalemul = FixedMul(scale, (thing->radius * 2) / gpatch->height);
ph = (float)gpatch->height;
scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
scalemul = FixedMul(scalemul, (interp.radius*2) / gpatch->height);
fscale = FIXED_TO_FLOAT(scalemul);
fx = FIXED_TO_FLOAT(interp.x);
fy = FIXED_TO_FLOAT(interp.y);
if (fscale > 0.0)
{
offset = (ph / 2) * fscale;
}
else
{
return;
}
// 3--2
// | /|
// |/ |
// 0--1
if (thing && fabsf(fscale - 1.0f) > 1.0E-36f)
offset = (gpatch->height/2) * fscale;
else
offset = (float)(gpatch->height/2);
shadowVerts[2].x = shadowVerts[3].x = fx + offset;
shadowVerts[1].x = shadowVerts[0].x = fx - offset;
shadowVerts[1].z = shadowVerts[2].z = fy - offset;
@ -3215,7 +3227,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
{
for (i = 0; i < 4; i++)
{
slopez = P_GetSlopeZAt(groundslope, FLOAT_TO_FIXED(shadowVerts[i].x), FLOAT_TO_FIXED(shadowVerts[i].z));
fixed_t slopez = P_GetSlopeZAt(groundslope, FLOAT_TO_FIXED(shadowVerts[i].x), FLOAT_TO_FIXED(shadowVerts[i].z));
shadowVerts[i].y = FIXED_TO_FLOAT(slopez) + flip * 0.05f;
}
}

View file

@ -308,6 +308,8 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
out->spritexscale = mobj->resetinterp ? mobj->spritexscale : R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac);
out->spriteyscale = mobj->resetinterp ? mobj->spriteyscale : R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac);
out->spritexoffset = mobj->resetinterp ? mobj->spritexoffset : R_LerpFixed(mobj->old_spritexoffset, mobj->spritexoffset, frac);
out->spriteyoffset = mobj->resetinterp ? mobj->spriteyoffset : R_LerpFixed(mobj->old_spriteyoffset, mobj->spriteyoffset, frac);
if (mobj->scale == mobj->old_scale) // Tiny optimisation - scale is usually unchanging, so let's skip a lerp, two FixedMuls, and two FixedDivs
{

View file

@ -1509,15 +1509,17 @@ static void R_SkewShadowSprite(
static patch_t *shadowpatch = NULL;
static void R_ProjectDropShadow(
mobj_t *thing, vissprite_t *vis,
fixed_t scale, fixed_t tx, fixed_t tz)
static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz)
{
vissprite_t *shadow;
patch_t *patch;
fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2;
INT32 heightsec, phs;
fixed_t scalemul;
fixed_t floordiff;
fixed_t groundz;
pslope_t *groundslope;
boolean isflipped = thing->eflags & MFE_VERTICALFLIP;
interpmobjstate_t interp = {0};
groundz = R_GetShadowZ(thing, &groundslope);
@ -1526,6 +1528,28 @@ static void R_ProjectDropShadow(
R_InterpolateMobjState(thing, R_GetTimeFrac(RTF_LEVEL), &interp);
heightsec = thing->subsector->sector->heightsec;
if (viewplayer->mo && viewplayer->mo->subsector)
phs = viewplayer->mo->subsector->sector->heightsec;
else
phs = -1;
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
{
if (viewz < sectors[phs].floorheight ?
groundz >= sectors[heightsec].floorheight :
groundz < sectors[heightsec].floorheight)
return;
if (viewz > sectors[phs].ceilingheight ?
groundz < sectors[heightsec].ceilingheight && viewz >= sectors[heightsec].ceilingheight :
groundz >= sectors[heightsec].ceilingheight)
return;
}
floordiff = abs((isflipped ? interp.height : 0) + interp.z - groundz);
scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
if (shadowpatch == NULL)
{
CONS_Debug(DBG_RENDER, "Recaching shadow patch\n");
@ -1535,20 +1559,14 @@ static void R_ProjectDropShadow(
patch = shadowpatch;
xscale = FixedDiv(projection[viewssnum], tz);
yscale = FixedDiv(projectiony[viewssnum], tz);
shadowxscale = FixedMul(thing->radius*2, scale);
shadowyscale = FixedMul(FixedMul(thing->radius*2, scale), FixedDiv(abs(groundz - viewz), tz));
shadowxscale = FixedMul(interp.radius*2, scalemul);
shadowyscale = FixedMul(FixedMul(interp.radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz));
shadowyscale = std::min(shadowyscale, shadowxscale) / patch->height;
shadowxscale /= patch->width;
shadowskew = 0;
if (groundslope)
{
R_SkewShadowSprite(
thing,
groundslope, groundz,
patch->height, FRACUNIT,
&shadowyscale, &shadowskew);
}
R_SkewShadowSprite(thing, groundslope, groundz, patch->height, scalemul, &shadowyscale, &shadowskew);
tx -= patch->width * shadowxscale/2;
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
@ -1565,6 +1583,10 @@ static void R_ProjectDropShadow(
shadow->bright = NULL;
shadow->heightsec = vis->heightsec;
shadow->thingheight = FRACUNIT;
shadow->pz = groundz + (isflipped ? -shadow->thingheight : 0);
shadow->pzt = shadow->pz + shadow->thingheight;
shadow->mobjflags = 0;
shadow->renderflags = 0;
shadow->floorclip = 0;
@ -1572,9 +1594,11 @@ static void R_ProjectDropShadow(
shadow->dispoffset = vis->dispoffset - 5;
shadow->gx = interp.x;
shadow->gy = interp.y;
shadow->gzt = groundz + patch->height * shadowyscale / 2;
shadow->gzt = (isflipped ? shadow->pzt : shadow->pz) + patch->height * shadowyscale / 2;
shadow->gz = shadow->gzt - patch->height * shadowyscale;
shadow->texturemid = FixedMul(interp.scale, FixedDiv(shadow->gzt - viewz, shadowyscale));
if (thing->skin && ((skin_t *)thing->skin)->highresscale != FRACUNIT)
shadow->texturemid = FixedMul(shadow->texturemid, ((skin_t *)thing->skin)->highresscale);
shadow->scalestep = 0;
shadow->shear.tan = shadowskew; // repurposed variable