From 09bfc6506a1c5a5e573b76759f5cf4cb06ed7ed5 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Sun, 7 Dec 2025 20:32:18 -0500 Subject: [PATCH] Update shadow code Thing brings over scale based on object height and interp amoung other things. --- src/hardware/hw_main.c | 50 ++++++++++++++++++++++++++---------------- src/r_fps.c | 2 ++ src/r_things.cpp | 50 +++++++++++++++++++++++++++++++----------- 3 files changed, 70 insertions(+), 32 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index d6f7d8c5f..03a56f94b 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -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; } } diff --git a/src/r_fps.c b/src/r_fps.c index 2e4128182..5a1936f98 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -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 { diff --git a/src/r_things.cpp b/src/r_things.cpp index e2bc281a7..47a56fb0a 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -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