Make 3D floors cull areas below or above them to reduce overdraw (2)

This commit is contained in:
Jaime Passos 2020-10-10 01:00:39 -03:00
parent 15008f31a7
commit c5a3a61b28
3 changed files with 118 additions and 21 deletions

View File

@ -151,6 +151,7 @@ consvar_t cv_flipcam2 = CVAR_INIT ("flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT,
consvar_t cv_shadow = CVAR_INIT ("shadow", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_skybox = CVAR_INIT ("skybox", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_ffloorclip = CVAR_INIT ("ffloorclip", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_allowmlook = CVAR_INIT ("allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL);
consvar_t cv_showhud = CVAR_INIT ("showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize);
consvar_t cv_translucenthud = CVAR_INIT ("translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL);
@ -1615,6 +1616,7 @@ void R_RegisterEngineStuff(void)
CV_RegisterVar(&cv_shadow);
CV_RegisterVar(&cv_skybox);
CV_RegisterVar(&cv_ffloorclip);
CV_RegisterVar(&cv_cam_dist);
CV_RegisterVar(&cv_cam_still);

View File

@ -107,6 +107,7 @@ extern consvar_t cv_chasecam, cv_chasecam2;
extern consvar_t cv_flipcam, cv_flipcam2;
extern consvar_t cv_shadow;
extern consvar_t cv_ffloorclip;
extern consvar_t cv_translucency;
extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip;
extern consvar_t cv_fov;

View File

@ -55,6 +55,15 @@ static INT32 worldtop, worldbottom, worldhigh, worldlow;
static INT32 worldtopslope, worldbottomslope, worldhighslope, worldlowslope; // worldtop/bottom at end of slope
static fixed_t rw_toptextureslide, rw_midtextureslide, rw_bottomtextureslide; // Defines how to adjust Y offsets along the wall for slopes
static fixed_t rw_midtextureback, rw_midtexturebackslide; // Values for masked midtexture height calculation
// Lactozilla: 3D floor clipping
static boolean rw_floormarked = false;
static boolean rw_ceilingmarked = false;
static INT32 *rw_silhouette = NULL;
static fixed_t *rw_tsilheight = NULL;
static fixed_t *rw_bsilheight = NULL;
static fixed_t pixhigh, pixlow, pixhighstep, pixlowstep;
static fixed_t topfrac, topstep;
static fixed_t bottomfrac, bottomstep;
@ -686,6 +695,19 @@ static void R_DrawRepeatFlippedMaskedColumn(column_t *col)
} while (sprtopscreen < sprbotscreen);
}
// Returns true if a fake floor is translucent.
static boolean R_IsFFloorTranslucent(visffloor_t *pfloor)
{
if (pfloor->polyobj)
return (pfloor->polyobj->translucency > 0);
// Polyobjects have no ffloors, and they're handled in the conditional above.
if (pfloor->ffloor != NULL)
return (pfloor->ffloor->flags & FF_TRANSLUCENT);
return false;
}
//
// R_RenderThickSideRange
// Renders all the thick sides in the given range.
@ -1188,7 +1210,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// R_ExpandPlaneY
//
// A simple function to modify a vsplane's top and bottom for a particular column
// A simple function to modify a visplane's top and bottom for a particular column
// Sort of like R_ExpandPlane in r_plane.c, except this is vertical expansion
static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bottom)
{
@ -1198,6 +1220,14 @@ static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bott
if (pl->bottom[x] < bottom) pl->bottom[x] = bottom;
}
// R_FFloorCanClip
//
// Returns true if a fake floor can clip a column away.
static boolean R_FFloorCanClip(visffloor_t *pfloor)
{
return (cv_ffloorclip.value && !R_IsFFloorTranslucent(pfloor) && !pfloor->polyobj);
}
//
// R_RenderSegLoop
// Draws zero, one, or two textures (and possibly a masked
@ -1281,6 +1311,11 @@ static void R_RenderSegLoop (void)
if (numffloors)
{
INT16 fftop, ffbottom;
rw_floormarked = false;
rw_ceilingmarked = false;
firstseg->frontscale[rw_x] = frontscale[rw_x];
top = ceilingclip[rw_x]+1; // PRBoom
bottom = floorclip[rw_x]-1; // PRBoom
@ -1311,8 +1346,30 @@ static void R_RenderSegLoop (void)
{
if (top_w <= bottom_w)
{
ffloor[i].plane->top[rw_x] = (INT16)top_w;
ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w;
fftop = (INT16)top_w;
ffbottom = (INT16)bottom_w;
ffloor[i].plane->top[rw_x] = fftop;
ffloor[i].plane->bottom[rw_x] = ffbottom;
// Lactozilla: Cull part of the column by the 3D floor if it can't be seen
// "bottom" is the top pixel of the floor column
if (ffbottom >= bottom-1 && R_FFloorCanClip(&ffloor[i]))
{
rw_floormarked = true;
floorclip[rw_x] = fftop;
if (yh > fftop)
yh = fftop;
if (markfloor && floorplane)
floorplane->top[rw_x] = bottom;
if (rw_silhouette)
{
(*rw_silhouette) |= SIL_BOTTOM;
(*rw_bsilheight) = INT32_MAX;
}
}
}
}
}
@ -1337,8 +1394,30 @@ static void R_RenderSegLoop (void)
{
if (top_w <= bottom_w)
{
ffloor[i].plane->top[rw_x] = (INT16)top_w;
ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w;
fftop = (INT16)top_w;
ffbottom = (INT16)bottom_w;
ffloor[i].plane->top[rw_x] = fftop;
ffloor[i].plane->bottom[rw_x] = ffbottom;
// Lactozilla: Cull part of the column by the 3D floor if it can't be seen
// "top" is the height of the ceiling column
if (fftop <= top+1 && R_FFloorCanClip(&ffloor[i]))
{
rw_ceilingmarked = true;
ceilingclip[rw_x] = ffbottom;
if (yl < ffbottom)
yl = ffbottom;
if (markceiling && ceilingplane)
ceilingplane->bottom[rw_x] = top;
if (rw_silhouette)
{
(*rw_silhouette) |= SIL_TOP;
(*rw_tsilheight) = INT32_MIN;
}
}
}
}
}
@ -1444,20 +1523,25 @@ static void R_RenderSegLoop (void)
// dont draw anything more for this column, since
// a midtexture blocks the view
ceilingclip[rw_x] = (INT16)viewheight;
floorclip[rw_x] = -1;
if (!rw_ceilingmarked)
ceilingclip[rw_x] = (INT16)viewheight;
if (!rw_floormarked)
floorclip[rw_x] = -1;
}
else
{
// note: don't use min/max macros, since casting from INT32 to INT16 is involved here
if (markceiling)
if (markceiling && (!rw_ceilingmarked))
ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
if (markfloor)
if (markfloor && (!rw_floormarked))
floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
}
}
else
{
INT16 topclip = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
INT16 bottomclip = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
// two sided line
if (toptexture)
{
@ -1471,7 +1555,10 @@ static void R_RenderSegLoop (void)
if (mid >= yl) // back ceiling lower than front ceiling ?
{
if (yl >= viewheight) // entirely off bottom of screen
ceilingclip[rw_x] = (INT16)viewheight;
{
if (!rw_ceilingmarked)
ceilingclip[rw_x] = (INT16)viewheight;
}
else if (mid >= 0) // safe to draw top texture
{
dc_yl = yl;
@ -1482,14 +1569,14 @@ static void R_RenderSegLoop (void)
colfunc();
ceilingclip[rw_x] = (INT16)mid;
}
else // entirely off top of screen
else if (!rw_ceilingmarked) // entirely off top of screen
ceilingclip[rw_x] = -1;
}
else
ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
else if (!rw_ceilingmarked)
ceilingclip[rw_x] = topclip;
}
else if (markceiling) // no top wall
ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1;
else if (markceiling && (!rw_ceilingmarked)) // no top wall
ceilingclip[rw_x] = topclip;
if (bottomtexture)
{
@ -1504,7 +1591,10 @@ static void R_RenderSegLoop (void)
if (mid <= yh) // back floor higher than front floor ?
{
if (yh < 0) // entirely off top of screen
floorclip[rw_x] = -1;
{
if (!rw_floormarked)
floorclip[rw_x] = -1;
}
else if (mid < viewheight) // safe to draw bottom texture
{
dc_yl = mid;
@ -1516,14 +1606,14 @@ static void R_RenderSegLoop (void)
colfunc();
floorclip[rw_x] = (INT16)mid;
}
else // entirely off bottom of screen
else if (!rw_floormarked) // entirely off bottom of screen
floorclip[rw_x] = (INT16)viewheight;
}
else
floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
else if (!rw_floormarked)
floorclip[rw_x] = bottomclip;
}
else if (markfloor) // no bottom wall
floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight;
else if (markfloor && (!rw_floormarked)) // no bottom wall
floorclip[rw_x] = bottomclip;
}
if (maskedtexture || numthicksides)
@ -2786,6 +2876,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
}
}
rw_silhouette = &(ds_p->silhouette);
rw_tsilheight = &(ds_p->tsilheight);
rw_bsilheight = &(ds_p->bsilheight);
#ifdef WALLSPLATS
if (linedef->splats && cv_splats.value)
{