diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e208a91b6..da8965454 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1692,7 +1692,7 @@ static void HWR_ProcessSeg(void) { blendmode = PF_Masked; - if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) + if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) { blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent; Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255)); @@ -1849,7 +1849,7 @@ static void HWR_ProcessSeg(void) { blendmode = PF_Masked; - if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) + if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) { blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent; Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255)); @@ -2530,7 +2530,7 @@ static void HWR_Subsector(size_t num) alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, false, rover->master->frontsector->extra_colormap); } - else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) // SoM: Flags are more efficient + else if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) // SoM: Flags are more efficient { light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); @@ -2576,7 +2576,7 @@ static void HWR_Subsector(size_t num) alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, false, rover->master->frontsector->extra_colormap); } - else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) + else if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) { light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false); diff --git a/src/r_draw.h b/src/r_draw.h index 00032e44f..d5c5b4e25 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -173,6 +173,7 @@ void R_DrawTiltedTranslucentSpan_8(void); void R_DrawSplat_8(void); void R_DrawTranslucentSplat_8(void); void R_DrawTiltedSplat_8(void); +void R_DrawTiltedTranslucentSplat_8(void); void R_DrawFloorSprite_8(void); void R_DrawTranslucentFloorSprite_8(void); @@ -194,6 +195,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void); void R_DrawSplat_NPO2_8(void); void R_DrawTranslucentSplat_NPO2_8(void); void R_DrawTiltedSplat_NPO2_8(void); +void R_DrawTiltedTranslucentSplat_NPO2_8(void); void R_DrawFloorSprite_NPO2_8(void); void R_DrawTranslucentFloorSprite_NPO2_8(void); diff --git a/src/r_draw8.c b/src/r_draw8.c index 220878f88..c720f454e 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1301,6 +1301,136 @@ void R_DrawTiltedSplat_8(void) #endif } +void R_DrawTiltedTranslucentSplat_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + + UINT8 val; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx); + uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); + vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); + + R_CalcSlopeLight(); + + dest = &topleft[ds_y*vid.width + ds_x1]; + source = ds_source; + //colormap = ds_colormap; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z); + v = (INT64)(vz*z); + + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + + dest++; + iz += ds_sz.x; + uz += ds_su.x; + vz += ds_sv.x; + } while (--width >= 0); +#else + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_sz.x * SPANSIZE; + uzstep = ds_su.x * SPANSIZE; + vzstep = ds_sv.x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu); + v = (INT64)(startv); + + for (i = SPANSIZE-1; i >= 0; i--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + } + else + { + double left = width; + iz += ds_sz.x * left; + uz += ds_su.x * left; + vz += ds_sv.x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu); + v = (INT64)(startv); + + for (; width != 0; width--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + u += stepu; + v += stepv; + } + } + } +#endif +} + /** \brief The R_DrawSplat_8 function Just like R_DrawSpan_8, but skips transparent pixels. */ diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 6213ecbc5..7fbb40d84 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -666,6 +666,204 @@ void R_DrawTiltedSplat_NPO2_8(void) #endif } +void R_DrawTiltedTranslucentSplat_NPO2_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + + UINT8 val; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth); + struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight); + + iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx); + uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); + vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); + + R_CalcSlopeLight(); + + dest = &topleft[ds_y*vid.width + ds_x1]; + source = ds_source; + //colormap = ds_colormap; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z); + v = (INT64)(vz*z); + + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + + dest++; + iz += ds_sz.x; + uz += ds_su.x; + vz += ds_sv.x; + } while (--width >= 0); +#else + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_sz.x * SPANSIZE; + uzstep = ds_su.x * SPANSIZE; + vzstep = ds_sv.x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu); + v = (INT64)(startv); + + for (i = SPANSIZE-1; i >= 0; i--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + } + else + { + double left = width; + iz += ds_sz.x * left; + uz += ds_su.x * left; + vz += ds_sv.x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu); + v = (INT64)(startv); + + for (; width != 0; width--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + u += stepu; + v += stepv; + } + } + } +#endif +} + /** \brief The R_DrawSplat_NPO2_8 function Just like R_DrawSpan_NPO2_8, but skips transparent pixels. */ diff --git a/src/r_plane.c b/src/r_plane.c index 380f39eab..7642a4dd6 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -1079,6 +1079,9 @@ void R_DrawSinglePlane(visplane_t *pl) case SPANDRAWFUNC_SPLAT: spanfunctype = SPANDRAWFUNC_TILTEDSPLAT; break; + case SPANDRAWFUNC_TRANSSPLAT: + spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPLAT; + break; case SPANDRAWFUNC_SOLID: spanfunctype = SPANDRAWFUNC_TILTEDSOLID; break; diff --git a/src/screen.c b/src/screen.c index a2c1f04da..781d22335 100644 --- a/src/screen.c +++ b/src/screen.c @@ -124,6 +124,7 @@ void SCR_SetDrawFuncs(void) spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8; spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8; spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8; + spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTiltedTranslucentSplat_8; spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8; spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8; spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8; @@ -146,6 +147,7 @@ void SCR_SetDrawFuncs(void) spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTiltedTranslucentSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_NPO2_8; diff --git a/src/screen.h b/src/screen.h index 6d45560c4..3ce593a52 100644 --- a/src/screen.h +++ b/src/screen.h @@ -115,6 +115,7 @@ enum SPANDRAWFUNC_SPLAT, SPANDRAWFUNC_TRANSSPLAT, SPANDRAWFUNC_TILTEDSPLAT, + SPANDRAWFUNC_TILTEDTRANSSPLAT, SPANDRAWFUNC_SPRITE, SPANDRAWFUNC_TRANSSPRITE,