From 837ed7bd8064b7872bd7884b26025ce3dee89709 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 29 Oct 2016 05:35:41 +0200 Subject: [PATCH] Fix dancing sprites due to texture coordinate calculations not taking pixel centers into account Merge R_DrawMaskedColumn and R_DrawMaskedColumnHoriz into one function to remove code duplication --- src/r_draw.h | 2 +- src/r_drawt.cpp | 113 +++++++---------------------------------------- src/r_segs.cpp | 24 +++++----- src/r_things.cpp | 93 ++++++++++++-------------------------- src/r_things.h | 4 +- src/v_draw.cpp | 6 +-- 6 files changed, 61 insertions(+), 181 deletions(-) diff --git a/src/r_draw.h b/src/r_draw.h index c45700a21..fa84e5ae9 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -116,7 +116,6 @@ extern void (*R_DrawSpanMaskedAddClamp)(void); // [RH] Span blit into an interleaved intermediate buffer extern void (*R_DrawColumnHoriz)(void); -void R_DrawMaskedColumnHoriz (const BYTE *column, const FTexture::Span *spans); // [RH] Initialize the above pointers void R_InitColumnDrawers (); @@ -183,6 +182,7 @@ extern void (*rt_map4cols)(int sx, int yl, int yh); #define rt_addclamp4cols rt_addclamp4cols_c #endif +void rt_flip_posts(); void rt_draw4cols (int sx); // [RH] Preps the temporary horizontal buffer. diff --git a/src/r_drawt.cpp b/src/r_drawt.cpp index e8faff0ce..cb228cce0 100644 --- a/src/r_drawt.cpp +++ b/src/r_drawt.cpp @@ -838,6 +838,21 @@ void rt_tlaterevsubclamp4cols (int sx, int yl, int yh) rt_revsubclamp4cols(sx, yl, yh); } +// Reorder the posts so that they get drawn top-to-bottom instead of bottom-to-top. +void rt_flip_posts() +{ + unsigned int *front = horizspan[dc_x & 3]; + unsigned int *back = dc_ctspan[dc_x & 3] - 2; + + while (front < back) + { + swapvalues(front[0], back[0]); + swapvalues(front[1], back[1]); + front += 2; + back -= 2; + } +} + // Copies all spans in all four columns to the screen starting at sx. // sx should be dword-aligned. void rt_draw4cols (int sx) @@ -1103,101 +1118,3 @@ void R_FillColumnHorizP (void) dest += 8; } while (--count); } - -// Same as R_DrawMaskedColumn() except that it always uses R_DrawColumnHoriz(). - -void R_DrawMaskedColumnHoriz (const BYTE *column, const FTexture::Span *span) -{ - const fixed_t texturemid = FLOAT2FIXED(dc_texturemid); - while (span->Length != 0) - { - const int length = span->Length; - const int top = span->TopOffset; - - // calculate unclipped screen coordinates for post - dc_yl = xs_RoundToInt(sprtopscreen + spryscale * top); - dc_yh = xs_RoundToInt(sprtopscreen + spryscale * (top + length) - 1); - - if (sprflipvert) - { - swapvalues (dc_yl, dc_yh); - } - - if (dc_yh >= mfloorclip[dc_x]) - { - dc_yh = mfloorclip[dc_x] - 1; - } - if (dc_yl < mceilingclip[dc_x]) - { - dc_yl = mceilingclip[dc_x]; - } - - if (dc_yl <= dc_yh) - { - if (sprflipvert) - { - dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS) - - fixed_t(CenterY * dc_iscale) - texturemid; - const fixed_t maxfrac = length << FRACBITS; - while (dc_texturefrac >= maxfrac) - { - if (++dc_yl > dc_yh) - goto nextpost; - dc_texturefrac += dc_iscale; - } - fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; - while (endfrac < 0) - { - if (--dc_yh < dc_yl) - goto nextpost; - endfrac -= dc_iscale; - } - } - else - { - dc_texturefrac = texturemid - (top << FRACBITS) - + (dc_yl*dc_iscale) - fixed_t((CenterY-1) * dc_iscale); - while (dc_texturefrac < 0) - { - if (++dc_yl > dc_yh) - goto nextpost; - dc_texturefrac += dc_iscale; - } - fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; - const fixed_t maxfrac = length << FRACBITS; - if (dc_yh < mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale) - { - dc_yh++; - } - else while (endfrac >= maxfrac) - { - if (--dc_yh < dc_yl) - goto nextpost; - endfrac -= dc_iscale; - } - } - dc_source = column + top; - dc_dest = ylookup[dc_yl] + dc_x + dc_destorg; - dc_count = dc_yh - dc_yl + 1; - hcolfunc_pre (); - } -nextpost: - span++; - } - - if (sprflipvert) - { - unsigned int *front = horizspan[dc_x&3]; - unsigned int *back = dc_ctspan[dc_x&3] - 2; - - // Reorder the posts so that they get drawn top-to-bottom - // instead of bottom-to-top. - while (front < back) - { - swapvalues (front[0], back[0]); - swapvalues (front[1], back[1]); - front += 2; - back -= 2; - } - } -} diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 48d8f1651..464fb3644 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -173,7 +173,7 @@ CVAR(Bool, r_drawmirrors, true, 0) float *MaskedSWall; float MaskedScaleY; -static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FTexture::Span *spans), FTexture *tex) +static void BlastMaskedColumn (FTexture *tex, bool useRt) { // calculate lighting if (fixedcolormap == NULL && fixedlightlev < 0) @@ -198,7 +198,7 @@ static void BlastMaskedColumn (void (*blastfunc)(const BYTE *pixels, const FText // draw the texture const FTexture::Span *spans; const BYTE *pixels = tex->GetColumn (maskedtexturecol[dc_x] >> FRACBITS, &spans); - blastfunc (pixels, spans); + R_DrawMaskedColumn(pixels, spans, useRt); rw_light += rw_lightstep; spryscale += rw_scalestep; } @@ -441,7 +441,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) { for (dc_x = x1; dc_x < x2; ++dc_x) { - BlastMaskedColumn (R_DrawMaskedColumn, tex); + BlastMaskedColumn (tex, false); } } else @@ -456,24 +456,24 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) while ((dc_x < stop) && (dc_x & 3)) { - BlastMaskedColumn (R_DrawMaskedColumn, tex); + BlastMaskedColumn (tex, false); dc_x++; } while (dc_x < stop) { rt_initcols(); - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); dc_x++; - BlastMaskedColumn (R_DrawMaskedColumnHoriz, tex); + BlastMaskedColumn (tex, true); dc_x++; + BlastMaskedColumn (tex, true); dc_x++; + BlastMaskedColumn (tex, true); dc_x++; + BlastMaskedColumn (tex, true); rt_draw4cols (dc_x - 3); dc_x++; } while (dc_x < x2) { - BlastMaskedColumn (R_DrawMaskedColumn, tex); + BlastMaskedColumn (tex, false); dc_x++; } } @@ -3245,7 +3245,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { // calculate lighting dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); } - R_WallSpriteColumn (R_DrawMaskedColumn); + R_WallSpriteColumn (false); dc_x++; } @@ -3258,7 +3258,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, rt_initcols(); for (int zz = 4; zz; --zz) { - R_WallSpriteColumn (R_DrawMaskedColumnHoriz); + R_WallSpriteColumn (true); dc_x++; } rt_draw4cols (dc_x - 4); @@ -3270,7 +3270,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { // calculate lighting dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); } - R_WallSpriteColumn (R_DrawMaskedColumn); + R_WallSpriteColumn (false); dc_x++; } } diff --git a/src/r_things.cpp b/src/r_things.cpp index a88624443..523004772 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -250,19 +250,17 @@ double sprtopscreen; bool sprflipvert; -void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span) +void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span, bool useRt) { - const fixed_t centeryfrac = FLOAT2FIXED(CenterY); - const fixed_t texturemid = FLOAT2FIXED(dc_texturemid); while (span->Length != 0) { const int length = span->Length; const int top = span->TopOffset; // calculate unclipped screen coordinates for post - dc_yl = xs_RoundToInt(sprtopscreen + spryscale * top); - dc_yh = xs_RoundToInt(sprtopscreen + spryscale * (top + length)) - 1; - + dc_yl = (int)(sprtopscreen + spryscale * top); + dc_yh = (int)(sprtopscreen + spryscale * (top + length)) - 1; + if (sprflipvert) { swapvalues (dc_yl, dc_yh); @@ -279,56 +277,20 @@ void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *span) if (dc_yl <= dc_yh) { - if (sprflipvert) - { - dc_texturefrac = (dc_yl*dc_iscale) - (top << FRACBITS) - - FixedMul (centeryfrac, dc_iscale) - texturemid; - const fixed_t maxfrac = length << FRACBITS; - while (dc_texturefrac >= maxfrac) - { - if (++dc_yl > dc_yh) - goto nextpost; - dc_texturefrac += dc_iscale; - } - fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; - while (endfrac < 0) - { - if (--dc_yh < dc_yl) - goto nextpost; - endfrac -= dc_iscale; - } - } - else - { - dc_texturefrac = texturemid - (top << FRACBITS) - + (dc_yl*dc_iscale) - FixedMul (centeryfrac-FRACUNIT, dc_iscale); - while (dc_texturefrac < 0) - { - if (++dc_yl > dc_yh) - goto nextpost; - dc_texturefrac += dc_iscale; - } - fixed_t endfrac = dc_texturefrac + (dc_yh-dc_yl)*dc_iscale; - const fixed_t maxfrac = length << FRACBITS; - if (dc_yh < mfloorclip[dc_x]-1 && endfrac < maxfrac - dc_iscale) - { - dc_yh++; - } - else while (endfrac >= maxfrac) - { - if (--dc_yh < dc_yl) - goto nextpost; - endfrac -= dc_iscale; - } - } - dc_source = column + top; - dc_dest = ylookup[dc_yl] + dc_x + dc_destorg; + dc_texturefrac = FLOAT2FIXED((dc_yl + 0.5 - sprtopscreen) / spryscale); + dc_source = column; + dc_dest = (ylookup[dc_yl] + dc_x) + dc_destorg; dc_count = dc_yh - dc_yl + 1; - colfunc (); + if (useRt) + hcolfunc_pre(); + else + colfunc (); } -nextpost: span++; } + + if (sprflipvert && useRt) + rt_flip_posts(); } // [ZZ] @@ -470,7 +432,7 @@ void R_DrawVisSprite (vissprite_t *vis) { pixels = tex->GetColumn (frac >> FRACBITS, &spans); if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) - R_DrawMaskedColumn (pixels, spans); + R_DrawMaskedColumn (pixels, spans, false); dc_x++; frac += xiscale; } @@ -482,7 +444,7 @@ void R_DrawVisSprite (vissprite_t *vis) { pixels = tex->GetColumn (frac >> FRACBITS, &spans); if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) - R_DrawMaskedColumnHoriz (pixels, spans); + R_DrawMaskedColumn (pixels, spans, true); dc_x++; frac += xiscale; } @@ -493,7 +455,7 @@ void R_DrawVisSprite (vissprite_t *vis) { pixels = tex->GetColumn (frac >> FRACBITS, &spans); if (ispsprite || !R_ClipSpriteColumnWithPortals(vis)) - R_DrawMaskedColumn (pixels, spans); + R_DrawMaskedColumn (pixels, spans, false); dc_x++; frac += xiscale; } @@ -603,7 +565,7 @@ void R_DrawWallSprite(vissprite_t *spr) dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT); } if (!R_ClipSpriteColumnWithPortals(spr)) - R_WallSpriteColumn(R_DrawMaskedColumn); + R_WallSpriteColumn(false); dc_x++; } @@ -617,7 +579,7 @@ void R_DrawWallSprite(vissprite_t *spr) for (int zz = 4; zz; --zz) { if (!R_ClipSpriteColumnWithPortals(spr)) - R_WallSpriteColumn(R_DrawMaskedColumnHoriz); + R_WallSpriteColumn(true); dc_x++; } rt_draw4cols(dc_x - 4); @@ -630,14 +592,14 @@ void R_DrawWallSprite(vissprite_t *spr) dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT); } if (!R_ClipSpriteColumnWithPortals(spr)) - R_WallSpriteColumn(R_DrawMaskedColumn); + R_WallSpriteColumn(false); dc_x++; } } R_FinishSetPatchStyle(); } -void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)) +void R_WallSpriteColumn (bool useRt) { float iscale = swall[dc_x] * MaskedScaleY; dc_iscale = FLOAT2FIXED(iscale); @@ -651,7 +613,7 @@ void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Sp const FTexture::Span *spans; column = WallSpriteTile->GetColumn (lwall[dc_x] >> FRACBITS, &spans); dc_texturefrac = 0; - drawfunc (column, spans); + R_DrawMaskedColumn(column, spans, useRt); rw_light += rw_lightstep; } @@ -984,21 +946,23 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor const double thingxscalemul = spriteScale.X / tex->Scale.X; tx -= ((renderflags & RF_XFLIP) ? (tex->GetWidth() - tex->LeftOffset - 1) : tex->LeftOffset) * thingxscalemul; - x1 = centerx + xs_RoundToInt(tx * xscale); + double dtx1 = tx * xscale; + x1 = centerx + xs_RoundToInt(dtx1); // off the right side? if (x1 >= WindowRight) return; tx += tex->GetWidth() * thingxscalemul; - x2 = centerx + xs_RoundToInt(tx * xscale); + double dtx2 = tx * xscale; + x2 = centerx + xs_RoundToInt(dtx2); // off the left side or too small? if ((x2 < WindowLeft || x2 <= x1)) return; xscale = spriteScale.X * xscale / tex->Scale.X; - iscale = (tex->GetWidth() << FRACBITS) / (x2 - x1); + iscale = (fixed_t)(tex->GetWidth() / (dtx2 - dtx1) * FRACUNIT); double yscale = spriteScale.Y / tex->Scale.Y; @@ -1026,8 +990,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor vis->xiscale = iscale; } - if (vis->x1 > x1) - vis->startfrac += vis->xiscale * (vis->x1 - x1); + vis->startfrac += (fixed_t)(vis->xiscale * (vis->x1 - centerx - dtx1 + 0.5 * thingxscalemul)); } else { diff --git a/src/r_things.h b/src/r_things.h index 29e69d3a5..53b887b18 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -124,8 +124,8 @@ extern double pspriteyscale; extern FTexture *WallSpriteTile; -void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *spans); -void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)); +void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *spans, bool useRt); +void R_WallSpriteColumn (bool useRt); void R_CacheSprite (spritedef_t *sprite); void R_SortVisSprites (int (*compare)(const void *, const void *), size_t first); diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 4677c4b08..20e5311cd 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -299,7 +299,7 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) while ((dc_x < stop4) && (dc_x & 3)) { pixels = img->GetColumn(frac >> FRACBITS, spanptr); - R_DrawMaskedColumn(pixels, spans); + R_DrawMaskedColumn(pixels, spans, false); dc_x++; frac += xiscale_i; } @@ -310,7 +310,7 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) for (int zz = 4; zz; --zz) { pixels = img->GetColumn(frac >> FRACBITS, spanptr); - R_DrawMaskedColumnHoriz(pixels, spans); + R_DrawMaskedColumn(pixels, spans, true); dc_x++; frac += xiscale_i; } @@ -320,7 +320,7 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) while (dc_x < x2_i) { pixels = img->GetColumn(frac >> FRACBITS, spanptr); - R_DrawMaskedColumn(pixels, spans); + R_DrawMaskedColumn(pixels, spans, false); dc_x++; frac += xiscale_i; }