mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-24 21:31:46 +00:00
Fix #1247
This commit is contained in:
parent
b6544efceb
commit
da3355a153
5 changed files with 235 additions and 23 deletions
|
@ -74,7 +74,7 @@ UINT8 *dc_transmap; // one of the translucency tables
|
|||
UINT8 *dc_translation;
|
||||
|
||||
struct r_lightlist_s *dc_lightlist = NULL;
|
||||
INT32 dc_numlights = 0, dc_maxlights, dc_texheight;
|
||||
INT32 dc_numlights = 0, dc_maxlights, dc_texheight, dc_postlength;
|
||||
|
||||
// =========================================================================
|
||||
// SPAN DRAWING CODE STUFF
|
||||
|
|
|
@ -41,8 +41,7 @@ extern UINT8 *dc_translation;
|
|||
extern struct r_lightlist_s *dc_lightlist;
|
||||
extern INT32 dc_numlights, dc_maxlights;
|
||||
|
||||
//Fix TUTIFRUTI
|
||||
extern INT32 dc_texheight;
|
||||
extern INT32 dc_texheight, dc_postlength;
|
||||
|
||||
// -----------------------
|
||||
// SPAN DRAWING CODE STUFF
|
||||
|
@ -154,8 +153,10 @@ void R_VideoErase(size_t ofs, INT32 count);
|
|||
// -----------------
|
||||
|
||||
void R_DrawColumn_8(void);
|
||||
void R_DrawColumnClamped_8(void);
|
||||
void R_DrawShadeColumn_8(void);
|
||||
void R_DrawTranslucentColumn_8(void);
|
||||
void R_DrawTranslucentColumnClamped_8(void);
|
||||
void R_DrawDropShadowColumn_8(void);
|
||||
void R_DrawTranslatedColumn_8(void);
|
||||
void R_DrawTranslatedTranslucentColumn_8(void);
|
||||
|
|
176
src/r_draw8.c
176
src/r_draw8.c
|
@ -100,6 +100,98 @@ void R_DrawColumn_8(void)
|
|||
}
|
||||
}
|
||||
|
||||
/** \brief The R_DrawColumnClamped_8 function
|
||||
Same as R_DrawColumn_8, but prevents artifacts from showing up (caused by fixed-point imprecisions)
|
||||
*/
|
||||
void R_DrawColumnClamped_8(void)
|
||||
{
|
||||
INT32 count;
|
||||
UINT8 *dest;
|
||||
fixed_t frac;
|
||||
fixed_t fracstep;
|
||||
|
||||
count = dc_yh - dc_yl;
|
||||
|
||||
if (count < 0) // Zero length, column does not exceed a pixel.
|
||||
return;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height)
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Framebuffer destination address.
|
||||
dest = &topleft[dc_yl*vid.width + dc_x];
|
||||
|
||||
count++;
|
||||
|
||||
// Determine scaling, which is the only mapping to be done.
|
||||
fracstep = dc_iscale;
|
||||
frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep);
|
||||
|
||||
// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
|
||||
// This is as fast as it gets.
|
||||
{
|
||||
const UINT8 *source = dc_source;
|
||||
const lighttable_t *colormap = dc_colormap;
|
||||
INT32 heightmask = dc_texheight-1;
|
||||
INT32 idx;
|
||||
if (dc_texheight & heightmask) // not a power of 2 -- killough
|
||||
{
|
||||
heightmask++;
|
||||
heightmask <<= FRACBITS;
|
||||
|
||||
if (frac < 0)
|
||||
while ((frac += heightmask) < 0);
|
||||
else
|
||||
while (frac >= heightmask)
|
||||
frac -= heightmask;
|
||||
|
||||
do
|
||||
{
|
||||
// Re-map color indices from wall texture column
|
||||
// using a lighting/special effects LUT.
|
||||
// heightmask is the Tutti-Frutti fix
|
||||
idx = frac>>FRACBITS;
|
||||
if (idx >= 0 && idx < dc_postlength)
|
||||
*dest = colormap[source[idx]];
|
||||
dest += vid.width;
|
||||
|
||||
// Avoid overflow.
|
||||
if (fracstep > 0x7FFFFFFF - frac)
|
||||
frac += fracstep - heightmask;
|
||||
else
|
||||
frac += fracstep;
|
||||
|
||||
while (frac >= heightmask)
|
||||
frac -= heightmask;
|
||||
} while (--count);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((count -= 2) >= 0) // texture height is a power of 2
|
||||
{
|
||||
idx = (frac>>FRACBITS) & heightmask;
|
||||
if (idx >= 0 && idx < dc_postlength)
|
||||
*dest = colormap[source[idx]];
|
||||
dest += vid.width;
|
||||
frac += fracstep;
|
||||
idx = (frac>>FRACBITS) & heightmask;
|
||||
if (idx >= 0 && idx < dc_postlength)
|
||||
*dest = colormap[source[idx]];
|
||||
dest += vid.width;
|
||||
frac += fracstep;
|
||||
}
|
||||
if (count & 1)
|
||||
{
|
||||
idx = (frac>>FRACBITS) & heightmask;
|
||||
if (idx >= 0 && idx < dc_postlength)
|
||||
*dest = colormap[source[idx]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief The R_DrawShadeColumn_8 function
|
||||
Experiment to make software go faster. Taken from the Boom source
|
||||
*/
|
||||
|
@ -212,6 +304,90 @@ void R_DrawTranslucentColumn_8(void)
|
|||
}
|
||||
}
|
||||
|
||||
/** \brief The R_DrawTranslucentColumnClamped_8 function
|
||||
Same as R_DrawTranslucentColumn_8, but prevents artifacts from showing up (caused by fixed-point imprecisions)
|
||||
*/
|
||||
void R_DrawTranslucentColumnClamped_8(void)
|
||||
{
|
||||
INT32 count;
|
||||
UINT8 *dest;
|
||||
fixed_t frac, fracstep;
|
||||
|
||||
count = dc_yh - dc_yl + 1;
|
||||
|
||||
if (count <= 0) // Zero length, column does not exceed a pixel.
|
||||
return;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height)
|
||||
I_Error("R_DrawTranslucentColumnClamped_8: %d to %d at %d", dc_yl, dc_yh, dc_x);
|
||||
#endif
|
||||
|
||||
dest = &topleft[dc_yl*vid.width + dc_x];
|
||||
|
||||
// Looks familiar.
|
||||
fracstep = dc_iscale;
|
||||
frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep);
|
||||
|
||||
// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
|
||||
// This is as fast as it gets.
|
||||
{
|
||||
const UINT8 *source = dc_source;
|
||||
const UINT8 *transmap = dc_transmap;
|
||||
const lighttable_t *colormap = dc_colormap;
|
||||
INT32 heightmask = dc_texheight - 1;
|
||||
INT32 idx;
|
||||
if (dc_texheight & heightmask)
|
||||
{
|
||||
heightmask++;
|
||||
heightmask <<= FRACBITS;
|
||||
|
||||
if (frac < 0)
|
||||
while ((frac += heightmask) < 0)
|
||||
;
|
||||
else
|
||||
while (frac >= heightmask)
|
||||
frac -= heightmask;
|
||||
|
||||
do
|
||||
{
|
||||
// Re-map color indices from wall texture column
|
||||
// using a lighting/special effects LUT.
|
||||
// heightmask is the Tutti-Frutti fix
|
||||
idx = frac>>FRACBITS;
|
||||
if (idx >= 0 && idx < dc_postlength)
|
||||
*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
|
||||
dest += vid.width;
|
||||
if ((frac += fracstep) >= heightmask)
|
||||
frac -= heightmask;
|
||||
}
|
||||
while (--count);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((count -= 2) >= 0) // texture height is a power of 2
|
||||
{
|
||||
idx = (frac>>FRACBITS)&heightmask;
|
||||
if (idx >= 0 && idx < dc_postlength)
|
||||
*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
|
||||
dest += vid.width;
|
||||
frac += fracstep;
|
||||
idx = (frac>>FRACBITS)&heightmask;
|
||||
if (idx >= 0 && idx < dc_postlength)
|
||||
*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
|
||||
dest += vid.width;
|
||||
frac += fracstep;
|
||||
}
|
||||
if (count & 1)
|
||||
{
|
||||
idx = (frac>>FRACBITS)&heightmask;
|
||||
if (idx >= 0 && idx < dc_postlength)
|
||||
*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hack: A cut-down copy of R_DrawTranslucentColumn_8 that does not read texture
|
||||
// data since something about calculating the texture reading address for drop shadows is broken.
|
||||
// dc_texturemid and dc_iscale get wrong values for drop shadows, however those are not strictly
|
||||
|
|
63
src/r_segs.c
63
src/r_segs.c
|
@ -515,6 +515,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
fixed_t wall_scalex, wall_scaley;
|
||||
UINT8 vertflip;
|
||||
unsigned lengthcol;
|
||||
boolean fog = false;
|
||||
boolean fuzzy = false;
|
||||
|
||||
void (*colfunc_2s) (column_t *, unsigned);
|
||||
|
||||
|
@ -528,8 +530,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector;
|
||||
sidedef = R_GetFFloorSide(curline, pfloor);
|
||||
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
|
||||
if (pfloor->master->flags & ML_TFERLINE)
|
||||
{
|
||||
line_t *newline = R_GetFFloorLine(curline, pfloor);
|
||||
|
@ -547,7 +547,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
|
||||
if (pfloor->fofflags & FOF_TRANSLUCENT)
|
||||
{
|
||||
boolean fuzzy = true;
|
||||
fuzzy = true;
|
||||
|
||||
// Hacked up support for alpha value in software mode Tails 09-24-2002
|
||||
// ...unhacked by toaster 04-01-2021, re-hacked a little by sphere 19-11-2021
|
||||
|
@ -560,17 +560,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
else if (!(dc_transmap = R_GetTranslucencyTable(trans)) || trans == 0)
|
||||
fuzzy = false; // Opaque
|
||||
}
|
||||
|
||||
if (fuzzy)
|
||||
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
|
||||
}
|
||||
else if (pfloor->fofflags & FOF_FOG)
|
||||
{
|
||||
colfunc = colfuncs[COLDRAWFUNC_FOG];
|
||||
fog = true;
|
||||
}
|
||||
|
||||
range = max(ds->x2-ds->x1, 1);
|
||||
//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;
|
||||
|
||||
dc_numlights = 0;
|
||||
if (frontsector->numlights)
|
||||
|
@ -673,9 +670,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
// Get correct light level!
|
||||
if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
|
||||
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
|
||||
else if (pfloor->fofflags & FOF_FOG)
|
||||
else if (fog)
|
||||
lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT);
|
||||
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
|
||||
else if (fuzzy)
|
||||
lightnum = LIGHTLEVELS-1;
|
||||
else
|
||||
lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)
|
||||
|
@ -703,6 +700,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
vertflip = !vertflip;
|
||||
}
|
||||
|
||||
//SoM: Moved these up here so they are available for my lightlist calculations
|
||||
// Lactozilla: Moved them back down
|
||||
// This uses floating point math now, because the fixed-point imprecisions
|
||||
// become more severe the bigger the texture is scaled.
|
||||
double dwall_scaley = FixedToDouble(wall_scaley);
|
||||
double scalestep = FixedToDouble(ds->scalestep) / dwall_scaley;
|
||||
double yscale = (FixedToDouble(ds->scale1) + (x1 - ds->x1)*scalestep) / dwall_scaley;
|
||||
|
||||
thicksidecol = ffloortexturecolumn;
|
||||
|
||||
wall_offsetx = ds->offsetx + sidedef->offsetx_mid;
|
||||
|
@ -824,15 +829,41 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
rlight->botheight += rlight->botheightstep;
|
||||
}
|
||||
}
|
||||
spryscale += rw_scalestep;
|
||||
yscale += scalestep;
|
||||
continue;
|
||||
}
|
||||
|
||||
dc_iscale = FixedMul(0xffffffffu / (unsigned)spryscale, wall_scaley);
|
||||
|
||||
// Get data for the column
|
||||
col = R_GetColumn(texnum, ((thicksidecol[dc_x] + wall_offsetx) >> FRACBITS));
|
||||
|
||||
spryscale = DoubleToFixed(yscale);
|
||||
|
||||
// Eh. I tried fixing the scaling artifacts but it still wasn't perfect.
|
||||
// So this checks if the column has gaps in it or not, and if it does, uses a version of the column drawers
|
||||
// that prevents the artifacts from being visible.
|
||||
// Note that if rendering fog then none of this matters because there's no texture mapping to be done
|
||||
if (!fog)
|
||||
{
|
||||
dc_iscale = 0xffffffffu / (unsigned)spryscale;
|
||||
|
||||
// Column has a single post and it matches the texture height, use regular column drawers
|
||||
if (col->num_posts == 1 && col->posts[0].topdelta == 0 && col->posts[0].length == (unsigned)dc_texheight)
|
||||
{
|
||||
if (fuzzy)
|
||||
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
|
||||
else
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise use column drawers with extra checks
|
||||
if (fuzzy)
|
||||
colfunc = R_DrawTranslucentColumnClamped_8;
|
||||
else
|
||||
colfunc = R_DrawColumnClamped_8;
|
||||
}
|
||||
}
|
||||
|
||||
// SoM: New code does not rely on R_DrawColumnShadowed_8 which
|
||||
// will (hopefully) put less strain on the stack.
|
||||
if (dc_numlights)
|
||||
|
@ -947,7 +978,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
if (windowtop < windowbottom)
|
||||
colfunc_2s (col, lengthcol);
|
||||
|
||||
spryscale += rw_scalestep;
|
||||
yscale += scalestep;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -966,7 +997,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
|
||||
// draw the texture
|
||||
colfunc_2s (col, lengthcol);
|
||||
spryscale += rw_scalestep;
|
||||
yscale += scalestep;
|
||||
}
|
||||
colfunc = colfuncs[BASEDRAWFUNC];
|
||||
|
||||
|
|
|
@ -839,8 +839,10 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol)
|
|||
{
|
||||
post_t *post = &column->posts[i];
|
||||
|
||||
dc_postlength = post->length;
|
||||
|
||||
INT32 topscreen = sprtopscreen + spryscale*post->topdelta;
|
||||
INT32 bottomscreen = topscreen + spryscale*post->length;
|
||||
INT32 bottomscreen = topscreen + spryscale*dc_postlength;
|
||||
|
||||
dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
|
||||
dc_yh = (bottomscreen-1)>>FRACBITS;
|
||||
|
@ -909,10 +911,12 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol)
|
|||
if (!post->length)
|
||||
continue;
|
||||
|
||||
topdelta = lengthcol-post->length-post->topdelta;
|
||||
dc_postlength = post->length;
|
||||
|
||||
topdelta = lengthcol-dc_postlength-post->topdelta;
|
||||
topscreen = sprtopscreen + spryscale*topdelta;
|
||||
bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*post->length
|
||||
: sprbotscreen + spryscale*post->length;
|
||||
bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*dc_postlength
|
||||
: sprbotscreen + spryscale*dc_postlength;
|
||||
|
||||
dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
|
||||
dc_yh = (bottomscreen-1)>>FRACBITS;
|
||||
|
|
Loading…
Reference in a new issue