Undo clipsegs optimization

This commit is contained in:
Lactozilla 2024-05-20 21:06:31 -03:00
parent e22ea1f2e9
commit 5f5fff7e58
4 changed files with 162 additions and 99 deletions

View file

@ -52,66 +52,164 @@ void R_ClearDrawSegs(void)
ds_p = drawsegs; ds_p = drawsegs;
} }
// CPhipps - // Fix from boom.
// Instead of clipsegs, let's try using an array with one entry for each column, #define MAXSEGS (MAXVIDWIDTH/2+1)
// indicating whether it's blocked by a solid wall yet or not.
UINT8 solidcol[MAXVIDWIDTH]; // newend is one past the last valid seg
static cliprange_t *newend;
static cliprange_t solidsegs[MAXSEGS];
// CPhipps -
// R_ClipWallSegment
// //
// Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those // R_ClipSolidWallSegment
// columns which aren't solid, and updates the solidcol[] array appropriately // Does handle solid walls,
static void R_ClipWallSegment(INT32 first, INT32 last, boolean solid) // e.g. single sided LineDefs (middle texture)
// that entirely block the view.
//
static void R_ClipSolidWallSegment(INT32 first, INT32 last)
{ {
while (first < last) cliprange_t *next;
cliprange_t *start;
// Find the first range that touches the range (adjacent pixels are touching).
start = solidsegs;
while (start->last < first - 1)
start++;
if (first < start->first)
{ {
UINT8 *p; if (last < start->first - 1)
if (solidcol[first])
{ {
p = memchr(solidcol+first, 0, last-first); // Post is entirely visible (above start), so insert a new clippost.
if (!p) R_StoreWallRange(first, last);
return; // All solid next = newend;
newend++;
// NO MORE CRASHING!
if (newend - solidsegs > MAXSEGS)
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
first = p - solidcol; while (next != start)
{
*next = *(next-1);
next--;
}
next->first = first;
next->last = last;
return;
} }
else
// There is a fragment above *start.
R_StoreWallRange(first, start->first - 1);
// Now adjust the clip size.
start->first = first;
}
// Bottom contained in start?
if (last <= start->last)
return;
next = start;
while (last >= (next+1)->first - 1)
{
// There is a fragment between two posts.
R_StoreWallRange(next->last + 1, (next+1)->first - 1);
next++;
if (last <= next->last)
{ {
p = memchr(solidcol+first, 1, last-first); // Bottom is contained in next.
// Adjust the clip size.
int to; start->last = next->last;
if (!p) goto crunch;
to = last;
else
to = p - solidcol;
R_StoreWallRange(first, to-1);
if (solid)
memset(solidcol+first, 1, to-first);
first = to;
} }
} }
// There is a fragment after *next.
R_StoreWallRange(next->last + 1, last);
// Adjust the clip size.
start->last = last;
// Remove start+1 to next from the clip list, because start now covers their area.
crunch:
if (next == start)
return; // Post just extended past the bottom of one post.
while (next++ != newend)
*++start = *next; // Remove a post.
newend = start + 1;
// NO MORE CRASHING!
if (newend - solidsegs > MAXSEGS)
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
} }
//
// R_ClipPassWallSegment
// Clips the given range of columns, but does not include it in the clip list.
// Does handle windows, e.g. LineDefs with upper and lower texture.
//
static inline void R_ClipPassWallSegment(INT32 first, INT32 last)
{
cliprange_t *start;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = solidsegs;
while (start->last < first - 1)
start++;
if (first < start->first)
{
if (last < start->first - 1)
{
// Post is entirely visible (above start).
R_StoreWallRange(first, last);
return;
}
// There is a fragment above *start.
R_StoreWallRange(first, start->first - 1);
}
// Bottom contained in start?
if (last <= start->last)
return;
while (last >= (start+1)->first - 1)
{
// There is a fragment between two posts.
R_StoreWallRange(start->last + 1, (start+1)->first - 1);
start++;
if (last <= start->last)
return;
}
// There is a fragment after *next.
R_StoreWallRange(start->last + 1, last);
}
//
// R_ClearClipSegs
//
void R_ClearClipSegs(void) void R_ClearClipSegs(void)
{ {
memset(solidcol, 0, viewwidth); solidsegs[0].first = -0x7fffffff;
solidsegs[0].last = -1;
solidsegs[1].first = viewwidth;
solidsegs[1].last = 0x7fffffff;
newend = solidsegs + 2;
} }
void R_PortalClearClipSegs(INT32 start, INT32 end) void R_PortalClearClipSegs(INT32 start, INT32 end)
{ {
R_ClearClipSegs(); solidsegs[0].first = -0x7fffffff;
solidsegs[0].last = start-1;
for (INT32 x = 0; x < start; x++) solidsegs[1].first = end;
solidcol[x] = 1; solidsegs[1].last = 0x7fffffff;
newend = solidsegs + 2;
for (INT32 x = end; x < viewwidth; x++)
solidcol[x] = 1;
} }
// R_DoorClosed // R_DoorClosed
// //
// This function is used to fix the automap bug which // This function is used to fix the automap bug which
@ -517,11 +615,11 @@ static void R_AddLine(seg_t *line)
return; return;
clippass: clippass:
R_ClipWallSegment(x1, x2, false); R_ClipPassWallSegment(x1, x2 - 1);
return; return;
clipsolid: clipsolid:
R_ClipWallSegment(x1, x2, true); R_ClipSolidWallSegment(x1, x2 - 1);
} }
// //
@ -554,23 +652,10 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
angle_t angle1, angle2; angle_t angle1, angle2;
INT32 sx1, sx2, boxpos; INT32 sx1, sx2, boxpos;
const INT32* check; const INT32* check;
cliprange_t *start;
// Find the corners of the box that define the edges from current viewpoint. // Find the corners of the box that define the edges from current viewpoint.
if (viewx <= bspcoord[BOXLEFT]) if ((boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT] ? 1 : 2) + (viewy >= bspcoord[BOXTOP] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8)) == 5)
boxpos = 0;
else if (viewx < bspcoord[BOXRIGHT])
boxpos = 1;
else
boxpos = 2;
if (viewy >= bspcoord[BOXTOP])
boxpos |= 0;
else if (viewy > bspcoord[BOXBOTTOM])
boxpos |= 1<<2;
else
boxpos |= 2<<2;
if (boxpos == 5)
return true; return true;
check = checkcoord[boxpos]; check = checkcoord[boxpos];
@ -599,14 +684,14 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
sx2 = viewangletox[angle2]; sx2 = viewangletox[angle2];
// Does not cross a pixel. // Does not cross a pixel.
if (sx1 >= sx2) if (sx1 >= sx2) return false;
return false;
if (!memchr(solidcol+sx1, 0, sx2-sx1)) start = solidsegs;
{ while (start->last < sx2)
// All columns it covers are already solidly covered start++;
return false;
} if (sx1 >= start->first && sx2 <= start->last)
return false; // The clippost contains the new span.
return true; return true;
} }
@ -1313,7 +1398,7 @@ void R_RenderPortalHorizonLine(sector_t *sector)
firstseg = NULL; firstseg = NULL;
curline = &segs[0]; curline = &segs[0];
R_ClipWallSegment(portalclipstart, portalclipend, true); R_ClipSolidWallSegment(portalclipstart, portalclipend);
curline = NULL; curline = NULL;
} }

View file

@ -38,8 +38,6 @@ extern boolean horizonline;
extern INT32 doorclosed; extern INT32 doorclosed;
extern UINT8 solidcol[MAXVIDWIDTH];
// BSP? // BSP?
void R_ClearClipSegs(void); void R_ClearClipSegs(void);
void R_PortalClearClipSegs(INT32 start, INT32 end); void R_PortalClearClipSegs(INT32 start, INT32 end);

View file

@ -31,6 +31,17 @@
#include "taglist.h" #include "taglist.h"
//
// ClipWallSegment
// Clips the given range of columns
// and includes it in the new clip list.
//
typedef struct
{
INT32 first;
INT32 last;
} cliprange_t;
// Silhouette, needed for clipping segs (mainly) and sprites representing things. // Silhouette, needed for clipping segs (mainly) and sprites representing things.
#define SIL_NONE 0 #define SIL_NONE 0
#define SIL_BOTTOM 1 #define SIL_BOTTOM 1

View file

@ -994,8 +994,6 @@ static boolean R_FFloorCanClip(visffloor_t *pfloor)
return (cv_ffloorclip.value && !R_IsFFloorTranslucent(pfloor) && !pfloor->polyobj); return (cv_ffloorclip.value && !R_IsFFloorTranslucent(pfloor) && !pfloor->polyobj);
} }
static boolean didsolidcol; // True if at least one column was marked solid
// //
// R_RenderSegLoop // R_RenderSegLoop
// Draws zero, one, or two textures (and possibly a masked // Draws zero, one, or two textures (and possibly a masked
@ -1437,12 +1435,6 @@ static void R_RenderSegLoop (void)
floorclip[rw_x] = bottomclip; floorclip[rw_x] = bottomclip;
} }
if ((markceiling || markfloor) && (floorclip[rw_x] <= ceilingclip[rw_x] + 1))
{
solidcol[rw_x] = 1;
didsolidcol = true;
}
if (maskedtexturecol) if (maskedtexturecol)
maskedtexturecol[rw_x] = texturecolumn + rw_offsetx; maskedtexturecol[rw_x] = texturecolumn + rw_offsetx;
@ -1565,12 +1557,6 @@ static void R_MarkSegBounds(void)
if (markfloor) // no bottom wall if (markfloor) // no bottom wall
floorclip[rw_x] = bottomclip; floorclip[rw_x] = bottomclip;
if (floorclip[rw_x] <= ceilingclip[rw_x] + 1)
{
solidcol[rw_x] = 1;
didsolidcol = true;
}
rw_scale += rw_scalestep; rw_scale += rw_scalestep;
topfrac += topstep; topfrac += topstep;
bottomfrac += bottomstep; bottomfrac += bottomstep;
@ -2954,8 +2940,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
} }
} }
didsolidcol = false;
if (!segtextured && !numffloors && !numbackffloors) if (!segtextured && !numffloors && !numbackffloors)
{ {
if (markfloor || markceiling) if (markfloor || markceiling)
@ -2985,21 +2969,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
else else
ds_p->portalpass = 0; ds_p->portalpass = 0;
// cph - if a column was made solid by this wall, we _must_ save full clipping info
if (backsector && didsolidcol)
{
if (!(ds_p->silhouette & SIL_BOTTOM))
{
ds_p->silhouette |= SIL_BOTTOM;
ds_p->bsilheight = backsector->f_slope ? INT32_MAX : backsector->floorheight;
}
if (!(ds_p->silhouette & SIL_TOP))
{
ds_p->silhouette |= SIL_TOP;
ds_p->tsilheight = backsector->c_slope ? INT32_MIN : backsector->ceilingheight;
}
}
// save sprite clipping info // save sprite clipping info
if (maskedtexture || (ds_p->silhouette & (SIL_TOP | SIL_BOTTOM))) if (maskedtexture || (ds_p->silhouette & (SIL_TOP | SIL_BOTTOM)))
{ {