Move portal drawing to r_portal

This commit is contained in:
Magnus Norddahl 2016-12-30 06:08:47 +01:00
commit 41d0e7c663
10 changed files with 569 additions and 503 deletions

View file

@ -73,7 +73,6 @@
CVAR(Bool, r_linearsky, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
CVAR(Bool, tilt, false, 0);
CVAR(Bool, r_skyboxes, true, 0)
EXTERN_CVAR(Int, r_skymode)
@ -90,16 +89,10 @@ static void R_DrawSkyStriped (visplane_t *pl);
planefunction_t floorfunc;
planefunction_t ceilingfunc;
// Here comes the obnoxious "visplane".
#define MAXVISPLANES 128 /* must be a power of 2 */
// Avoid infinite recursion with stacked sectors by limiting them.
#define MAX_SKYBOX_PLANES 1000
// [RH] Allocate one extra for sky box planes.
static visplane_t *visplanes[MAXVISPLANES+1]; // killough
static visplane_t *freetail; // killough
static visplane_t **freehead = &freetail; // killough
visplane_t *visplanes[MAXVISPLANES+1];
visplane_t *freetail;
visplane_t **freehead = &freetail;
visplane_t *floorplane;
visplane_t *ceilingplane;
@ -1300,241 +1293,6 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
NetUpdate ();
}
//==========================================================================
//
// R_DrawPortals
//
// Draws any recorded sky boxes and then frees them.
//
// The process:
// 1. Move the camera to coincide with the SkyViewpoint.
// 2. Clear out the old planes. (They have already been drawn.)
// 3. Clear a window out of the ClipSegs just large enough for the plane.
// 4. Pretend the existing vissprites and drawsegs aren't there.
// 5. Create a drawseg at 0 distance to clip sprites to the visplane. It
// doesn't need to be associated with a line in the map, since there
// will never be any sprites in front of it.
// 6. Render the BSP, then planes, then masked stuff.
// 7. Restore the previous vissprites and drawsegs.
// 8. Repeat for any other sky boxes.
// 9. Put the camera back where it was to begin with.
//
//==========================================================================
static int numskyboxes;
void R_DrawPortals ()
{
static TArray<size_t> interestingStack;
static TArray<ptrdiff_t> drawsegStack;
static TArray<ptrdiff_t> visspriteStack;
static TArray<DVector3> viewposStack;
static TArray<visplane_t *> visplaneStack;
numskyboxes = 0;
if (visplanes[MAXVISPLANES] == NULL)
return;
R_3D_EnterSkybox();
CurrentPortalInSkybox = true;
int savedextralight = extralight;
DVector3 savedpos = ViewPos;
DAngle savedangle = ViewAngle;
ptrdiff_t savedvissprite_p = vissprite_p - vissprites;
ptrdiff_t savedds_p = ds_p - drawsegs;
size_t savedinteresting = FirstInterestingDrawseg;
double savedvisibility = R_GetVisibility();
AActor *savedcamera = camera;
sector_t *savedsector = viewsector;
int i;
visplane_t *pl;
for (pl = visplanes[MAXVISPLANES]; pl != NULL; pl = visplanes[MAXVISPLANES])
{
// Pop the visplane off the list now so that if this skybox adds more
// skyboxes to the list, they will be drawn instead of skipped (because
// new skyboxes go to the beginning of the list instead of the end).
visplanes[MAXVISPLANES] = pl->next;
pl->next = NULL;
if (pl->right < pl->left || !r_skyboxes || numskyboxes == MAX_SKYBOX_PLANES || pl->portal == NULL)
{
R_DrawSinglePlane (pl, OPAQUE, false, false);
*freehead = pl;
freehead = &pl->next;
continue;
}
numskyboxes++;
FSectorPortal *port = pl->portal;
switch (port->mType)
{
case PORTS_SKYVIEWPOINT:
{
// Don't let gun flashes brighten the sky box
ASkyViewpoint *sky = barrier_cast<ASkyViewpoint*>(port->mSkybox);
extralight = 0;
R_SetVisibility(sky->args[0] * 0.25f);
ViewPos = sky->InterpolatedPosition(r_TicFracF);
ViewAngle = savedangle + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * r_TicFracF);
R_CopyStackedViewParameters();
break;
}
case PORTS_STACKEDSECTORTHING:
case PORTS_PORTAL:
case PORTS_LINKEDPORTAL:
extralight = pl->extralight;
R_SetVisibility (pl->visibility);
ViewPos.X = pl->viewpos.X + port->mDisplacement.X;
ViewPos.Y = pl->viewpos.Y + port->mDisplacement.Y;
ViewPos.Z = pl->viewpos.Z;
ViewAngle = pl->viewangle;
break;
case PORTS_HORIZON:
case PORTS_PLANE:
// not implemented yet
default:
R_DrawSinglePlane(pl, OPAQUE, false, false);
*freehead = pl;
freehead = &pl->next;
numskyboxes--;
continue;
}
port->mFlags |= PORTSF_INSKYBOX;
if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags |= PORTSF_INSKYBOX;
camera = NULL;
viewsector = port->mDestination;
assert(viewsector != NULL);
R_SetViewAngle ();
validcount++; // Make sure we see all sprites
R_ClearPlanes (false);
R_ClearClipSegs (pl->left, pl->right);
WindowLeft = pl->left;
WindowRight = pl->right;
for (i = pl->left; i < pl->right; i++)
{
if (pl->top[i] == 0x7fff)
{
ceilingclip[i] = viewheight;
floorclip[i] = -1;
}
else
{
ceilingclip[i] = pl->top[i];
floorclip[i] = pl->bottom[i];
}
}
// Create a drawseg to clip sprites to the sky plane
drawseg_t *draw_segment = R_AddDrawSegment();
draw_segment->CurrentPortalUniq = CurrentPortalUniq;
draw_segment->siz1 = INT_MAX;
draw_segment->siz2 = INT_MAX;
draw_segment->sz1 = 0;
draw_segment->sz2 = 0;
draw_segment->x1 = pl->left;
draw_segment->x2 = pl->right;
draw_segment->silhouette = SIL_BOTH;
draw_segment->sprbottomclip = R_NewOpening (pl->right - pl->left);
draw_segment->sprtopclip = R_NewOpening (pl->right - pl->left);
draw_segment->maskedtexturecol = ds_p->swall = -1;
draw_segment->bFogBoundary = false;
draw_segment->curline = NULL;
draw_segment->fake = 0;
memcpy (openings + draw_segment->sprbottomclip, floorclip + pl->left, (pl->right - pl->left)*sizeof(short));
memcpy (openings + draw_segment->sprtopclip, ceilingclip + pl->left, (pl->right - pl->left)*sizeof(short));
firstvissprite = vissprite_p;
firstdrawseg = draw_segment;
FirstInterestingDrawseg = InterestingDrawsegs.Size();
interestingStack.Push (FirstInterestingDrawseg);
ptrdiff_t diffnum = firstdrawseg - drawsegs;
drawsegStack.Push (diffnum);
diffnum = firstvissprite - vissprites;
visspriteStack.Push (diffnum);
viewposStack.Push(ViewPos);
visplaneStack.Push (pl);
InSubsector = NULL;
R_RenderBSPNode (nodes + numnodes - 1);
R_3D_ResetClip(); // reset clips (floor/ceiling)
R_DrawPlanes ();
port->mFlags &= ~PORTSF_INSKYBOX;
if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags &= ~PORTSF_INSKYBOX;
}
// Draw all the masked textures in a second pass, in the reverse order they
// were added. This must be done separately from the previous step for the
// sake of nested skyboxes.
while (interestingStack.Pop (FirstInterestingDrawseg))
{
ptrdiff_t pd = 0;
drawsegStack.Pop (pd);
firstdrawseg = drawsegs + pd;
visspriteStack.Pop (pd);
firstvissprite = vissprites + pd;
// Masked textures and planes need the view coordinates restored for proper positioning.
viewposStack.Pop(ViewPos);
R_DrawMasked ();
ds_p = firstdrawseg;
vissprite_p = firstvissprite;
visplaneStack.Pop (pl);
if (pl->Alpha > 0 && pl->picnum != skyflatnum)
{
R_DrawSinglePlane (pl, pl->Alpha, pl->Additive, true);
}
*freehead = pl;
freehead = &pl->next;
}
firstvissprite = vissprites;
vissprite_p = vissprites + savedvissprite_p;
firstdrawseg = drawsegs;
ds_p = drawsegs + savedds_p;
InterestingDrawsegs.Resize ((unsigned int)FirstInterestingDrawseg);
FirstInterestingDrawseg = savedinteresting;
camera = savedcamera;
viewsector = savedsector;
ViewPos = savedpos;
R_SetVisibility(savedvisibility);
extralight = savedextralight;
ViewAngle = savedangle;
R_SetViewAngle ();
CurrentPortalInSkybox = false;
R_3D_LeaveSkybox();
if(fakeActive) return;
for (*freehead = visplanes[MAXVISPLANES], visplanes[MAXVISPLANES] = NULL; *freehead; )
freehead = &(*freehead)->next;
}
ADD_STAT(skyboxes)
{
FString out;
out.Format ("%d skybox planes", numskyboxes);
return out;
}
//==========================================================================
//
// R_DrawSkyPlane