Thick stuff. Hoping I didn't break anything.

This commit is contained in:
Jaime Passos 2019-12-26 17:15:30 -03:00
parent 5f1e3bab71
commit 919864d0f3
2 changed files with 386 additions and 331 deletions

View File

@ -2360,14 +2360,13 @@ static void R_DrawWallSplats(void)
// way we don't have to store extra post_t info with each column for // way we don't have to store extra post_t info with each column for
// multi-patch textures. They are not normally needed as multi-patch // multi-patch textures. They are not normally needed as multi-patch
// textures don't have holes in it. At least not for now. // textures don't have holes in it. At least not for now.
static INT32 column2s_length; // column->length : for multi-patch on 2sided wall = texture->height
static void R_Render2sidedMultiPatchColumn(column_t *column) static void R_Render2sidedMultiPatchColumn(column_t *column)
{ {
INT32 topscreen, bottomscreen; INT32 topscreen, bottomscreen;
topscreen = sprtopscreen; // + spryscale*column->topdelta; topdelta is 0 for the wall topscreen = sprtopscreen; // + spryscale*column->topdelta; topdelta is 0 for the wall
bottomscreen = topscreen + spryscale * column2s_length; bottomscreen = topscreen + spryscale * rw.column2s_length;
dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS;
@ -2403,7 +2402,7 @@ static void R_Render2sidedMultiPatchColumn(column_t *column)
// uses column2s_length for texture->height as above // uses column2s_length for texture->height as above
static void R_DrawFlippedMaskedSegColumn(column_t *column) static void R_DrawFlippedMaskedSegColumn(column_t *column)
{ {
R_DrawFlippedMaskedColumn(column, column2s_length); R_DrawFlippedMaskedColumn(column, rw.column2s_length);
} }
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
@ -2414,7 +2413,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
fixed_t height, realbot; fixed_t height, realbot;
lightlist_t *light; lightlist_t *light;
r_lightlist_t *rlight; r_lightlist_t *rlight;
void (*colfunc_2s)(column_t *);
line_t *ldef; line_t *ldef;
sector_t *front, *back; sector_t *front, *back;
INT32 times, repeats; INT32 times, repeats;
@ -2483,16 +2481,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{ {
if (textures[texnum]->flip & 2) // vertically flipped? if (textures[texnum]->flip & 2) // vertically flipped?
{ {
colfunc_2s = R_DrawFlippedMaskedSegColumn; rw.colfunc_2s = R_DrawFlippedMaskedSegColumn;
column2s_length = textures[texnum]->height; rw.column2s_length = textures[texnum]->height;
} }
else else
colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture rw.colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture
} }
else else
{ {
colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info) rw.colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info)
column2s_length = textures[texnum]->height; rw.column2s_length = textures[texnum]->height;
} }
// Setup lighting based on the presence/lack-of 3D floors. // Setup lighting based on the presence/lack-of 3D floors.
@ -2741,7 +2739,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
if (windowbottom >= realbot) if (windowbottom >= realbot)
{ {
windowbottom = realbot; windowbottom = realbot;
colfunc_2s(col); rw.colfunc_2s(col);
for (i++; i < dc_numlights; i++) for (i++; i < dc_numlights; i++)
{ {
rlight = &dc_lightlist[i]; rlight = &dc_lightlist[i];
@ -2750,13 +2748,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
continue; continue;
} }
colfunc_2s(col); rw.colfunc_2s(col);
windowtop = windowbottom + 1; windowtop = windowbottom + 1;
dc_colormap = rlight->rcolormap; dc_colormap = rlight->rcolormap;
} }
windowbottom = realbot; windowbottom = realbot;
if (windowtop < windowbottom) if (windowtop < windowbottom)
colfunc_2s(col); rw.colfunc_2s(col);
spryscale += rw.scalestep; spryscale += rw.scalestep;
continue; continue;
@ -2833,7 +2831,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
} }
else else
#endif #endif
colfunc_2s(col); rw.colfunc_2s(col);
} }
spryscale += rw.scalestep; spryscale += rw.scalestep;
} }
@ -2856,110 +2854,238 @@ static void R_DrawRepeatMaskedColumn(column_t *col)
static void R_DrawRepeatFlippedMaskedColumn(column_t *col) static void R_DrawRepeatFlippedMaskedColumn(column_t *col)
{ {
do { do {
R_DrawFlippedMaskedColumn(col, column2s_length); R_DrawFlippedMaskedColumn(col, rw.column2s_length);
sprtopscreen += dc_texheight*spryscale; sprtopscreen += dc_texheight*spryscale;
} while (sprtopscreen < sprbotscreen); } while (sprtopscreen < sprbotscreen);
} }
// //
// R_RenderThickSideRange // R_RenderThickSegLoop
// Renders all the thick sides in the given range. // Like R_RenderSegLoop, but for thick sides.
void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) //
void R_RenderThickSegLoop(void)
{ {
size_t pindex; column_t *col;
column_t * col; size_t pindex;
INT32 lightnum; INT32 i;
INT32 texnum; INT32 lightnum;
sector_t tempsec; r_lightlist_t *rlight;
INT32 templight;
INT32 i, p; ffloor_t *pfloor = rw.pfloor;
fixed_t bottombounds = viewheight << FRACBITS; fixed_t bottombounds = viewheight << FRACBITS;
fixed_t topbounds = (con_clipviewtop - 1) << FRACBITS; fixed_t topbounds = (con_clipviewtop - 1) << FRACBITS;
fixed_t offsetvalue = 0;
lightlist_t *light;
r_lightlist_t *rlight;
#ifdef ESLOPE #ifdef ESLOPE
INT32 range; INT32 oldx = -1;
#endif
#ifndef ESLOPE
fixed_t lheight;
#endif
line_t *newline = NULL;
#ifdef ESLOPE
// Render FOF sides kinda like normal sides, with the frac and step and everything
// NOTE: INT64 instead of fixed_t because overflow concerns
INT64 top_frac, top_step, bottom_frac, bottom_step;
// skew FOF walls with slopes?
boolean slopeskew = false;
fixed_t ffloortextureslide = 0;
INT32 oldx = -1;
fixed_t left_top, left_bottom; // needed here for slope skewing
pslope_t *skewslope = NULL;
#endif #endif
void (*colfunc_2s) (column_t *); for (dc_x = rw.x; dc_x <= rw.stopx; dc_x++)
// Calculate light table.
// Use different light tables
// for horizontal / vertical / diagonal. Diagonal?
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
curline = ds->curline;
backsector = pfloor->target;
frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector;
texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture);
colfunc = colfuncs[BASEDRAWFUNC];
if (pfloor->master->flags & ML_TFERLINE)
{ {
size_t linenum = curline->linedef-backsector->lines[0]; if (maskedtexturecol[dc_x] != INT16_MAX)
newline = pfloor->master->frontsector->lines[0] + linenum; {
texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
}
if (pfloor->flags & FF_TRANSLUCENT)
{
boolean fuzzy = true;
// Hacked up support for alpha value in software mode Tails 09-24-2002
if (pfloor->alpha < 12)
return; // Don't even draw it
else if (pfloor->alpha < 38)
dc_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 64)
dc_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 89)
dc_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 115)
dc_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 140)
dc_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 166)
dc_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 192)
dc_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 217)
dc_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 243)
dc_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT);
else
fuzzy = false; // Opaque
if (fuzzy)
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
}
else if (pfloor->flags & FF_FOG)
colfunc = colfuncs[COLDRAWFUNC_FOG];
#ifdef ESLOPE #ifdef ESLOPE
range = max(ds->x2-ds->x1, 1); if (rw.ffloortextureslide) { // skew FOF walls
if (oldx != -1)
dc_texturemid += FixedMul(rw.ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])<<FRACBITS);
oldx = dc_x;
}
#endif #endif
//SoM: Moved these up here so they are available for my lightlist calculations // Calculate bounds
rw.scalestep = ds->scalestep; // clamp the values if necessary to avoid overflows and rendering glitches caused by them
spryscale = ds->scale1 + (x1 - ds->x1)*rw.scalestep; #ifdef ESLOPE
#define CLAMPMAX INT32_MAX
#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out.
if (rw.top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX;
else if (rw.top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)rw.top_frac;
else sprtopscreen = windowtop = CLAMPMIN;
if (rw.bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX;
else if (rw.bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)rw.bottom_frac;
else sprbotscreen = windowbottom = CLAMPMIN;
rw.top_frac += rw.top_step;
rw.bottom_frac += rw.bottom_step;
#else
sprtopscreen = windowtop = (centeryfrac - FixedMul((dc_texturemid - offsetvalue), spryscale));
sprbotscreen = windowbottom = FixedMul(*pfloor->topheight - *pfloor->bottomheight, spryscale) + sprtopscreen;
#endif
// SoM: If column is out of range, why bother with it??
if (windowbottom < topbounds || windowtop > bottombounds)
{
if (dc_numlights)
{
for (i = 0; i < dc_numlights; i++)
{
rlight = &dc_lightlist[i];
rlight->height += rlight->heightstep;
if (rlight->flags & FF_CUTLEVEL)
rlight->botheight += rlight->botheightstep;
}
}
spryscale += rw.scalestep;
continue;
}
dc_iscale = 0xffffffffu / (unsigned)spryscale;
// Get data for the column
col = (column_t *)((UINT8 *)R_GetColumn(rw.texnum,maskedtexturecol[dc_x]) - 3);
// SoM: New code does not rely on R_DrawColumnShadowed_8 which
// will (hopefully) put less strain on the stack.
if (dc_numlights)
{
lighttable_t **xwalllights;
fixed_t height;
fixed_t bheight = 0;
INT32 solid = 0;
INT32 lighteffect = 0;
for (i = 0; i < dc_numlights; i++)
{
// Check if the current light effects the colormap/lightlevel
rlight = &dc_lightlist[i];
lighteffect = !(dc_lightlist[i].flags & FF_NOSHADE);
if (lighteffect)
{
lightnum = rlight->lightnum;
if (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE-1;
if (pfloor->flags & FF_FOG)
{
if (pfloor->master->frontsector->extra_colormap)
rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
else
rlight->rcolormap = xwalllights[pindex];
}
else
{
if (rlight->extra_colormap)
rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
else
rlight->rcolormap = xwalllights[pindex];
}
}
solid = 0; // don't carry over solid-cutting flag from the previous light
// Check if the current light can cut the current 3D floor.
if (rlight->flags & FF_CUTSOLIDS && !(pfloor->flags & FF_EXTRA))
solid = 1;
else if (rlight->flags & FF_CUTEXTRA && pfloor->flags & FF_EXTRA)
{
if (rlight->flags & FF_EXTRA)
{
// The light is from an extra 3D floor... Check the flags so
// there are no undesired cuts.
if ((rlight->flags & (FF_FOG|FF_SWIMMABLE)) == (pfloor->flags & (FF_FOG|FF_SWIMMABLE)))
solid = 1;
}
else
solid = 1;
}
else
solid = 0;
height = rlight->height;
rlight->height += rlight->heightstep;
if (solid)
{
bheight = rlight->botheight - (FRACUNIT >> 1);
rlight->botheight += rlight->botheightstep;
}
if (height <= windowtop)
{
if (lighteffect)
dc_colormap = rlight->rcolormap;
if (solid && windowtop < bheight)
windowtop = bheight;
continue;
}
windowbottom = height;
if (windowbottom >= sprbotscreen)
{
windowbottom = sprbotscreen;
// draw the texture
rw.colfunc_2s (col);
for (i++; i < dc_numlights; i++)
{
rlight = &dc_lightlist[i];
rlight->height += rlight->heightstep;
if (rlight->flags & FF_CUTLEVEL)
rlight->botheight += rlight->botheightstep;
}
continue;
}
// draw the texture
rw.colfunc_2s (col);
if (solid)
windowtop = bheight;
else
windowtop = windowbottom + 1;
if (lighteffect)
dc_colormap = rlight->rcolormap;
}
windowbottom = sprbotscreen;
// draw the texture, if there is any space left
if (windowtop < windowbottom)
rw.colfunc_2s (col);
spryscale += rw.scalestep;
continue;
}
// calculate lighting
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE - 1;
dc_colormap = walllights[pindex];
if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap)
dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
else if (frontsector->extra_colormap)
dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
// draw the texture
rw.colfunc_2s (col);
spryscale += rw.scalestep;
}
}
}
//
// R_ThickLightLists
// Creates light lists, but for thick sides.
//
static void R_ThickLightLists(drawseg_t *ds, INT32 range)
{
INT32 lightnum;
sector_t tempsec;
INT32 templight;
INT32 i, p;
lightlist_t *light;
r_lightlist_t *rlight;
ffloor_t *pfloor = rw.pfloor;
dc_numlights = 0; dc_numlights = 0;
if (frontsector->numlights) if (frontsector->numlights)
{ {
dc_numlights = frontsector->numlights; dc_numlights = frontsector->numlights;
@ -2975,6 +3101,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
fixed_t leftheight, rightheight; fixed_t leftheight, rightheight;
fixed_t pfloorleft, pfloorright; fixed_t pfloorleft, pfloorright;
INT64 overflow_test; INT64 overflow_test;
#else
(void)range;
#endif #endif
light = &frontsector->lightlist[i]; light = &frontsector->lightlist[i];
rlight = &dc_lightlist[p]; rlight = &dc_lightlist[p];
@ -3006,8 +3134,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
leftheight -= viewz; leftheight -= viewz;
rightheight -= viewz; rightheight -= viewz;
#define CLAMPMAX INT32_MAX
#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out.
// Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave. // Monster Iestyn (25/03/18): do not skip these lights if they fail overflow test, just clamp them instead so they behave.
overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS); overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS);
if (overflow_test > (INT64)CLAMPMAX) rlight->height = CLAMPMAX; if (overflow_test > (INT64)CLAMPMAX) rlight->height = CLAMPMAX;
@ -3104,6 +3230,130 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
else else
walllights = scalelight[lightnum]; walllights = scalelight[lightnum];
} }
}
//
// R_ThickStepping
// Set stepping values for thick sides.
//
#ifdef ESLOPE
static void R_ThickStepping(drawseg_t *ds, INT32 range)
{
fixed_t right_top, right_bottom;
ffloor_t *pfloor = rw.pfloor;
// calculate right ends now
if (*pfloor->t_slope)
right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
else
right_top = *pfloor->topheight - viewz;
if (*pfloor->b_slope)
right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
else
right_bottom = *pfloor->bottomheight - viewz;
// using INT64 to avoid 32bit overflow
rw.top_frac = (INT64)centeryfrac - (((INT64)rw.left_top * ds->scale1) >> FRACBITS);
rw.bottom_frac = (INT64)centeryfrac - (((INT64)rw.left_bottom * ds->scale1) >> FRACBITS);
rw.top_step = (INT64)centeryfrac - (((INT64)right_top * ds->scale2) >> FRACBITS);
rw.bottom_step = (INT64)centeryfrac - (((INT64)right_bottom * ds->scale2) >> FRACBITS);
rw.top_step = (rw.top_step-rw.top_frac)/(range);
rw.bottom_step = (rw.bottom_step-rw.bottom_frac)/(range);
rw.top_frac += rw.top_step * (rw.x - ds->x1);
rw.bottom_frac += rw.bottom_step * (rw.x - ds->x1);
}
#endif
//
// R_RenderThickSideRange
// Renders all the thick sides in the given range.
//
void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
{
INT32 texnum;
fixed_t offsetvalue = 0;
#ifdef ESLOPE
INT32 range;
#endif
#ifndef ESLOPE
fixed_t lheight;
#endif
line_t *newline = NULL;
#ifdef ESLOPE
// skew FOF walls with slopes?
boolean slopeskew = false;
pslope_t *skewslope = NULL;
#endif
rw.x = x1;
rw.stopx = x2;
rw.pfloor = pfloor;
// Calculate light table.
// Use different light tables
// for horizontal / vertical / diagonal. Diagonal?
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
curline = ds->curline;
backsector = pfloor->target;
frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector;
texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture);
colfunc = colfuncs[BASEDRAWFUNC];
if (pfloor->master->flags & ML_TFERLINE)
{
size_t linenum = curline->linedef-backsector->lines[0];
newline = pfloor->master->frontsector->lines[0] + linenum;
texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
}
if (pfloor->flags & FF_TRANSLUCENT)
{
boolean fuzzy = true;
// Hacked up support for alpha value in software mode Tails 09-24-2002
if (pfloor->alpha < 12)
return; // Don't even draw it
else if (pfloor->alpha < 38)
dc_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 64)
dc_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 89)
dc_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 115)
dc_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 140)
dc_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 166)
dc_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 192)
dc_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 217)
dc_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT);
else if (pfloor->alpha < 243)
dc_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT);
else
fuzzy = false; // Opaque
if (fuzzy)
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
}
else if (pfloor->flags & FF_FOG)
colfunc = colfuncs[COLDRAWFUNC_FOG];
#ifdef ESLOPE
range = max(ds->x2-ds->x1, 1);
#endif
//SoM: Moved these up here so they are available for my lightlist calculations
rw.scalestep = ds->scalestep;
spryscale = ds->scale1 + (x1 - ds->x1)*rw.scalestep;
R_ThickLightLists(ds, range);
maskedtexturecol = ds->thicksidecol; maskedtexturecol = ds->thicksidecol;
@ -3114,14 +3364,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
#ifdef ESLOPE #ifdef ESLOPE
// calculate both left ends // calculate both left ends
if (*pfloor->t_slope) if (*pfloor->t_slope)
left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz; rw.left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz;
else else
left_top = *pfloor->topheight - viewz; rw.left_top = *pfloor->topheight - viewz;
if (*pfloor->b_slope) if (*pfloor->b_slope)
left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz; rw.left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz;
else else
left_bottom = *pfloor->bottomheight - viewz; rw.left_bottom = *pfloor->bottomheight - viewz;
skewslope = *pfloor->t_slope; // skew using top slope by default skewslope = *pfloor->t_slope; // skew using top slope by default
if (newline) if (newline)
{ {
@ -3132,7 +3382,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
slopeskew = true; slopeskew = true;
if (slopeskew) if (slopeskew)
dc_texturemid = left_top; dc_texturemid = rw.left_top;
else else
#endif #endif
dc_texturemid = *pfloor->topheight - viewz; dc_texturemid = *pfloor->topheight - viewz;
@ -3145,7 +3395,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
#ifdef ESLOPE #ifdef ESLOPE
skewslope = *pfloor->b_slope; // skew using bottom slope skewslope = *pfloor->b_slope; // skew using bottom slope
if (slopeskew) if (slopeskew)
dc_texturemid = left_bottom; dc_texturemid = rw.left_bottom;
else else
#endif #endif
offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; offsetvalue -= *pfloor->topheight - *pfloor->bottomheight;
@ -3159,7 +3409,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
#ifdef ESLOPE #ifdef ESLOPE
skewslope = *pfloor->b_slope; // skew using bottom slope skewslope = *pfloor->b_slope; // skew using bottom slope
if (slopeskew) if (slopeskew)
dc_texturemid = left_bottom; dc_texturemid = rw.left_bottom;
else else
#endif #endif
offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; offsetvalue -= *pfloor->topheight - *pfloor->bottomheight;
@ -3172,7 +3422,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y);
if (skewslope) if (skewslope)
ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); rw.ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT));
} }
#endif #endif
@ -3187,236 +3437,26 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
{ {
if (textures[texnum]->flip & 2) // vertically flipped? if (textures[texnum]->flip & 2) // vertically flipped?
{ {
colfunc_2s = R_DrawRepeatFlippedMaskedColumn; rw.colfunc_2s = R_DrawRepeatFlippedMaskedColumn;
column2s_length = textures[texnum]->height; rw.column2s_length = textures[texnum]->height;
} }
else else
colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture rw.colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture
} }
else else
{ {
colfunc_2s = R_Render2sidedMultiPatchColumn; //render multipatch with no holes (no post_t info) rw.colfunc_2s = R_Render2sidedMultiPatchColumn; //render multipatch with no holes (no post_t info)
column2s_length = textures[texnum]->height; rw.column2s_length = textures[texnum]->height;
} }
#ifdef ESLOPE #ifdef ESLOPE
// Set heights according to plane, or slope, whichever // Set heights according to plane, or slope, whichever
{ R_ThickStepping(ds, range);
fixed_t right_top, right_bottom;
// calculate right ends now
if (*pfloor->t_slope)
right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
else
right_top = *pfloor->topheight - viewz;
if (*pfloor->b_slope)
right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
else
right_bottom = *pfloor->bottomheight - viewz;
// using INT64 to avoid 32bit overflow
top_frac = (INT64)centeryfrac - (((INT64)left_top * ds->scale1) >> FRACBITS);
bottom_frac = (INT64)centeryfrac - (((INT64)left_bottom * ds->scale1) >> FRACBITS);
top_step = (INT64)centeryfrac - (((INT64)right_top * ds->scale2) >> FRACBITS);
bottom_step = (INT64)centeryfrac - (((INT64)right_bottom * ds->scale2) >> FRACBITS);
top_step = (top_step-top_frac)/(range);
bottom_step = (bottom_step-bottom_frac)/(range);
top_frac += top_step * (x1 - ds->x1);
bottom_frac += bottom_step * (x1 - ds->x1);
}
#endif #endif
// draw the columns // draw the columns
for (dc_x = x1; dc_x <= x2; dc_x++) rw.texnum = texnum;
{ R_RenderThickSegLoop();
if (maskedtexturecol[dc_x] != INT16_MAX)
{
#ifdef ESLOPE
if (ffloortextureslide) { // skew FOF walls
if (oldx != -1)
dc_texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])<<FRACBITS);
oldx = dc_x;
}
#endif
// Calculate bounds
// clamp the values if necessary to avoid overflows and rendering glitches caused by them
#ifdef ESLOPE
if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX;
else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac;
else sprtopscreen = windowtop = CLAMPMIN;
if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX;
else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac;
else sprbotscreen = windowbottom = CLAMPMIN;
top_frac += top_step;
bottom_frac += bottom_step;
#else
sprtopscreen = windowtop = (centeryfrac - FixedMul((dc_texturemid - offsetvalue), spryscale));
sprbotscreen = windowbottom = FixedMul(*pfloor->topheight - *pfloor->bottomheight, spryscale) + sprtopscreen;
#endif
// SoM: If column is out of range, why bother with it??
if (windowbottom < topbounds || windowtop > bottombounds)
{
if (dc_numlights)
{
for (i = 0; i < dc_numlights; i++)
{
rlight = &dc_lightlist[i];
rlight->height += rlight->heightstep;
if (rlight->flags & FF_CUTLEVEL)
rlight->botheight += rlight->botheightstep;
}
}
spryscale += rw.scalestep;
continue;
}
dc_iscale = 0xffffffffu / (unsigned)spryscale;
// Get data for the column
col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3);
// SoM: New code does not rely on R_DrawColumnShadowed_8 which
// will (hopefully) put less strain on the stack.
if (dc_numlights)
{
lighttable_t **xwalllights;
fixed_t height;
fixed_t bheight = 0;
INT32 solid = 0;
INT32 lighteffect = 0;
for (i = 0; i < dc_numlights; i++)
{
// Check if the current light effects the colormap/lightlevel
rlight = &dc_lightlist[i];
lighteffect = !(dc_lightlist[i].flags & FF_NOSHADE);
if (lighteffect)
{
lightnum = rlight->lightnum;
if (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE-1;
if (pfloor->flags & FF_FOG)
{
if (pfloor->master->frontsector->extra_colormap)
rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
else
rlight->rcolormap = xwalllights[pindex];
}
else
{
if (rlight->extra_colormap)
rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
else
rlight->rcolormap = xwalllights[pindex];
}
}
solid = 0; // don't carry over solid-cutting flag from the previous light
// Check if the current light can cut the current 3D floor.
if (rlight->flags & FF_CUTSOLIDS && !(pfloor->flags & FF_EXTRA))
solid = 1;
else if (rlight->flags & FF_CUTEXTRA && pfloor->flags & FF_EXTRA)
{
if (rlight->flags & FF_EXTRA)
{
// The light is from an extra 3D floor... Check the flags so
// there are no undesired cuts.
if ((rlight->flags & (FF_FOG|FF_SWIMMABLE)) == (pfloor->flags & (FF_FOG|FF_SWIMMABLE)))
solid = 1;
}
else
solid = 1;
}
else
solid = 0;
height = rlight->height;
rlight->height += rlight->heightstep;
if (solid)
{
bheight = rlight->botheight - (FRACUNIT >> 1);
rlight->botheight += rlight->botheightstep;
}
if (height <= windowtop)
{
if (lighteffect)
dc_colormap = rlight->rcolormap;
if (solid && windowtop < bheight)
windowtop = bheight;
continue;
}
windowbottom = height;
if (windowbottom >= sprbotscreen)
{
windowbottom = sprbotscreen;
// draw the texture
colfunc_2s (col);
for (i++; i < dc_numlights; i++)
{
rlight = &dc_lightlist[i];
rlight->height += rlight->heightstep;
if (rlight->flags & FF_CUTLEVEL)
rlight->botheight += rlight->botheightstep;
}
continue;
}
// draw the texture
colfunc_2s (col);
if (solid)
windowtop = bheight;
else
windowtop = windowbottom + 1;
if (lighteffect)
dc_colormap = rlight->rcolormap;
}
windowbottom = sprbotscreen;
// draw the texture, if there is any space left
if (windowtop < windowbottom)
colfunc_2s (col);
spryscale += rw.scalestep;
continue;
}
// calculate lighting
pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE - 1;
dc_colormap = walllights[pindex];
if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap)
dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
else if (frontsector->extra_colormap)
dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
// draw the texture
colfunc_2s (col);
spryscale += rw.scalestep;
}
}
colfunc = colfuncs[BASEDRAWFUNC]; colfunc = colfuncs[BASEDRAWFUNC];
#undef CLAMPMAX #undef CLAMPMAX

View File

@ -109,6 +109,21 @@ typedef struct
fixed_t distance; fixed_t distance;
angle_t normalangle; angle_t normalangle;
angle_t angle1; // angle to line origin angle_t angle1; // angle to line origin
// for masked segs and thick sides
INT32 texnum;
void (*colfunc_2s) (column_t *);
INT32 column2s_length; // column->length : for multi-patch on 2sided wall = texture->height
// thick sides
ffloor_t *pfloor;
#ifdef ESLOPE
// Render FOF sides kinda like normal sides, with the frac and step and everything
// NOTE: INT64 instead of fixed_t because overflow concerns
INT64 top_frac, top_step, bottom_frac, bottom_step;
fixed_t ffloortextureslide;
fixed_t left_top, left_bottom; // needed here for slope skewing
#endif
} renderwall_t; } renderwall_t;
extern renderwall_t rw; extern renderwall_t rw;