Vissprite clipping improvements.

Vissprites are now only clipped against their respective portal's geometry obtained from their BSP run.
Additionally, if a portal is provided, they're clipped to the portal's clip boundaries.
The work on this branch should conclude after a pair of remaining glitches are fixed.
This commit is contained in:
Nev3r 2019-06-05 16:35:48 +02:00
parent 25b56ffecd
commit 1c14062e8b
5 changed files with 77 additions and 44 deletions

View file

@ -1061,8 +1061,7 @@ void R_RenderPlayerView(player_t *player)
masks[nummasks - 1].drawsegs[1] = ds_p - drawsegs; masks[nummasks - 1].drawsegs[1] = ds_p - drawsegs;
masks[nummasks - 1].vissprites[1] = visspritecount; masks[nummasks - 1].vissprites[1] = visspritecount;
R_ClipSprites(drawsegs, NULL);
R_ClipSprites();
#ifdef TIMING #ifdef TIMING
RDMSR(0x10, &mycount); RDMSR(0x10, &mycount);
mytotal += mycount; // 64bit add mytotal += mycount; // 64bit add
@ -1108,7 +1107,8 @@ void R_RenderPlayerView(player_t *player)
R_RenderBSPNode((INT32)numnodes - 1); R_RenderBSPNode((INT32)numnodes - 1);
masks[nummasks - 1].drawsegs[1] = ds_p - drawsegs; masks[nummasks - 1].drawsegs[1] = ds_p - drawsegs;
masks[nummasks - 1].vissprites[1] = visspritecount; masks[nummasks - 1].vissprites[1] = visspritecount;
R_ClipSprites();
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
Portal_Remove(portal); Portal_Remove(portal);
} }

View file

@ -17,6 +17,7 @@
#include "doomstat.h" #include "doomstat.h"
#include "p_spec.h" // Skybox viewpoints #include "p_spec.h" // Skybox viewpoints
#include "z_zone.h" #include "z_zone.h"
#include "r_things.h"
UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */ UINT8 portalrender; /**< When rendering a portal, it establishes the depth of the current BSP traversal. */
sector_t *portalcullsector; sector_t *portalcullsector;
@ -98,9 +99,9 @@ void Portal_ClipApply (const portal_t* portal)
portal_t* Portal_Add (const INT16 x1, const INT16 x2) portal_t* Portal_Add (const INT16 x1, const INT16 x2)
{ {
portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL); portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL);
INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL); INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL);
INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL); INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL);
fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1), PU_LEVEL, NULL); fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL);
// Linked list. // Linked list.
if (!portal_base) if (!portal_base)
@ -199,15 +200,7 @@ static void Portal_ClipVisplane (const visplane_t* plane, portal_t* portal)
for (i = 0; i < end - start; i++) for (i = 0; i < end - start; i++)
{ {
if (plane->bottom[i + start] == 0) portal->ceilingclip[i] = plane->top[i + start];
{
portal->ceilingclip[i] = 0;
portal->floorclip[i] = 0;
continue;
}
portal->ceilingclip[i] = plane->top[i + start] - 1;
portal->floorclip[i] = plane->bottom[i + start] + 1; portal->floorclip[i] = plane->bottom[i + start] + 1;
portal->frontscale[i] = INT32_MAX; portal->frontscale[i] = INT32_MAX;
} }
@ -230,6 +223,25 @@ void Portal_AddSkybox (const visplane_t* plane)
if (!(start < end)) if (!(start < end))
return; return;
/** Trims a visplane's horizontal gap to match its render area.
*
* Visplanes' minx/maxx may sometimes exceed the area they're
* covering. This merely adjusts the boundaries to the next
* valid area.
*/
while (plane->bottom[start] == 0 && plane->top[start] == 65535 && start < end)
{
start++;
}
while (plane->bottom[end - 1] == 0 && plane->top[start] == 65535 && end > start)
{
end--;
}
portal = Portal_Add(start, end); portal = Portal_Add(start, end);
Portal_ClipVisplane(plane, portal); Portal_ClipVisplane(plane, portal);

View file

@ -11,6 +11,9 @@
/// \file r_portal.h /// \file r_portal.h
/// \brief Software renderer portal struct, functions, linked list extern. /// \brief Software renderer portal struct, functions, linked list extern.
#ifndef __R_PORTAL__
#define __R_PORTAL__
#include "r_data.h" #include "r_data.h"
#include "r_plane.h" // visplanes #include "r_plane.h" // visplanes
@ -52,3 +55,5 @@ void Portal_AddSkybox (const visplane_t* plane);
void Portal_ClipRange (portal_t* portal); void Portal_ClipRange (portal_t* portal);
void Portal_ClipApply (const portal_t* portal); void Portal_ClipApply (const portal_t* portal);
#endif

View file

@ -2185,7 +2185,7 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr)
// R_ClipSprites // R_ClipSprites
// Clips vissprites without drawing, so that portals can work. -Red // Clips vissprites without drawing, so that portals can work. -Red
void R_ClipSprites(void) void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
{ {
vissprite_t *spr; vissprite_t *spr;
for (; clippedvissprites < visspritecount; clippedvissprites++) for (; clippedvissprites < visspritecount; clippedvissprites++)
@ -2211,7 +2211,7 @@ void R_ClipSprites(void)
// and buggy, by going past LEFT end of array: // and buggy, by going past LEFT end of array:
// for (ds = ds_p-1; ds >= drawsegs; ds--) old buggy code // for (ds = ds_p-1; ds >= drawsegs; ds--) old buggy code
for (ds = ds_p; ds-- > drawsegs ;) for (ds = ds_p; ds-- > dsstart;)
{ {
// determine if the drawseg obscures the sprite // determine if the drawseg obscures the sprite
if (ds->x1 > spr->x2 || if (ds->x1 > spr->x2 ||
@ -2223,12 +2223,11 @@ void R_ClipSprites(void)
continue; continue;
} }
if (ds->portalpass != 66)
{
if (ds->portalpass > 0 && ds->portalpass <= portalrender) if (ds->portalpass > 0 && ds->portalpass <= portalrender)
continue; // is a portal continue; // is a portal
r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;
if (ds->scale1 > ds->scale2) if (ds->scale1 > ds->scale2)
{ {
lowscale = ds->scale2; lowscale = ds->scale2;
@ -2250,6 +2249,10 @@ void R_ClipSprites(void)
// seg is behind sprite // seg is behind sprite
continue; continue;
} }
}
r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;
// clip this piece of the sprite // clip this piece of the sprite
silhouette = ds->silhouette; silhouette = ds->silhouette;
@ -2367,6 +2370,17 @@ void R_ClipSprites(void)
//Fab : 26-04-98: was -1, now clips against console bottom //Fab : 26-04-98: was -1, now clips against console bottom
spr->cliptop[x] = (INT16)con_clipviewtop; spr->cliptop[x] = (INT16)con_clipviewtop;
} }
if (portal)
{
for (x = spr->x1; x <= spr->x2; x++)
{
if (spr->clipbot[x] > portal->floorclip[x - portal->start])
spr->clipbot[x] = portal->floorclip[x - portal->start];
if (spr->cliptop[x] < portal->ceilingclip[x - portal->start])
spr->cliptop[x] = portal->ceilingclip[x - portal->start];
}
}
} }
} }
@ -2444,12 +2458,13 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks)
R_CreateDrawNodes(&masks[i], &heads[i], false); R_CreateDrawNodes(&masks[i], &heads[i], false);
} }
for (i = 0; i < nummasks; i++) //for (i = 0; i < nummasks; i++)
CONS_Printf("Mask no.%d:\ndrawsegs: %d\n vissprites: %d\n\n", i, masks[i].drawsegs[1] - masks[i].drawsegs[0], masks[i].vissprites[1] - masks[i].vissprites[0]); // CONS_Printf("Mask no.%d:\ndrawsegs: %d\n vissprites: %d\n\n", i, masks[i].drawsegs[1] - masks[i].drawsegs[0], masks[i].vissprites[1] - masks[i].vissprites[0]);
for (; nummasks > 0; nummasks--) for (; nummasks > 0; nummasks--)
{ {
viewz = masks[nummasks - 1].viewz; viewz = masks[nummasks - 1].viewz;
R_DrawMaskedList(&heads[nummasks - 1]); R_DrawMaskedList(&heads[nummasks - 1]);
R_ClearDrawNodes(&heads[nummasks - 1]); R_ClearDrawNodes(&heads[nummasks - 1]);
} }

View file

@ -16,6 +16,7 @@
#include "sounds.h" #include "sounds.h"
#include "r_plane.h" #include "r_plane.h"
#include "r_portal.h"
// "Left" and "Right" character symbols for additional rotation functionality // "Left" and "Right" character symbols for additional rotation functionality
#define ROT_L ('L' - '0') #define ROT_L ('L' - '0')
@ -54,7 +55,7 @@ void R_AddSpriteDefs(UINT16 wadnum);
void R_AddSprites(sector_t *sec, INT32 lightlevel); void R_AddSprites(sector_t *sec, INT32 lightlevel);
void R_InitSprites(void); void R_InitSprites(void);
void R_ClearSprites(void); void R_ClearSprites(void);
void R_ClipSprites(void); void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
/** Used to count the amount of masked elements /** Used to count the amount of masked elements
* per portal to later group them in separate * per portal to later group them in separate