From 5db4bff19cb6a69ce4c84f2b04b4054ca050bf92 Mon Sep 17 00:00:00 2001 From: Jaime Ita Passos Date: Tue, 12 Oct 2021 14:10:48 -0300 Subject: [PATCH] Fix slope planes not being able to render fog --- src/r_draw.c | 33 ++++++++++ src/r_draw.h | 4 +- src/r_draw8.c | 92 ++++++++-------------------- src/r_draw8_npo2.c | 48 ++------------- src/r_plane.c | 147 +++++++++++++++++++++++++++++++++------------ src/screen.c | 2 +- src/screen.h | 1 + 7 files changed, 173 insertions(+), 154 deletions(-) diff --git a/src/r_draw.c b/src/r_draw.c index f0a19a462..ac6d67bc7 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -883,6 +883,39 @@ void R_DrawViewBorder(void) } #endif +// R_CalcTiltedLighting +// Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly. +static INT32 tiltlighting[MAXVIDWIDTH]; + +static void R_CalcTiltedLighting(fixed_t start, fixed_t end) +{ + // ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version + // of this function. Here's my own. + INT32 left = ds_x1, right = ds_x2; + fixed_t step = (end-start)/(ds_x2-ds_x1+1); + INT32 i; + + // I wanna do some optimizing by checking for out-of-range segments on either side to fill in all at once, + // but I'm too bad at coding to not crash the game trying to do that. I guess this is fast enough for now... + + for (i = left; i <= right; i++) { + tiltlighting[i] = (start += step) >> FRACBITS; + if (tiltlighting[i] < 0) + tiltlighting[i] = 0; + else if (tiltlighting[i] >= MAXLIGHTSCALE) + tiltlighting[i] = MAXLIGHTSCALE-1; + } +} + +// Lighting is simple. It's just linear interpolation from start to end +#define CALC_SLOPE_LIGHT { \ + float planelightfloat = PLANELIGHTFLOAT; \ + float lightstart, lightend; \ + lightend = (iz + ds_szp->x*width) * planelightfloat; \ + lightstart = iz * planelightfloat; \ + R_CalcTiltedLighting(FloatToFixed(lightstart), FloatToFixed(lightend)); \ +} + // ========================================================================== // INCLUDE 8bpp DRAWING CODE HERE // ========================================================================== diff --git a/src/r_draw.h b/src/r_draw.h index 2173c7a5a..823fb4839 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -193,13 +193,11 @@ void R_DrawTranslucentFloorSprite_8(void); void R_DrawTiltedFloorSprite_8(void); void R_DrawTiltedTranslucentFloorSprite_8(void); -void R_CalcTiltedLighting(fixed_t start, fixed_t end); -extern INT32 tiltlighting[MAXVIDWIDTH]; - void R_DrawTranslucentWaterSpan_8(void); void R_DrawTiltedTranslucentWaterSpan_8(void); void R_DrawFogSpan_8(void); +void R_DrawTiltedFogSpan_8(void); // Lactozilla: Non-powers-of-two void R_DrawSpan_NPO2_8(void); diff --git a/src/r_draw8.c b/src/r_draw8.c index b8a63d5c0..c7209fa3e 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -623,29 +623,6 @@ void R_DrawSpan_8 (void) } } -// R_CalcTiltedLighting -// Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly. -INT32 tiltlighting[MAXVIDWIDTH]; -void R_CalcTiltedLighting(fixed_t start, fixed_t end) -{ - // ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version - // of this function. Here's my own. - INT32 left = ds_x1, right = ds_x2; - fixed_t step = (end-start)/(ds_x2-ds_x1+1); - INT32 i; - - // I wanna do some optimizing by checking for out-of-range segments on either side to fill in all at once, - // but I'm too bad at coding to not crash the game trying to do that. I guess this is fast enough for now... - - for (i = left; i <= right; i++) { - tiltlighting[i] = (start += step) >> FRACBITS; - if (tiltlighting[i] < 0) - tiltlighting[i] = 0; - else if (tiltlighting[i] >= MAXLIGHTSCALE) - tiltlighting[i] = MAXLIGHTSCALE-1; - } -} - /** \brief The R_DrawTiltedSpan_8 function Draw slopes! Holy sheit! */ @@ -668,17 +645,7 @@ void R_DrawTiltedSpan_8(void) iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds_szp->x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } + CALC_SLOPE_LIGHT uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); @@ -801,17 +768,7 @@ void R_DrawTiltedTranslucentSpan_8(void) iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds_szp->x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } + CALC_SLOPE_LIGHT uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); @@ -934,17 +891,7 @@ void R_DrawTiltedTranslucentWaterSpan_8(void) iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds_szp->x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } + CALC_SLOPE_LIGHT uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); @@ -1066,17 +1013,7 @@ void R_DrawTiltedSplat_8(void) iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds_szp->x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } + CALC_SLOPE_LIGHT uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); @@ -2034,6 +1971,27 @@ void R_DrawFogSpan_8(void) } } +/** \brief The R_DrawTiltedFogSpan_8 function + Draws a tilted span with fogging. +*/ +void R_DrawTiltedFogSpan_8(void) +{ + int width = ds_x2 - ds_x1; + + UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1]; + + double iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + + CALC_SLOPE_LIGHT + + do + { + UINT8 *colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = colormap[*dest]; + dest++; + } while (--width >= 0); +} + /** \brief The R_DrawFogColumn_8 function Fog wall. */ diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 71ec99948..656e1b098 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -111,17 +111,7 @@ void R_DrawTiltedSpan_NPO2_8(void) iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds_szp->x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } + CALC_SLOPE_LIGHT uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); @@ -311,17 +301,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds_szp->x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } + CALC_SLOPE_LIGHT uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); @@ -509,17 +489,7 @@ void R_DrawTiltedSplat_NPO2_8(void) iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds_szp->x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } + CALC_SLOPE_LIGHT uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); @@ -1427,17 +1397,7 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); - // Lighting is simple. It's just linear interpolation from start to end - { - float planelightfloat = PLANELIGHTFLOAT; - float lightstart, lightend; - - lightend = (iz + ds_szp->x*width) * planelightfloat; - lightstart = iz * planelightfloat; - - R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); - //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); - } + CALC_SLOPE_LIGHT uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); diff --git a/src/r_plane.c b/src/r_plane.c index d844048ae..d900313f6 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -262,6 +262,61 @@ static void R_MapTiltedPlane(INT32 y, INT32 x1, INT32 x2) spanfunc(); } +static void R_MapFogPlane(INT32 y, INT32 x1, INT32 x2) +{ + fixed_t distance; + size_t pindex; + +#ifdef RANGECHECK + if (x2 < x1 || x1 < 0 || x2 >= viewwidth || y > viewheight) + I_Error("R_MapFogPlane: %d, %d at %d", x1, x2, y); +#endif + + if (x1 >= vid.width) + x1 = vid.width - 1; + + if (planeheight != cachedheight[y]) + distance = FixedMul(planeheight, yslope[y]); + else + distance = cacheddistance[y]; + + pindex = distance >> LIGHTZSHIFT; + if (pindex >= MAXLIGHTZ) + pindex = MAXLIGHTZ - 1; + + ds_colormap = planezlight[pindex]; + if (currentplane->extra_colormap) + ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps); + + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + + spanfunc(); +} + +static void R_MapTiltedFogPlane(INT32 y, INT32 x1, INT32 x2) +{ +#ifdef RANGECHECK + if (x2 < x1 || x1 < 0 || x2 >= viewwidth || y > viewheight) + I_Error("R_MapTiltedFogPlane: %d, %d at %d", x1, x2, y); +#endif + + if (x1 >= vid.width) + x1 = vid.width - 1; + + if (currentplane->extra_colormap) + ds_colormap = currentplane->extra_colormap->colormap; + else + ds_colormap = colormaps; + + ds_y = y; + ds_x1 = x1; + ds_x2 = x2; + + spanfunc(); +} + void R_ClearFFloorClips (void) { INT32 i, p; @@ -791,11 +846,11 @@ static inline void R_AdjustSlopeCoordinatesNPO2(vector3_t *origin) void R_DrawSinglePlane(visplane_t *pl) { - levelflat_t *levelflat; INT32 light = 0; INT32 x, stop; ffloor_t *rover; - INT32 type, spanfunctype = BASEDRAWFUNC; + boolean fog = false; + INT32 spanfunctype = BASEDRAWFUNC; void (*mapfunc)(INT32, INT32, INT32) = R_MapPlane; if (!(pl->minx <= pl->maxx)) @@ -885,6 +940,7 @@ void R_DrawSinglePlane(visplane_t *pl) } else if (pl->ffloor->flags & FF_FOG) { + fog = true; spanfunctype = SPANDRAWFUNC_FOG; light = (pl->lightlevel >> LIGHTSEGSHIFT); } @@ -892,28 +948,28 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->ffloor->flags & FF_RIPPLE) { - INT32 top, bottom; - planeripple.active = true; if (spanfunctype == SPANDRAWFUNC_TRANS) { - spanfunctype = SPANDRAWFUNC_WATER; - // Copy the current scene, ugh - top = pl->high-8; - bottom = pl->low+8; + INT32 top = pl->high-8; + INT32 bottom = pl->low+8; if (top < 0) top = 0; if (bottom > vid.height) bottom = vid.height; + spanfunctype = SPANDRAWFUNC_WATER; + // Only copy the part of the screen we need VID_BlitLinearScreen((splitscreen && viewplayer == &players[secondarydisplayplayer]) ? screens[0] + (top+(vid.height>>1))*vid.width : screens[0]+((top)*vid.width), screens[1]+((top)*vid.width), vid.width, bottom-top, vid.width, vid.width); } + else if (fog) + planeripple.active = false; } } else @@ -921,35 +977,40 @@ void R_DrawSinglePlane(visplane_t *pl) } currentplane = pl; - levelflat = &levelflats[pl->picnum]; - /* :james: */ - type = levelflat->type; - switch (type) + if (!fog) { - case LEVELFLAT_NONE: - return; - case LEVELFLAT_FLAT: - ds_source = (UINT8 *)R_GetFlat(levelflat->u.flat.lumpnum); - R_CheckFlatLength(W_LumpLength(levelflat->u.flat.lumpnum)); - // Raw flats always have dimensions that are powers-of-two numbers. - ds_powersoftwo = true; - break; - default: - ds_source = (UINT8 *)R_GetLevelFlat(levelflat); - if (!ds_source) + levelflat_t *levelflat = &levelflats[pl->picnum]; + + /* :james: */ + switch (levelflat->type) + { + case LEVELFLAT_NONE: return; - // Check if this texture or patch has power-of-two dimensions. - if (R_CheckPowersOfTwo()) - R_CheckFlatLength(ds_flatwidth * ds_flatheight); - } + case LEVELFLAT_FLAT: + ds_source = (UINT8 *)R_GetFlat(levelflat->u.flat.lumpnum); + R_CheckFlatLength(W_LumpLength(levelflat->u.flat.lumpnum)); + // Raw flats always have dimensions that are powers-of-two numbers. + ds_powersoftwo = true; + break; + default: + ds_source = (UINT8 *)R_GetLevelFlat(levelflat); + if (!ds_source) + return; + // Check if this texture or patch has power-of-two dimensions. + if (R_CheckPowersOfTwo()) + R_CheckFlatLength(ds_flatwidth * ds_flatheight); + } - if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later - && viewangle != pl->viewangle+pl->plangle) - { - memset(cachedheight, 0, sizeof (cachedheight)); - viewangle = pl->viewangle+pl->plangle; + if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later + && viewangle != pl->viewangle+pl->plangle) + { + memset(cachedheight, 0, sizeof (cachedheight)); + viewangle = pl->viewangle+pl->plangle; + } } + else + mapfunc = R_MapFogPlane; xoffs = pl->xoffs; yoffs = pl->yoffs; @@ -962,14 +1023,19 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->slope) { - mapfunc = R_MapTiltedPlane; - - if (!pl->plangle) + if (fog) + mapfunc = R_MapTiltedFogPlane; + else { - if (ds_powersoftwo) - R_AdjustSlopeCoordinates(&pl->slope->o); - else - R_AdjustSlopeCoordinatesNPO2(&pl->slope->o); + mapfunc = R_MapTiltedPlane; + + if (!pl->plangle) + { + if (ds_powersoftwo) + R_AdjustSlopeCoordinates(&pl->slope->o); + else + R_AdjustSlopeCoordinatesNPO2(&pl->slope->o); + } } if (planeripple.active) @@ -999,6 +1065,9 @@ void R_DrawSinglePlane(visplane_t *pl) case SPANDRAWFUNC_SPLAT: spanfunctype = SPANDRAWFUNC_TILTEDSPLAT; break; + case SPANDRAWFUNC_FOG: + spanfunctype = SPANDRAWFUNC_TILTEDFOG; + break; default: spanfunctype = SPANDRAWFUNC_TILTED; break; diff --git a/src/screen.c b/src/screen.c index 770f1c802..ead2590ac 100644 --- a/src/screen.c +++ b/src/screen.c @@ -139,6 +139,7 @@ void SCR_SetDrawFuncs(void) spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8; spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_8; spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8; + spanfuncs[SPANDRAWFUNC_TILTEDFOG] = R_DrawTiltedFogSpan_8; // Lactozilla: Non-powers-of-two spanfuncs_npo2[BASEDRAWFUNC] = R_DrawSpan_NPO2_8; @@ -154,7 +155,6 @@ void SCR_SetDrawFuncs(void) spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8; - spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed #ifdef RUSEASM if (R_ASM) diff --git a/src/screen.h b/src/screen.h index 67880e2b9..993178561 100644 --- a/src/screen.h +++ b/src/screen.h @@ -156,6 +156,7 @@ enum SPANDRAWFUNC_TILTEDWATER, SPANDRAWFUNC_FOG, + SPANDRAWFUNC_TILTEDFOG, SPANDRAWFUNC_MAX };