From a50e6bd7698073bc950ecb722e813984b9e7384b Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Mon, 22 Jan 2024 21:16:46 -0300 Subject: [PATCH] Fixed: - Issues with negative texture scales in the OpenGL renderer - Regression related to horizontal texture scaling - Regression related to the rendering of vertically flipped textures --- src/hardware/hw_main.c | 72 ++++++++++++++++++++++++++++++++++-------- src/r_segs.c | 36 ++++++++++++--------- src/r_things.c | 9 ++---- 3 files changed, 82 insertions(+), 35 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index efbcf81d7..e476e6aef 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1167,10 +1167,21 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gl_toptexture) { grTex = HWR_GetTexture(gl_toptexture); - xscale = FixedToFloat(gl_sidedef->scalex_top); - yscale = FixedToFloat(gl_sidedef->scaley_top); + xscale = FixedToFloat(abs(gl_sidedef->scalex_top)); + yscale = FixedToFloat(abs(gl_sidedef->scaley_top)); - fixed_t texheight = FixedDiv(textureheight[gl_toptexture], gl_sidedef->scaley_top); + fixed_t offsetx_top = gl_sidedef->offsetx_top; + + float left = cliplow * xscale; + float right = cliphigh * xscale; + if (gl_sidedef->scalex_top < 0) + { + left = -left; + right = -right; + offsetx_top = -offsetx_top; + } + + fixed_t texheight = FixedDiv(textureheight[gl_toptexture], abs(gl_sidedef->scaley_top)); // PEGGING if (gl_linedef->flags & ML_DONTPEGTOP) @@ -1182,15 +1193,18 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom texturevpeg *= yscale; - texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_top; + if (gl_sidedef->scaley_top < 0) + texturevpeg -= gl_sidedef->rowoffset + gl_sidedef->offsety_top; + else + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_top; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway texturevpeg %= texheight; wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + (gl_frontsector->ceilingheight - gl_backsector->ceilingheight) * yscale) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_top) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_top) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (left + offsetx_top) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (right + offsetx_top) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1215,6 +1229,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].t = wallVerts[1].t - (worldtopslope - worldhighslope) * yscale * grTex->scaleY; } + if (gl_sidedef->scaley_top < 0) + { + wallVerts[0].t = -wallVerts[0].t; + wallVerts[1].t = -wallVerts[1].t; + wallVerts[2].t = -wallVerts[2].t; + wallVerts[3].t = -wallVerts[3].t; + } + // set top/bottom coords wallVerts[3].y = FIXED_TO_FLOAT(worldtop); wallVerts[0].y = FIXED_TO_FLOAT(worldhigh); @@ -1233,8 +1255,19 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if ((worldlowslope > worldbottomslope || worldlow > worldbottom) && gl_bottomtexture) { grTex = HWR_GetTexture(gl_bottomtexture); - xscale = FixedToFloat(gl_sidedef->scalex_bottom); - yscale = FixedToFloat(gl_sidedef->scaley_bottom); + xscale = FixedToFloat(abs(gl_sidedef->scalex_bottom)); + yscale = FixedToFloat(abs(gl_sidedef->scaley_bottom)); + + fixed_t offsetx_bottom = gl_sidedef->offsetx_bottom; + + float left = cliplow * xscale; + float right = cliphigh * xscale; + if (gl_sidedef->scalex_bottom < 0) + { + left = -left; + right = -right; + offsetx_bottom = -offsetx_bottom; + } // PEGGING if (!(gl_linedef->flags & ML_DONTPEGBOTTOM)) @@ -1246,15 +1279,18 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom texturevpeg *= yscale; - texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; + if (gl_sidedef->scaley_bottom < 0) + texturevpeg -= gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; + else + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway - texturevpeg %= FixedDiv(textureheight[gl_bottomtexture], gl_sidedef->scaley_bottom); + texturevpeg %= FixedDiv(textureheight[gl_bottomtexture], abs(gl_sidedef->scaley_bottom)); wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + (gl_backsector->floorheight - gl_frontsector->floorheight) * yscale) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_bottom) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_bottom) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (left + offsetx_bottom) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (right + offsetx_bottom) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1278,6 +1314,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[1].t = (texturevpeg + (worldlowslope - worldbottomslope) * yscale) * grTex->scaleY; } + if (gl_sidedef->scaley_bottom < 0) + { + wallVerts[0].t = -wallVerts[0].t; + wallVerts[1].t = -wallVerts[1].t; + wallVerts[2].t = -wallVerts[2].t; + wallVerts[3].t = -wallVerts[3].t; + } + // set top/bottom coords wallVerts[3].y = FIXED_TO_FLOAT(worldlow); wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); @@ -1296,7 +1340,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (gl_midtexture && HWR_BlendMidtextureSurface(&Surf)) { sector_t *front, *back; - fixed_t texheight = FixedDiv(textureheight[gl_midtexture], gl_sidedef->scaley_mid); + fixed_t texheight = FixedDiv(textureheight[gl_midtexture], abs(gl_sidedef->scaley_mid)); INT32 repeats; if (gl_linedef->frontsector->heightsec != -1) @@ -1363,7 +1407,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // Find the wall's coordinates fixed_t midtexheight = texheight * repeats; - fixed_t rowoffset = FixedDiv(gl_sidedef->rowoffset + gl_sidedef->offsety_mid, gl_sidedef->scaley_mid); + fixed_t rowoffset = FixedDiv(gl_sidedef->rowoffset + gl_sidedef->offsety_mid, abs(gl_sidedef->scaley_mid)); // Texture is not skewed if (gl_linedef->flags & ML_NOSKEW) diff --git a/src/r_segs.c b/src/r_segs.c index 0352a4428..97b26c86f 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1424,20 +1424,20 @@ static void R_RenderSegLoop (void) { angle_t angle; fixed_t textureoffset; - size_t pindex; - INT32 yl; - INT32 yh; + size_t pindex; + INT32 yl; + INT32 yh; - INT32 mid; + INT32 mid; fixed_t texturecolumn = 0; fixed_t toptexturecolumn = 0; fixed_t bottomtexturecolumn = 0; fixed_t oldtexturecolumn = -1; fixed_t oldtexturecolumn_top = -1; fixed_t oldtexturecolumn_bottom = -1; - INT32 top; - INT32 bottom; - INT32 i; + INT32 top; + INT32 bottom; + INT32 i; fixed_t topscaley = rw_toptexturescaley; fixed_t midscaley = rw_midtexturescaley; @@ -1838,8 +1838,11 @@ static void R_RenderSegLoop (void) { if (oldtexturecolumn != -1) { - rw_midtexturemid += FixedMul(rw_midtextureslide, oldtexturecolumn-texturecolumn); - rw_midtextureback += FixedMul(rw_midtexturebackslide, oldtexturecolumn-texturecolumn); + INT32 diff = oldtexturecolumn-texturecolumn; + if (rw_invmidtexturescalex < 0) + diff = -diff; + rw_midtexturemid += FixedMul(rw_midtextureslide, diff); + rw_midtextureback += FixedMul(rw_midtexturebackslide, diff); } oldtexturecolumn = texturecolumn; @@ -1878,8 +1881,11 @@ static void R_RenderSegLoop (void) if (oldoverlaycolumn[i] != -1) { - rw_overlay[i].mid += FixedMul(rw_overlay[i].slide, oldoverlaycolumn[i]-overlaycolumn[i]); - rw_overlay[i].back += FixedMul(rw_overlay[i].backslide, oldoverlaycolumn[i]-overlaycolumn[i]); + INT32 diff = oldoverlaycolumn[i]-overlaycolumn[i]; + if (rw_overlay[i].scalex < 0) + diff = -diff; + rw_overlay[i].mid += FixedMul(rw_overlay[i].slide, diff); + rw_overlay[i].back += FixedMul(rw_overlay[i].backslide, diff); } oldoverlaycolumn[i] = overlaycolumn[i]; @@ -2059,7 +2065,7 @@ static void R_AddOverlayTextures(fixed_t ceilingfrontslide, fixed_t floorfrontsl rw_overlay[i].offsetx = sidedef->overlays[i].offsetx; rw_overlay[i].offsety = sidedef->overlays[i].offsety; - rw_overlay[i].invscalex = FixedDiv(FRACUNIT, abs(rw_overlay[i].scalex)); + rw_overlay[i].invscalex = FixedDiv(FRACUNIT, rw_overlay[i].scalex); if (sidedef->flags & GET_SIDEFLAG_EDGENOSKEW(i)) { @@ -2333,7 +2339,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_midtexturescalex = sidedef->scalex_mid; rw_midtexturescaley = sidedef->scaley_mid; - rw_invmidtexturescalex = FixedDiv(FRACUNIT, abs(rw_midtexturescalex)); + rw_invmidtexturescalex = FixedDiv(FRACUNIT, rw_midtexturescalex); if (!backsector) { @@ -2578,7 +2584,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_toptexturescalex = sidedef->scalex_top; rw_toptexturescaley = sidedef->scaley_top; - rw_invtoptexturescalex = FixedDiv(FRACUNIT, abs(rw_toptexturescalex)); + rw_invtoptexturescalex = FixedDiv(FRACUNIT, rw_toptexturescalex); if (rw_toptexturescaley < 0) toprowoffset = -toprowoffset; @@ -2618,7 +2624,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) rw_bottomtexturescalex = sidedef->scalex_bottom; rw_bottomtexturescaley = sidedef->scaley_bottom; - rw_invbottomtexturescalex = FixedDiv(FRACUNIT, abs(rw_bottomtexturescalex)); + rw_invbottomtexturescalex = FixedDiv(FRACUNIT, rw_bottomtexturescalex); if (rw_bottomtexturescaley < 0) botrowoffset = -botrowoffset; diff --git a/src/r_things.c b/src/r_things.c index 4052ea34a..5375a6112 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -704,8 +704,6 @@ static size_t flippedcolsize; void R_DrawFlippedPost(UINT8 *source, unsigned length, void (*drawcolfunc)(void)) { - UINT8 *d, *s; - if (!length) return; @@ -717,8 +715,8 @@ void R_DrawFlippedPost(UINT8 *source, unsigned length, void (*drawcolfunc)(void) dc_source = flippedcol; - for (s = (UINT8 *)source+length, d = flippedcol; d < flippedcol+length; --s) - *d++ = *s; + for (UINT8 *s = (UINT8 *)source, *d = flippedcol+length-1; d >= flippedcol; s++) + *d-- = *s; drawcolfunc(); } @@ -729,7 +727,6 @@ void R_DrawFlippedMaskedColumn(column_t *column) INT32 bottomscreen; fixed_t basetexturemid = dc_texturemid; INT32 topdelta, prevdelta = -1; - UINT8 *d,*s; for (; column->topdelta != 0xff ;) { @@ -769,7 +766,7 @@ void R_DrawFlippedMaskedColumn(column_t *column) dc_texturemid = basetexturemid - (topdelta<length, colfunc); + R_DrawFlippedPost((UINT8 *)column+3, column->length, colfunc); } column = (column_t *)((UINT8 *)column + column->length + 4); }