diff --git a/src/deh_tables.c b/src/deh_tables.c index cfc98f631e9d475f403e104425eae189949157bf..e1f4936a8737245c6ad6fa7c08d224b7eb20925c 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4921,6 +4921,7 @@ struct int_const_s const INT_CONST[] = { {"RF_SHADOWDRAW",RF_SHADOWDRAW}, {"RF_SHADOWEFFECTS",RF_SHADOWEFFECTS}, {"RF_DROPSHADOW",RF_DROPSHADOW}, + {"RF_PORTALSPRITE",RF_PORTALSPRITE}, // Level flags {"LF_SCRIPTISFILE",LF_SCRIPTISFILE}, diff --git a/src/doomdef.h b/src/doomdef.h index 46bd5df159090564c53c3182adb2deb8d6e8f39a..bc06f79bc76d9521c978b89e90e9e48a1bdba1ec 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -540,9 +540,6 @@ INT32 I_GetKey(void); // Max gamepad/joysticks that can be detected/used. #define MAX_JOYSTICKS 4 -// Software multithreading -#define MAX_RENDER_CONTEXTS 8 - #ifndef M_PIl #define M_PIl 3.1415926535897932384626433832795029L #endif diff --git a/src/r_context.h b/src/r_context.h index edf01f2bdcea8c82f1773f5f2e702cfed7d86ac8..cd8389d667d6e7ae55f4d070d7e3de43417cce7a 100644 --- a/src/r_context.h +++ b/src/r_context.h @@ -168,13 +168,13 @@ typedef struct wallcontext_s typedef struct rendercontext_s { - // Setup vbuffer_t buffer; - INT32 num; INT32 begincolumn; INT32 endcolumn; + INT16 *sprtopclip, *sprbotclip; + viewcontext_t viewcontext; bspcontext_t bspcontext; planecontext_t planecontext; diff --git a/src/r_defs.h b/src/r_defs.h index e3aa6f5f2e6eb365f4f6c35d920a41e5d86e9568..865c646d2aea44ed26ca70f3c0c9b9c580d79081 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -30,6 +30,8 @@ #include "taglist.h" +#define MAX_PORTAL_RECURSION 12 + // // ClipWallSegment // Clips the given range of columns @@ -61,7 +63,10 @@ typedef UINT8 lighttable_t; typedef struct vbuffer_s { + UINT8 numscreens; + UINT8 *viewbuf, *waterbuf; UINT8 *screens[5]; + boolean isbasebuffer; } vbuffer_t; typedef struct { @@ -757,6 +762,8 @@ typedef enum RF_SHADOWDRAW = 0x00004000, // Stretches and skews the sprite like a shadow. RF_SHADOWEFFECTS = 0x00008000, // Scales and becomes transparent like a shadow. RF_DROPSHADOW = (RF_SHADOWDRAW | RF_SHADOWEFFECTS | RF_FULLDARK), + + RF_PORTALSPRITE = 0x00010000 } renderflags_t; typedef enum diff --git a/src/r_draw.h b/src/r_draw.h index c7355ad9207cb122198f701e77489609923d8557..991302d943e47bbe30ef9a09f814f738e7aa29b0 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -133,9 +133,6 @@ typedef struct colcontext_s INT32 texheight; // vars for R_DrawMaskedColumn - // Rum and Raisin put these on the sprite context. - // I put them on the column context because it felt - // more appropriate (for [REDACTED] anyway) INT16 *mfloorclip; INT16 *mceilingclip; diff --git a/src/r_draw8.c b/src/r_draw8.c index 104d207fd3360581e56ff4bd8238f0596f67c27a..de3cb997e0679ae96c41c9df67763c0c1e1b7ce6 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -40,11 +40,7 @@ void R_DrawColumn_8(colcontext_t *dc) #endif // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - - //dest = ylookup[dc->yl] + columnofs[dc->x]; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &dc->dest->viewbuf[dc->yl*vid.width + dc->x]; count++; @@ -123,11 +119,7 @@ void R_Draw2sMultiPatchColumn_8(colcontext_t *dc) #endif // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - - //dest = ylookup[dc->yl] + columnofs[dc->x]; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &dc->dest->viewbuf[dc->yl*vid.width + dc->x]; count++; @@ -219,11 +211,7 @@ void R_Draw2sMultiPatchTranslucentColumn_8(colcontext_t *dc) #endif // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - - //dest = ylookup[dc->yl] + columnofs[dc->x]; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &dc->dest->viewbuf[dc->yl*vid.width + dc->x]; count++; @@ -321,12 +309,10 @@ void R_DrawShadeColumn_8(colcontext_t *dc) #endif // FIXME. As above. - //dest = ylookup[dc->yl] + columnofs[dc->x]; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &dc->dest->viewbuf[dc->yl*vid.width + dc->x]; // Looks familiar. fracstep = dc->iscale; - //frac = dc->texturemid + (dc->yl - centery)*fracstep; frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep)); // Here we do an additional index re-mapping. @@ -360,8 +346,7 @@ void R_DrawTranslucentColumn_8(colcontext_t *dc) #endif // FIXME. As above. - //dest = ylookup[dc->yl] + columnofs[dc->x]; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &dc->dest->viewbuf[dc->yl*vid.width + dc->x]; // Looks familiar. fracstep = dc->iscale; @@ -431,7 +416,7 @@ void R_DrawDropShadowColumn_8(colcontext_t *dc) if (count <= 0) // Zero length, column does not exceed a pixel. return; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &dc->dest->viewbuf[dc->yl*vid.width + dc->x]; { #define DSCOLOR 31 // palette index for the color of the shadow @@ -465,8 +450,7 @@ void R_DrawTranslatedTranslucentColumn_8(colcontext_t *dc) return; // FIXME. As above. - //dest = ylookup[dc->yl] + columnofs[dc->x]; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &dc->dest->viewbuf[dc->yl*vid.width + dc->x]; // Looks familiar. fracstep = dc->iscale; @@ -541,8 +525,7 @@ void R_DrawTranslatedColumn_8(colcontext_t *dc) #endif // FIXME. As above. - //dest = ylookup[dc->yl] + columnofs[dc->x]; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &dc->dest->viewbuf[dc->yl*vid.width + dc->x]; // Looks familiar. fracstep = dc->iscale; @@ -584,7 +567,7 @@ void R_DrawSpan_8(spancontext_t *ds) UINT8 *source; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); @@ -603,7 +586,7 @@ void R_DrawSpan_8(spancontext_t *ds) source = ds->source; colormap = ds->colormap; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; if (dest+8 > deststop) return; @@ -683,7 +666,7 @@ void R_DrawTiltedSpan_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; source = ds->source; //colormap = ds->colormap; @@ -806,7 +789,7 @@ void R_DrawTiltedTranslucentSpan_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; source = ds->source; //colormap = ds->colormap; @@ -929,8 +912,8 @@ void R_DrawTiltedTranslucentWaterSpan_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; - dsrc = screens[1] + (ds->y+ds->bgofs)*vid.width + ds->x1; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; + dsrc = ds->dest->waterbuf + (ds->y+ds->bgofs)*vid.width + ds->x1; source = ds->source; //colormap = ds->colormap; @@ -1051,7 +1034,7 @@ void R_DrawTiltedSplat_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; source = ds->source; //colormap = ds->colormap; @@ -1168,7 +1151,7 @@ void R_DrawSplat_8(spancontext_t *ds) UINT8 *source; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); UINT32 val; @@ -1188,7 +1171,7 @@ void R_DrawSplat_8(spancontext_t *ds) source = ds->source; colormap = ds->colormap; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; while (count >= 8) { @@ -1288,7 +1271,7 @@ void R_DrawTranslucentSplat_8(spancontext_t *ds) UINT8 *source; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); UINT32 val; @@ -1308,7 +1291,7 @@ void R_DrawTranslucentSplat_8(spancontext_t *ds) source = ds->source; colormap = ds->colormap; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; while (count >= 8) { @@ -1390,7 +1373,7 @@ void R_DrawFloorSprite_8(spancontext_t *ds) UINT8 *colormap; UINT8 *translation; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); UINT32 val; @@ -1411,7 +1394,7 @@ void R_DrawFloorSprite_8(spancontext_t *ds) source = (UINT16 *)ds->source; colormap = ds->colormap; translation = ds->translation; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; while (count >= 8) { @@ -1501,7 +1484,7 @@ void R_DrawTranslucentFloorSprite_8(spancontext_t *ds) UINT8 *colormap; UINT8 *translation; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); UINT32 val; @@ -1522,7 +1505,7 @@ void R_DrawTranslucentFloorSprite_8(spancontext_t *ds) source = (UINT16 *)ds->source; colormap = ds->colormap; translation = ds->translation; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; while (count >= 8) { @@ -1617,7 +1600,7 @@ void R_DrawTiltedFloorSprite_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; source = (UINT16 *)ds->source; colormap = ds->colormap; translation = ds->translation; @@ -1726,7 +1709,7 @@ void R_DrawTiltedTranslucentFloorSprite_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; source = (UINT16 *)ds->source; colormap = ds->colormap; translation = ds->translation; @@ -1821,7 +1804,7 @@ void R_DrawTranslucentSpan_8(spancontext_t *ds) UINT8 *source; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); UINT32 val; @@ -1841,7 +1824,7 @@ void R_DrawTranslucentSpan_8(spancontext_t *ds) source = ds->source; colormap = ds->colormap; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; while (count >= 8) { @@ -1918,8 +1901,8 @@ void R_DrawTranslucentWaterSpan_8(spancontext_t *ds) source = ds->source; colormap = ds->colormap; - dest = ylookup[ds->y] + columnofs[ds->x1]; - dsrc = screens[1] + (ds->y+ds->bgofs)*vid.width + ds->x1; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; + dsrc = ds->dest->waterbuf + (ds->y+ds->bgofs)*vid.width + ds->x1; count = ds->x2 - ds->x1 + 1; while (count >= 8) @@ -1981,8 +1964,7 @@ void R_DrawFogSpan_8(spancontext_t *ds) size_t count; colormap = ds->colormap; - //dest = ylookup[ds->y] + columnofs[ds->x1]; - dest = &topleft[ds->y *vid.width + ds->x1]; + dest = &ds->dest->viewbuf[ds->y *vid.width + ds->x1]; count = ds->x2 - ds->x1 + 1; @@ -2024,10 +2006,7 @@ void R_DrawFogColumn_8(colcontext_t *dc) #endif // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - //dest = ylookup[dc->yl] + columnofs[dc->x]; - dest = &topleft[dc->yl*vid.width + dc->x]; + dest = &dc->dest->viewbuf[dc->yl*vid.width + dc->x]; // Determine scaling, which is the only mapping to be done. do diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 70ac467f3e19a88b98a7ca6d856e220e65929989..c203b7323e796ac89994436e3a114fb6dc421b03 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -32,7 +32,7 @@ void R_DrawSpan_NPO2_8(spancontext_t *ds) UINT8 *source; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); @@ -41,7 +41,7 @@ void R_DrawSpan_NPO2_8(spancontext_t *ds) source = ds->source; colormap = ds->colormap; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; if (dest+8 > deststop) return; @@ -116,7 +116,7 @@ void R_DrawTiltedSpan_NPO2_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; source = ds->source; //colormap = ds->colormap; @@ -306,7 +306,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; source = ds->source; //colormap = ds->colormap; @@ -494,7 +494,7 @@ void R_DrawTiltedSplat_NPO2_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; source = ds->source; //colormap = ds->colormap; @@ -678,7 +678,7 @@ void R_DrawSplat_NPO2_8(spancontext_t *ds) UINT8 *source; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); UINT32 val; @@ -688,7 +688,7 @@ void R_DrawSplat_NPO2_8(spancontext_t *ds) source = ds->source; colormap = ds->colormap; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; fixedwidth = ds->flatwidth << FRACBITS; fixedheight = ds->flatheight << FRACBITS; @@ -746,7 +746,7 @@ void R_DrawTranslucentSplat_NPO2_8(spancontext_t *ds) UINT8 *source; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); UINT32 val; @@ -756,7 +756,7 @@ void R_DrawTranslucentSplat_NPO2_8(spancontext_t *ds) source = ds->source; colormap = ds->colormap; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; fixedwidth = ds->flatwidth << FRACBITS; fixedheight = ds->flatheight << FRACBITS; @@ -815,7 +815,7 @@ void R_DrawFloorSprite_NPO2_8(spancontext_t *ds) UINT8 *translation; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); UINT32 val; @@ -826,7 +826,7 @@ void R_DrawFloorSprite_NPO2_8(spancontext_t *ds) source = (UINT16 *)ds->source; colormap = ds->colormap; translation = ds->translation; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; fixedwidth = ds->flatwidth << FRACBITS; fixedheight = ds->flatheight << FRACBITS; @@ -885,7 +885,7 @@ void R_DrawTranslucentFloorSprite_NPO2_8(spancontext_t *ds) UINT8 *translation; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); UINT32 val; @@ -896,7 +896,7 @@ void R_DrawTranslucentFloorSprite_NPO2_8(spancontext_t *ds) source = (UINT16 *)ds->source; colormap = ds->colormap; translation = ds->translation; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; fixedwidth = ds->flatwidth << FRACBITS; fixedheight = ds->flatheight << FRACBITS; @@ -969,7 +969,7 @@ void R_DrawTiltedFloorSprite_NPO2_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; source = (UINT16 *)ds->source; colormap = ds->colormap; translation = ds->translation; @@ -1125,7 +1125,7 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; source = (UINT16 *)ds->source; colormap = ds->colormap; translation = ds->translation; @@ -1266,7 +1266,7 @@ void R_DrawTranslucentSpan_NPO2_8(spancontext_t *ds) UINT8 *source; UINT8 *colormap; UINT8 *dest; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); UINT32 val; @@ -1276,7 +1276,7 @@ void R_DrawTranslucentSpan_NPO2_8(spancontext_t *ds) source = ds->source; colormap = ds->colormap; - dest = ylookup[ds->y] + columnofs[ds->x1]; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; fixedwidth = ds->flatwidth << FRACBITS; fixedheight = ds->flatheight << FRACBITS; @@ -1331,7 +1331,7 @@ void R_DrawTranslucentWaterSpan_NPO2_8(spancontext_t *ds) UINT8 *colormap; UINT8 *dest; UINT8 *dsrc; - const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + const UINT8 *deststop = ds->dest->viewbuf + vid.rowbytes * vid.height; size_t count = (ds->x2 - ds->x1 + 1); @@ -1340,8 +1340,8 @@ void R_DrawTranslucentWaterSpan_NPO2_8(spancontext_t *ds) source = ds->source; colormap = ds->colormap; - dest = ylookup[ds->y] + columnofs[ds->x1]; - dsrc = screens[1] + (ds->y+ds->bgofs)*vid.width + ds->x1; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; + dsrc = ds->dest->waterbuf + (ds->y+ds->bgofs)*vid.width + ds->x1; fixedwidth = ds->flatwidth << FRACBITS; fixedheight = ds->flatheight << FRACBITS; @@ -1413,8 +1413,8 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(spancontext_t *ds) uz = ds->sup->z + ds->sup->y*(centery-ds->y) + ds->sup->x*(ds->x1-centerx); vz = ds->svp->z + ds->svp->y*(centery-ds->y) + ds->svp->x*(ds->x1-centerx); - dest = ylookup[ds->y] + columnofs[ds->x1]; - dsrc = screens[1] + (ds->y+ds->bgofs)*vid.width + ds->x1; + dest = &ds->dest->viewbuf[ds->y*vid.width + ds->x1]; + dsrc = ds->dest->waterbuf + (ds->y+ds->bgofs)*vid.width + ds->x1; source = ds->source; //colormap = ds->colormap; diff --git a/src/r_main.c b/src/r_main.c index 99f9b0a277dcdf1d495db33e7e0347894b6f842f..50e60a3d75e46f8682a269f3d7b22cf42691fa97 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -40,20 +40,9 @@ #include "hardware/hw_main.h" #endif -//profile stuff --------------------------------------------------------- -//#define TIMING -#ifdef TIMING -#include "p5prof.h" -INT64 mycount; -INT64 mytotal = 0; -//unsigned long nombre = 100000; -#endif -//profile stuff --------------------------------------------------------- - -// Fineangles in the SCREENWIDTH wide window. -#define FIELDOFVIEW 2048 - +#define MAX_RENDER_CONTEXTS MAX_PORTAL_RECURSION static rendercontext_t r_contexts[MAX_RENDER_CONTEXTS]; +UINT8 r_curcontext = 0; // increment every time a check is made size_t validcount = 1; @@ -135,7 +124,7 @@ static CV_PossibleValue_t drawdist_precip_cons_t[] = { static CV_PossibleValue_t fov_cons_t[] = {{60*FRACUNIT, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}}; static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; -static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {MAX_PORTAL_RECURSION, "MAX"}, {0, NULL}}; static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}}; static void Fov_OnChange(void); @@ -454,9 +443,9 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe return false; } -// -// R_InitTextureMapping -// +// Fineangles in the SCREENWIDTH wide window. +#define FIELDOFVIEW 2048 + static void R_InitTextureMapping(void) { INT32 i; @@ -1010,6 +999,11 @@ static void R_ResetContext(rendercontext_t *context, INT32 leftclip, INT32 right context->bspcontext.portalclipstart = leftclip; context->bspcontext.portalclipend = rightclip; + for (INT32 i = 0; i < leftclip; i++) + context->planecontext.ceilingclip[i] = viewheight; + for (INT32 i = rightclip + 1; i < viewwidth; i++) + context->planecontext.floorclip[i] = -1; + R_ClearClipSegs(&context->bspcontext, leftclip, rightclip); } @@ -1038,6 +1032,68 @@ static void R_InitContexts(void) } } +static void R_PrepareViewContext(viewcontext_t *context) +{ + context->x = viewx; + context->y = viewy; + context->z = viewz; + + context->angle = viewangle; + context->sin = viewsin; + context->cos = viewcos; + + context->sector = viewsector; + context->player = viewplayer; + context->mobj = r_viewmobj; +} + +static void R_InitRenderContext(rendercontext_t *context, INT32 begincolumn, INT32 endcolumn) +{ + context->buffer.viewbuf = topleft; + context->buffer.waterbuf = screens[1]; + + for (unsigned i = 0; i < NUMSCREENS; i++) + context->buffer.screens[i] = screens[i]; + + context->buffer.isbasebuffer = true; + context->buffer.numscreens = NUMSCREENS; + + context->colcontext.dest = &context->buffer; + context->spancontext.dest = &context->buffer; + + context->begincolumn = begincolumn; + context->endcolumn = endcolumn; + + R_ResetContext(context, context->begincolumn, context->endcolumn); + + if (context->spritecontext.sectorvisited == NULL) + { + context->spritecontext.sectorvisited = Z_Malloc( + sizeof(boolean) * numsectors, + PU_LEVEL, &context->spritecontext.sectorvisited); + } + + memset(context->spritecontext.sectorvisited, 0, sizeof(boolean) * numsectors); +} + +static void R_PrepareContext(rendercontext_t *context) +{ + R_InitRenderContext(context, 0, viewwidth); + R_PrepareViewContext(&context->viewcontext); +} + +static void R_FreeContextSlopeData(rendercontext_t *context) +{ + spancontext_t *ds = &context->spancontext; + + Z_Free(ds->su); + Z_Free(ds->sv); + Z_Free(ds->sz); + + ds->su = ds->sv = ds->sz = NULL; + ds->sup = ds->svp = ds->szp = NULL; +} + // // R_SetViewSize // Do not really change anything here, @@ -1114,17 +1170,7 @@ void R_ExecuteSetViewSize(void) yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy); } - for (i = 0; i < MAX_RENDER_CONTEXTS; i++) - { - spancontext_t *ds = &r_contexts[i].spancontext; - - Z_Free(ds->su); - Z_Free(ds->sv); - Z_Free(ds->sz); - - ds->su = ds->sv = ds->sz = NULL; - ds->sup = ds->svp = ds->szp = NULL; - } + R_FreeContextSlopeData(&r_contexts[0]); } memset(scalelight, 0xFF, sizeof(scalelight)); @@ -1554,58 +1600,185 @@ boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox) // R_RenderView // ================ -static void R_PrepareViewContext(viewcontext_t *context) +static void R_ClearPlayerView(rendercontext_t *context) { - context->x = viewx; - context->y = viewy; - context->z = viewz; + if (cv_homremoval.value && context->viewcontext.player == &players[displayplayer]) // if this is display player 1 + { + if (cv_homremoval.value == 1) + memset(context->buffer.viewbuf, 31, vid.width * vid.height * vid.bpp); // No HOM effect! + else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted. + memset(context->buffer.viewbuf, 32+(timeinmap&15), vid.width * vid.height * vid.bpp); + } +} - context->angle = viewangle; - context->sin = viewsin; - context->cos = viewcos; +void R_RenderPlayerView(player_t *player) +{ + R_SetupFrame(player); + framecount++; + validcount++; - context->sector = viewsector; - context->player = viewplayer; - context->mobj = r_viewmobj; + R_PrepareContext(&r_contexts[0]); + + // check for new console commands. + NetUpdate(); + + R_ClearPlayerView(&r_contexts[0]); + R_RenderViewContext(&r_contexts[0]); + + while (r_curcontext) + R_FinishAltView(); } -static void R_PrepareContext(rendercontext_t *context) +static void R_CopyContextClip( + size_t start, size_t length, + INT16 *topdest, INT16 *botdest, + INT16 *cliptop, INT16 *clipbot) { - context->buffer.screens[0] = topleft; - for (unsigned i = 1; i < NUMSCREENS; i++) - context->buffer.screens[i] = screens[i]; + M_Memcpy(topdest, cliptop + start, length * sizeof(INT16)); + M_Memcpy(botdest, clipbot + start, length * sizeof(INT16)); +} - context->begincolumn = 0; - context->endcolumn = viewwidth; +static void R_AllocVBuffer(rendercontext_t *context, UINT8 numscreens) +{ + context->buffer.numscreens = numscreens; + context->buffer.isbasebuffer = false; - R_ResetContext(context, context->begincolumn, context->endcolumn); - R_PrepareViewContext(&context->viewcontext); + for (UINT8 i = 0; i < numscreens; i++) + { + void *screen = malloc(vid.rowbytes*vid.height); + if (!screen) + I_Error("R_AllocVBuffer: Out of memory for buffer %d", i); - if (context->spritecontext.sectorvisited == NULL) - context->spritecontext.sectorvisited = Z_Calloc(sizeof(boolean) * numsectors, PU_LEVEL, NULL); - memset(context->spritecontext.sectorvisited, 0, sizeof(boolean) * numsectors); + context->buffer.screens[i] = screen; + } + + context->buffer.viewbuf = context->buffer.screens[0] + viewwindowy*vid.width + viewwindowx; + context->buffer.waterbuf = context->buffer.screens[1]; } -void R_RenderPlayerView(player_t *player) +static void R_CopyViewContext(viewcontext_t *thisvctx, viewcontext_t *viewctx) { - if (cv_homremoval.value && player == &players[displayplayer]) // if this is display player 1 + thisvctx->x = viewctx->x; + thisvctx->y = viewctx->y; + thisvctx->z = viewctx->z; + + thisvctx->angle = viewctx->angle; + thisvctx->sin = viewctx->sin; + thisvctx->cos = viewctx->cos; + + thisvctx->sector = viewctx->sector; + thisvctx->player = viewctx->player; + thisvctx->mobj = viewctx->mobj; +} + +boolean R_NewAltView(INT32 left, INT32 right, INT16 *cliptop, INT16 *clipbot, viewcontext_t *viewctx, boolean allocvbuf) +{ + if (r_curcontext == min(MAX_RENDER_CONTEXTS, cv_maxportals.value)-1) + return false; + + left = max(0, left); + right = min(right, viewwidth); + + unsigned length = right - left; + + // Nahhhh bruh fr? On God?? + if (!length || left >= right) + return false; + + r_curcontext++; + rendercontext_t *context = &r_contexts[r_curcontext]; + + R_InitRenderContext(context, left, right); + R_CopyViewContext(&context->viewcontext, viewctx); + + if (allocvbuf) { - if (cv_homremoval.value == 1) - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // No HOM effect! - else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted. - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 32+(timeinmap&15)); + R_AllocVBuffer(context, 2); + R_ClearPlayerView(context); } - R_SetupFrame(player); - framecount++; - validcount++; + R_CopyContextClip(left, length, + context->planecontext.ceilingclip + left, + context->planecontext.floorclip + left, + cliptop, clipbot); - R_PrepareContext(&r_contexts[0]); + context->sprtopclip = malloc(length * sizeof(INT16)); + context->sprbotclip = malloc(length * sizeof(INT16)); - // check for new console commands. - NetUpdate(); + if (!context->sprtopclip) + I_Error("R_NewAltView: Out of memory for sprtopclip"); + if (!context->sprbotclip) + I_Error("R_NewAltView: Out of memory for sprbotclip"); - R_RenderViewContext(&r_contexts[0]); + R_CopyContextClip(left, length, + context->sprtopclip, context->sprbotclip, + cliptop, clipbot); + + return true; +} + +void R_RenderAltView(void) +{ + R_RenderViewContext(&r_contexts[r_curcontext]); +} + +static void R_DrawAltViewColumn(rendercontext_t *context, UINT8 *transmap, UINT8 *srcbuf, INT32 x, INT16 top, INT16 bottom) +{ + if (top < 0) + top = 0; + if (bottom >= vid.height) + bottom = vid.height - 1; + + INT32 count = bottom - top + 1; + if (count <= 0) + return; + + UINT8 *dest = &context->buffer.viewbuf[top*vid.width + x]; + UINT8 *source = &srcbuf[top*vid.width + x]; + + while (count--) + { + *dest = *(transmap + ((*source)<<8) + (*dest)); + dest += vid.width; + source += vid.width; + } +} + +void R_BlitAltView(rendercontext_t *curctx, UINT8 *transmap) +{ + rendercontext_t *altctx = &r_contexts[r_curcontext]; + + INT32 start = altctx->begincolumn; + INT32 left = max(start, curctx->begincolumn); + INT32 right = min(altctx->endcolumn, curctx->endcolumn); + + for (INT32 x = left; x < right; x++) + { + R_DrawAltViewColumn(curctx, transmap, altctx->buffer.viewbuf, x, + altctx->sprtopclip[x - start]+1, altctx->sprbotclip[x - start]-1); + } +} + +void R_FinishAltView(void) +{ + if (r_curcontext == 0) + return; + + rendercontext_t *context = &r_contexts[r_curcontext]; + + R_FreeContextSlopeData(context); + Z_Free(context->spritecontext.sectorvisited); + + free(context->sprtopclip); + free(context->sprbotclip); + + if (!context->buffer.isbasebuffer) + { + for (UINT8 i = 0; i < context->buffer.numscreens; i++) + free(context->buffer.screens[i]); + } + + r_curcontext--; } // ========================================================================= diff --git a/src/r_main.h b/src/r_main.h index e183a75f4cc5a18d605ec1d49c97b71a1225cf5f..81ddba16d999737437e744bb53782287032f3ef1 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -16,6 +16,7 @@ #include "d_player.h" #include "r_data.h" +#include "r_context.h" #include "r_textures.h" #include "m_perfstats.h" // ps_metric_t @@ -135,6 +136,11 @@ boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox); // Called by D_Display. void R_RenderPlayerView(player_t *player); +boolean R_NewAltView(INT32 left, INT32 right, INT16 *cliptop, INT16 *clipbot, viewcontext_t *viewctx, boolean allocvbuf); +void R_BlitAltView(rendercontext_t *context, UINT8 *transmap); +void R_RenderAltView(void); +void R_FinishAltView(void); + // add commands related to engine, at game startup void R_RegisterEngineStuff(void); #endif diff --git a/src/r_plane.c b/src/r_plane.c index c85ab8a8ff50ccc9b5d78075a5e688ac7bd32355..dc932750f9fd8122019e432263ba4e3d264de8b7 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -853,8 +853,12 @@ void R_DrawSinglePlane(rendercontext_t *context, visplane_t *pl) if (bottom > vid.height) bottom = vid.height; + UINT8 *src = (splitscreen && context->viewcontext.player == &players[secondarydisplayplayer]) + ? context->buffer.screens[0] + (top+(vid.height>>1))*vid.width + : context->buffer.screens[0] + ((top)*vid.width); + // Only copy the part of the screen we need - VID_BlitLinearScreen((splitscreen && context->viewcontext.player == &players[secondarydisplayplayer]) ? screens[0] + (top+(vid.height>>1))*vid.width : screens[0]+((top)*vid.width), screens[1]+((top)*vid.width), + VID_BlitLinearScreen(src, context->buffer.waterbuf+((top)*vid.width), vid.width, bottom-top, vid.width, vid.width); } diff --git a/src/r_portal.h b/src/r_portal.h index 9b99de2effbb6c25f74e54b67e186c9ba27f69ff..e244e29f4abaab2c5a5ae485d9ea40a5eb9cb086 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -56,4 +56,5 @@ void Portal_ClipRange (struct planecontext_s *planecontext, portal_t* portal); void Portal_ClipApply (struct planecontext_s *planecontext, const portal_t* portal); void Portal_AddSkyboxPortals (struct rendercontext_s *context); + #endif diff --git a/src/r_segs.c b/src/r_segs.c index 719229292e1cb1eacb28123a48ed28e762735c55..d9ca5d048602e5e36583ba2ec713528b75415fad 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -1305,6 +1305,10 @@ static void R_RenderSegLoop(rendercontext_t *context, wallcontext_t *wallcontext planecontext->frontscale[currx] = wallcontext->scale; + // FIXME: Why is this < 0 sometimes? + if (yl < 0) + yl = 0; + // draw the wall tiers if (segcontext->midtexture) { @@ -1386,6 +1390,10 @@ static void R_RenderSegLoop(rendercontext_t *context, wallcontext_t *wallcontext if (mid <= planecontext->ceilingclip[currx]) mid = planecontext->ceilingclip[currx]+1; + // FIXME: Why is this < 0 sometimes? + if (mid < 0) + mid = 0; + if (mid <= yh) // back floor higher than front floor ? { if (yh < 0) // entirely off top of screen @@ -1521,8 +1529,8 @@ void R_StoreWallRange(rendercontext_t *context, wallcontext_t *wallcontext, INT3 sector_t *frontsector = bspcontext->frontsector; sector_t *backsector = bspcontext->backsector; - INT32 worldtop, worldbottom, worldhigh, worldlow; - INT32 worldtopslope, worldbottomslope, worldhighslope, worldlowslope; // worldtop/bottom at end of slope + INT32 worldtop, worldbottom, worldhigh = 0, worldlow = 0; + INT32 worldtopslope, worldbottomslope, worldhighslope = 0, worldlowslope = 0; // worldtop/bottom at end of slope drawseg_t *ds_p; segloopcontext_t loopcontext; diff --git a/src/r_state.h b/src/r_state.h index 519421ff9f736881296c2bd84fe6c3d1e43af1de..4d1fe7e008872cae9ae4200e93c4bab14a6aee16 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -99,4 +99,6 @@ extern angle_t doubleclipangle; extern INT32 viewangletox[FINEANGLES/2]; extern angle_t xtoviewangle[MAXVIDWIDTH+1]; +extern UINT8 r_curcontext; + #endif diff --git a/src/r_things.c b/src/r_things.c index a84325f10a20c9fd842af21cd7b0411c2b7f94de..44fef3a1268b430f006e538358956e6b86838cbc 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -964,6 +964,325 @@ static void R_DrawVisSprite(rendercontext_t *context, vissprite_t *vis) vis->x2 = x2; } +static void R_ClipPortalSpriteColumn(colcontext_t *dc, column_t *column, INT32 x, INT32 *prevdelta, INT16 *top, INT16 *bot) +{ + INT32 topdelta = column->topdelta; + if (topdelta <= *prevdelta) + topdelta += *prevdelta; + *prevdelta = topdelta; + + INT32 topscreen = dc->sprtopscreen + dc->spryscale*topdelta; + INT32 bottomscreen = topscreen + dc->spryscale*column->length; + + INT32 yl = (topscreen+FRACUNIT-1)>>FRACBITS; + INT32 yh = (bottomscreen-1)>>FRACBITS; + + if (yh >= dc->mfloorclip[x]) + yh = dc->mfloorclip[x]-1; + if (yl <= dc->mceilingclip[x]) + yl = dc->mceilingclip[x]+1; + if (yl < 0) + yl = 0; + if (yh >= vid.height) // yl must be < vid.height, so reduces number of checks in tight loop + yh = vid.height - 1; + + if (yl <= yh && yh > 0) + { + if (top) + *top = yl; + if (bot) + *bot = yh; + } + else + { + if (top) + *top = -1; + if (bot) + *bot = -1; + } +} + +static void R_ClipPortalSpriteColumnFlipped(colcontext_t *dc, column_t *column, INT32 x, INT32 *prevdelta, INT16 *top, INT16 *bot) +{ + INT32 topdelta = column->topdelta; + if (topdelta <= *prevdelta) + topdelta += *prevdelta; + *prevdelta = topdelta; + topdelta = dc->lengthcol-column->length-topdelta; + + INT32 topscreen = dc->sprtopscreen + dc->spryscale*topdelta; + INT32 bottomscreen = topscreen + dc->spryscale*column->length; + + INT32 yl = (topscreen+FRACUNIT-1)>>FRACBITS; + INT32 yh = (bottomscreen-1)>>FRACBITS; + + if (yh >= dc->mfloorclip[x]) + yh = dc->mfloorclip[x]-1; + if (yl <= dc->mceilingclip[x]) + yl = dc->mceilingclip[x]+1; + if (yl < 0) + yl = 0; + if (yh >= vid.height) // yl must be < vid.height, so reduces number of checks in tight loop + yh = vid.height - 1; + + if (yl <= yh && yh > 0) + { + if (top) + *top = yl; + if (bot) + *bot = yh; + } + else + { + if (top) + *top = -1; + if (bot) + *bot = -1; + } +} + +static void R_AddPortalSpriteColumn(colcontext_t *dc, column_t *column, INT32 x, INT16 *cliptop, INT16 *clipbot, + void (*clipfunc)(colcontext_t *, column_t *, INT32, INT32 *, INT16 *, INT16 *)) +{ + INT32 prevdelta = 0; + INT16 firstrow = -1, lastrow = -1; + + column_t *first = column; + + for (;;) + { + if (first->topdelta == 0xff) + { + cliptop[x] = vid.height; + clipbot[x] = -1; + return; + } + + clipfunc(dc, first, x, &prevdelta, &firstrow, &lastrow); + + if (firstrow == -1) + first = (column_t *)((UINT8 *)first + first->length + 4); + else + break; + } + + column = first; + + for (;;) + { + column_t *next = (column_t *)((UINT8 *)column + column->length + 4); + + if (next->topdelta == 0xff) + { + if (column != first) + clipfunc(dc, column, x, &prevdelta, NULL, &lastrow); + break; + } + + column = next; + } + + if (lastrow == -1) + firstrow = vid.height + 1; + + cliptop[x] = firstrow - 1; + clipbot[x] = lastrow + 1; +} + +static void R_RenderPortalSprite(rendercontext_t *context, vissprite_t *vis) +{ + colcontext_t *dc = &context->colcontext; + column_t *column; + void (*localclipfunc)(colcontext_t *, column_t *, INT32, INT32 *, INT16 *, INT16 *); + INT32 texturecolumn; + INT32 pwidth; + fixed_t frac; + patch_t *patch = vis->patch; + fixed_t this_scale = vis->thingscale; + fixed_t texturemid = vis->texturemid; + INT32 x, x1, x2; + INT64 overflow_test; + + if (!patch) + return; + + // Check for overflow + overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*vis->scale)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // fixed point mult would overflow + + if (vis->scalestep) // handles right edge too + { + overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*(vis->scale + (vis->scalestep*(vis->x2 - vis->x1))))>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto + } + + frac = vis->startfrac; + + if (vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES) + this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->skin)->highresscale); + if (this_scale <= 0) + this_scale = 1; + if (this_scale != FRACUNIT) + { + if (!(vis->cut & SC_ISSCALED)) + { + vis->scale = FixedMul(vis->scale, this_scale); + vis->scalestep = FixedMul(vis->scalestep, this_scale); + vis->xiscale = FixedDiv(vis->xiscale,this_scale); + vis->cut |= SC_ISSCALED; + } + texturemid = FixedDiv(texturemid,this_scale); + } + + dc->spryscale = vis->scale; + + if (!(vis->scalestep)) + { + dc->sprtopscreen = centeryfrac - FixedMul(texturemid, dc->spryscale); + dc->sprtopscreen += vis->shear.tan * vis->shear.offset; + } + + x1 = vis->x1; + x2 = vis->x2; + + if (vis->x1 < 0) + { + dc->spryscale += vis->scalestep*(-vis->x1); + vis->x1 = 0; + } + + if (vis->x2 >= vid.width) + vis->x2 = vid.width-1; + + localclipfunc = (vis->cut & SC_VFLIP) ? R_ClipPortalSpriteColumnFlipped : R_ClipPortalSpriteColumn; + dc->lengthcol = patch->height; + + INT16 cliptop[MAXVIDWIDTH], clipbot[MAXVIDWIDTH]; + + // Split drawing loops for paper and non-paper to reduce conditional checks per sprite + if (vis->scalestep) + { + fixed_t horzscale = FixedMul(vis->spritexscale, this_scale); + fixed_t scalestep = FixedMul(vis->scalestep, vis->spriteyscale); + + pwidth = patch->width; + + // Papersprite drawing loop + for (x = vis->x1; x <= vis->x2; x++, dc->spryscale += scalestep) + { + angle_t angle = ((vis->centerangle + xtoviewangle[x]) >> ANGLETOFINESHIFT) & 0xFFF; + texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / horzscale; + + if (texturecolumn < 0 || texturecolumn >= pwidth) + { + cliptop[x] = vid.height; + clipbot[x] = -1; + continue; + } + + if (vis->xiscale < 0) // Flipped sprite + texturecolumn = pwidth - 1 - texturecolumn; + + dc->sprtopscreen = (centeryfrac - FixedMul(texturemid, dc->spryscale)); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); + + R_AddPortalSpriteColumn(dc, column, x, cliptop, clipbot, localclipfunc); + } + } + else if (vis->cut & SC_SHEAR) + { +#ifdef RANGECHECK + pwidth = patch->width; +#endif + + // Vertically sheared sprite + for (x = vis->x1; x <= vis->x2; x++, frac += vis->xiscale, texturemid -= vis->shear.tan) + { +#ifdef RANGECHECK + texturecolumn = frac>>FRACBITS; + if (texturecolumn < 0 || texturecolumn >= pwidth) + I_Error("R_RenderPortalSprite: bad texturecolumn at %d from end", vis->x2 - x); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); +#else + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); +#endif + + dc->sprtopscreen = (centeryfrac - FixedMul(texturemid, dc->spryscale)); + R_AddPortalSpriteColumn(dc, column, x, cliptop, clipbot, localclipfunc); + } + } + else + { +#ifdef RANGECHECK + pwidth = patch->width; +#endif + + // Non-paper drawing loop + for (x = vis->x1; x <= vis->x2; x++, frac += vis->xiscale, dc->sprtopscreen += vis->shear.tan) + { +#ifdef RANGECHECK + texturecolumn = frac>>FRACBITS; + if (texturecolumn < 0 || texturecolumn >= pwidth) + I_Error("R_RenderPortalSprite: bad texturecolumn at %d from end", vis->x2 - x); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); +#else + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); +#endif + R_AddPortalSpriteColumn(dc, column, x, cliptop, clipbot, localclipfunc); + } + } + + mobj_t *source = vis->mobj; + mobj_t *target = source->target; + boolean altview = false; + + if (context->bspcontext.portalrender < cv_maxportals.value + && vis->x1 <= vis->x2 + && target != NULL && !P_MobjWasRemoved(target) && target != source) + { + angle_t dangle = target->angle - source->angle; + + fixed_t disttopoint = R_PointToDist2(source->x, source->y, context->viewcontext.x, context->viewcontext.y); + angle_t angtopoint = R_PointToAngle2(source->x, source->y, context->viewcontext.x, context->viewcontext.y); + angtopoint += dangle; + + viewcontext_t viewctx; + + viewctx.x = target->x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); + viewctx.y = target->y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); + viewctx.z = context->viewcontext.z + target->z - source->z; + viewctx.angle = context->viewcontext.angle + dangle; + viewctx.sin = FINESINE(viewctx.angle>>ANGLETOFINESHIFT); + viewctx.cos = FINECOSINE(viewctx.angle>>ANGLETOFINESHIFT); + viewctx.sector = R_PointInSubsector(viewctx.x, viewctx.y)->sector; + viewctx.player = context->viewcontext.player; + viewctx.mobj = target; + + UINT8 *transmap = vis->transmap; + + if (R_NewAltView(x1, x2+1, cliptop, clipbot, &viewctx, transmap != NULL)) + { + context->bspcontext.portalrender++; + + R_RenderAltView(); + if (transmap) + R_BlitAltView(context, transmap); + R_FinishAltView(); + + context->bspcontext.portalrender--; + altview = true; + } + } + + vis->x1 = x1; + vis->x2 = x2; + + if (!altview) + R_DrawVisSprite(context, vis); +} + // Special precipitation drawer Tails 08-18-2002 static void R_DrawPrecipitationVisSprite(rendercontext_t *context, vissprite_t *vis) { @@ -1216,7 +1535,7 @@ static void R_ProjectDropShadow(spritecontext_t *spritecontext, viewcontext_t *v groundz = R_GetShadowZ(thing, &groundslope); - if (abs(groundz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes + if (abs(groundz-viewcontext->z)/tz > 4) return; // Prevent stretchy shadows and possible crashes floordiff = abs((isflipped ? thing->height : 0) + thing->z - groundz); @@ -1229,7 +1548,7 @@ static void R_ProjectDropShadow(spritecontext_t *spritecontext, viewcontext_t *v xscale = FixedDiv(projection, tz); yscale = FixedDiv(projectiony, tz); shadowxscale = FixedMul(thing->radius*2, scalemul); - shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz)); + shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(groundz - viewcontext->z), tz)); shadowyscale = min(shadowyscale, shadowxscale) / patch->height; shadowxscale /= patch->width; shadowskew = 0; @@ -1262,7 +1581,7 @@ static void R_ProjectDropShadow(spritecontext_t *spritecontext, viewcontext_t *v shadow->gy = thing->y; shadow->gzt = (isflipped ? shadow->pzt : shadow->pz) + patch->height * shadowyscale / 2; shadow->gz = shadow->gzt - patch->height * shadowyscale; - shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); + shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewcontext->z, shadowyscale)); if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) shadow->texturemid = FixedMul(shadow->texturemid, ((skin_t *)thing->skin)->highresscale); shadow->scalestep = 0; @@ -1277,8 +1596,8 @@ static void R_ProjectDropShadow(spritecontext_t *spritecontext, viewcontext_t *v shadow->scale = FixedMul(yscale, shadowyscale); shadow->thingscale = thing->scale; shadow->sector = vis->sector; - shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewz, yscale))>>FRACBITS); - shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS); + shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewcontext->z, yscale))>>FRACBITS); + shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewcontext->z, yscale))>>FRACBITS); shadow->cut = SC_ISSCALED|SC_SHADOW; //check this shadow->startfrac = 0; @@ -1879,7 +2198,7 @@ static void R_ProjectSprite(rendercontext_t *context, mobj_t *thing) } heightsec = thing->subsector->sector->heightsec; - if (view_plr->mo && view_plr->mo->subsector) + if (view_plr && view_plr->mo && view_plr->mo->subsector) phs = view_plr->mo->subsector->sector->heightsec; else phs = -1; @@ -2017,6 +2336,8 @@ static void R_ProjectSprite(rendercontext_t *context, mobj_t *thing) vis->cut |= SC_VFLIP; if (splat) vis->cut |= SC_SPLAT; // I like ya cut g + if (vis->renderflags & RF_PORTALSPRITE && context->bspcontext.portalrender < cv_maxportals.value) + vis->cut |= SC_PORTAL; vis->patch = patch; @@ -2777,7 +3098,9 @@ static void R_DrawSprite(rendercontext_t *context, vissprite_t *spr) context->colcontext.mfloorclip = spr->clipbot; context->colcontext.mceilingclip = spr->cliptop; - if (spr->cut & SC_SPLAT) + if (spr->cut & SC_PORTAL) + R_RenderPortalSprite(context, spr); + else if (spr->cut & SC_SPLAT) R_DrawFloorSplat(context, spr); else R_DrawVisSprite(context, spr); @@ -2792,9 +3115,9 @@ static void R_DrawPrecipitationSprite(rendercontext_t *context, vissprite_t *spr R_DrawPrecipitationVisSprite(context, spr); } -// R_ClipVisSprite +// R_ClipSingleSprite // Clips vissprites without drawing, so that portals can work. -Red -static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, rendercontext_t *context, drawseg_t *dsstart, portal_t *portal) +static void R_ClipSingleSprite(vissprite_t *spr, INT32 x1, INT32 x2, rendercontext_t *context, drawseg_t *dsstart, portal_t *portal) { drawseg_t *ds; INT32 x; @@ -2991,6 +3314,21 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, rendercontext_ spr->cliptop[x] = -1; } } + + if (r_curcontext) + { + INT32 begin = context->begincolumn; + INT32 start_index = max(begin, x1); + INT32 end_index = min(begin + context->endcolumn - begin, x2); + + for (x = start_index; x <= end_index; x++) + { + if (spr->clipbot[x] > context->sprbotclip[x - begin]) + spr->clipbot[x] = context->sprbotclip[x - begin]; + if (spr->cliptop[x] < context->sprtopclip[x - begin]) + spr->cliptop[x] = context->sprtopclip[x - begin]; + } + } } void R_ClipSprites(rendercontext_t *context, drawseg_t *dsstart, portal_t *portal) @@ -3002,7 +3340,7 @@ void R_ClipSprites(rendercontext_t *context, drawseg_t *dsstart, portal_t *porta vissprite_t *spr = R_GetVisSprite(spritecontext, spritecontext->clippedvissprites); INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1; INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth-1 : spr->x2; - R_ClipVisSprite(spr, x1, x2, context, dsstart, portal); + R_ClipSingleSprite(spr, x1, x2, context, dsstart, portal); } } diff --git a/src/r_things.h b/src/r_things.h index 04725dfca011799c729c599a7f89c81620b3de78..2f08ab83fca52aca7ab5d8d84411fc512ebb13e4 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -127,6 +127,7 @@ typedef enum SC_SHADOW = 1<<10, SC_SHEAR = 1<<11, SC_SPLAT = 1<<12, + SC_PORTAL = 1<<13, // masks SC_CUTMASK = SC_TOP|SC_BOTTOM, SC_FLAGMASK = ~SC_CUTMASK