From d7924d6e9d38287b2b529c8f1ef72d39b5e42b7e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 12 Feb 2021 04:48:59 +0100 Subject: [PATCH] Fix dancing sprites regression --- src/rendering/swrenderer/line/r_wallsetup.cpp | 34 ++++++++++++++----- .../swrenderer/viewport/r_spritedrawer.cpp | 13 +++---- .../swrenderer/viewport/r_spritedrawer.h | 2 +- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/rendering/swrenderer/line/r_wallsetup.cpp b/src/rendering/swrenderer/line/r_wallsetup.cpp index 1e70dc0af..2f864581e 100644 --- a/src/rendering/swrenderer/line/r_wallsetup.cpp +++ b/src/rendering/swrenderer/line/r_wallsetup.cpp @@ -54,6 +54,8 @@ namespace swrenderer auto viewport = thread->Viewport.get(); RenderPortal* renderportal = thread->Portal.get(); + // Rotate to view direction: + tleft.X = float(pt1.X * viewport->viewpoint.Sin - pt1.Y * viewport->viewpoint.Cos); tright.X = float(pt2.X * viewport->viewpoint.Sin - pt2.Y * viewport->viewpoint.Cos); @@ -68,6 +70,8 @@ namespace swrenderer std::swap(tleft.Y, tright.Y); } + // Edge clip: + float fsx1, fsz1, fsx2, fsz2; if (tleft.X >= -tleft.Y) @@ -112,23 +116,20 @@ namespace swrenderer if (fsz2 < TOO_CLOSE_Z) return true; + // Find screen range covered by the line: + sx1 = xs_RoundToInt(fsx1); sx2 = xs_RoundToInt(fsx2); - float delta = fsx2 - fsx1; - float t1 = (sx1 + 0.5f - fsx1) / delta; - float t2 = (sx2 + 0.5f - fsx1) / delta; - float invZ1 = 1.0f / fsz1; - float invZ2 = 1.0f / fsz2; - sz1 = 1.0f / (invZ1 * (1.0f - t1) + invZ2 * t1); - sz2 = 1.0f / (invZ1 * (1.0f - t2) + invZ2 * t2); - if (sx2 <= sx1) return true; + // Remap texture coordinates to the part covered by the line segment: + if (lineseg && lineseg->linedef) { line_t* line = lineseg->linedef; + float t1, t2; if (fabs(line->delta.X) > fabs(line->delta.Y)) { t1 = (lineseg->v1->fX() - line->v1->fX()) / line->delta.X; @@ -150,6 +151,23 @@ namespace swrenderer tx2 = t1 + tx2 * (t2 - t1); } + // Calculate screen depths for the start and end points (resulting values are at the pixel center): + + float delta = fsx2 - fsx1; + float t1 = (sx1 + 0.5f - fsx1) / delta; + float t2 = (sx2 + 0.5f - fsx1) / delta; + float invZ1 = 1.0f / fsz1; + float invZ2 = 1.0f / fsz2; + sz1 = 1.0f / (invZ1 * (1.0f - t1) + invZ2 * t1); + sz2 = 1.0f / (invZ1 * (1.0f - t2) + invZ2 * t2); + + // Adjust texture coordinates to also be at the pixel centers: + + float ftx1 = tx1 * invZ1; + float ftx2 = tx2 * invZ2; + tx1 = (ftx1 * (1.0f - t1) + ftx2 * t1) * sz1; + tx2 = (ftx1 * (1.0f - t2) + ftx2 * t2) * sz2; + return false; } diff --git a/src/rendering/swrenderer/viewport/r_spritedrawer.cpp b/src/rendering/swrenderer/viewport/r_spritedrawer.cpp index 25710c1f3..316f6af91 100644 --- a/src/rendering/swrenderer/viewport/r_spritedrawer.cpp +++ b/src/rendering/swrenderer/viewport/r_spritedrawer.cpp @@ -70,9 +70,6 @@ namespace swrenderer iscale = -iscale; float vstepY = iscale / WallC.sz1 / (viewport->InvZtoScale / WallC.sz1); - wpos += wstepX * 0.5f; - upos += ustepX * 0.5f; - int x1 = MAX(WallC.sx1, clipx1); int x2 = MIN(WallC.sx2, clipx2); if (x1 >= x2) @@ -165,7 +162,7 @@ namespace swrenderer } } - void SpriteDrawerArgs::DrawMaskedColumn(RenderThread* thread, int x, int y1, int cliptop, int clipbottom, uint32_t texelX, uint32_t texelStepX, uint32_t texelStepY, float scaleV, bool flipY, FSoftwareTexture* tex, int texwidth, int texheight, bool bgra, FRenderStyle style) + void SpriteDrawerArgs::DrawMaskedColumn(RenderThread* thread, int x, float y1, int cliptop, int clipbottom, uint32_t texelX, uint32_t texelStepX, uint32_t texelStepY, float scaleV, bool flipY, FSoftwareTexture* tex, int texwidth, int texheight, bool bgra, FRenderStyle style) { const FSoftwareTextureSpan* span; if (bgra) @@ -230,8 +227,8 @@ namespace swrenderer const int top = span->TopOffset; // calculate unclipped screen coordinates for post - dc_yl = (int)(y1 + top / scaleV + 0.5f); - dc_yh = (int)(y1 + (top + length) / scaleV + 0.5f); + dc_yl = xs_RoundToInt(y1 + top / scaleV); + dc_yh = xs_RoundToInt(y1 + (top + length) / scaleV); if (flipY) std::swap(dc_yl, dc_yh); @@ -268,8 +265,8 @@ namespace swrenderer const int top = span->TopOffset; // calculate unclipped screen coordinates for post - dc_yl = (int)(y1 + top / scaleV + 0.5f); - dc_yh = (int)(y1 + (top + length) / scaleV + 0.5f); + dc_yl = xs_RoundToInt(y1 + top / scaleV); + dc_yh = xs_RoundToInt(y1 + (top + length) / scaleV); if (flipY) std::swap(dc_yl, dc_yh); diff --git a/src/rendering/swrenderer/viewport/r_spritedrawer.h b/src/rendering/swrenderer/viewport/r_spritedrawer.h index f233d2c03..2ab3b97cc 100644 --- a/src/rendering/swrenderer/viewport/r_spritedrawer.h +++ b/src/rendering/swrenderer/viewport/r_spritedrawer.h @@ -69,7 +69,7 @@ namespace swrenderer RenderViewport *Viewport() const { return dc_viewport; } private: - void DrawMaskedColumn(RenderThread* thread, int x, int y1, int cliptop, int clipbottom, uint32_t texelX, uint32_t texelStepX, uint32_t texelStepY, float scaleV, bool flipY, FSoftwareTexture* tex, int texwidth, int texheight, bool bgra, FRenderStyle style); + void DrawMaskedColumn(RenderThread* thread, int x, float y1, int cliptop, int clipbottom, uint32_t texelX, uint32_t texelStepX, uint32_t texelStepY, float scaleV, bool flipY, FSoftwareTexture* tex, int texwidth, int texheight, bool bgra, FRenderStyle style); void SetDest(RenderViewport* viewport, int x, int y); void SetCount(int count) { dc_count = count; }