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

@ -44,6 +44,7 @@
#include "scene/r_clip_segment.h"
#include "scene/r_segs.h"
#include "scene/r_3dfloors.h"
#include "scene/r_portal.h"
#include "r_sky.h"
#include "drawers/r_draw_rgba.h"
#include "st_stuff.h"
@ -70,16 +71,8 @@
CVAR (String, r_viewsize, "", CVAR_NOSET)
CVAR (Bool, r_shadercolormaps, true, CVAR_ARCHIVE)
CVAR(Int, r_portal_recursions, 4, CVAR_ARCHIVE)
CVAR(Bool, r_highlight_portals, false, CVAR_ARCHIVE)
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor)
extern cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
extern cycle_t FrameCycles;
extern bool r_showviewer;
namespace swrenderer
{
@ -539,245 +532,6 @@ void R_SetupFreelook()
}
}
//==========================================================================
//
// R_EnterPortal
//
// [RH] Draw the reflection inside a mirror
// [ZZ] Merged with portal code, originally called R_EnterMirror
//
//==========================================================================
void R_HighlightPortal (PortalDrawseg* pds)
{
// [ZZ] NO OVERFLOW CHECKS HERE
// I believe it won't break. if it does, blame me. :(
if (r_swtruecolor) // Assuming this is just a debug function
return;
BYTE color = (BYTE)BestColor((DWORD *)GPalette.BaseColors, 255, 0, 0, 0, 255);
BYTE* pixels = RenderTarget->GetBuffer();
// top edge
for (int x = pds->x1; x < pds->x2; x++)
{
if (x < 0 || x >= RenderTarget->GetWidth())
continue;
int p = x - pds->x1;
int Ytop = pds->ceilingclip[p];
int Ybottom = pds->floorclip[p];
if (x == pds->x1 || x == pds->x2-1)
{
RenderTarget->DrawLine(x, Ytop, x, Ybottom+1, color, 0);
continue;
}
int YtopPrev = pds->ceilingclip[p-1];
int YbottomPrev = pds->floorclip[p-1];
if (abs(Ytop-YtopPrev) > 1)
RenderTarget->DrawLine(x, YtopPrev, x, Ytop, color, 0);
else *(pixels + Ytop * RenderTarget->GetPitch() + x) = color;
if (abs(Ybottom-YbottomPrev) > 1)
RenderTarget->DrawLine(x, YbottomPrev, x, Ybottom, color, 0);
else *(pixels + Ybottom * RenderTarget->GetPitch() + x) = color;
}
}
void R_EnterPortal (PortalDrawseg* pds, int depth)
{
// [ZZ] check depth. fill portal with black if it's exceeding the visual recursion limit, and continue like nothing happened.
if (depth >= r_portal_recursions)
{
BYTE color = (BYTE)BestColor((DWORD *)GPalette.BaseColors, 0, 0, 0, 0, 255);
int spacing = RenderTarget->GetPitch();
for (int x = pds->x1; x < pds->x2; x++)
{
if (x < 0 || x >= RenderTarget->GetWidth())
continue;
int Ytop = pds->ceilingclip[x-pds->x1];
int Ybottom = pds->floorclip[x-pds->x1];
if (r_swtruecolor)
{
uint32_t *dest = (uint32_t*)RenderTarget->GetBuffer() + x + Ytop * spacing;
uint32_t c = GPalette.BaseColors[color].d;
for (int y = Ytop; y <= Ybottom; y++)
{
*dest = c;
dest += spacing;
}
}
else
{
BYTE *dest = RenderTarget->GetBuffer() + x + Ytop * spacing;
for (int y = Ytop; y <= Ybottom; y++)
{
*dest = color;
dest += spacing;
}
}
}
if (r_highlight_portals)
R_HighlightPortal(pds);
return;
}
DAngle startang = ViewAngle;
DVector3 startpos = ViewPos;
DVector3 savedpath[2] = { ViewPath[0], ViewPath[1] };
ActorRenderFlags savedvisibility = camera? camera->renderflags & RF_INVISIBLE : ActorRenderFlags::FromInt(0);
CurrentPortalUniq++;
unsigned int portalsAtStart = WallPortals.Size ();
if (pds->mirror)
{
//vertex_t *v1 = ds->curline->v1;
vertex_t *v1 = pds->src->v1;
// Reflect the current view behind the mirror.
if (pds->src->Delta().X == 0)
{ // vertical mirror
ViewPos.X = v1->fX() - startpos.X + v1->fX();
}
else if (pds->src->Delta().Y == 0)
{ // horizontal mirror
ViewPos.Y = v1->fY() - startpos.Y + v1->fY();
}
else
{ // any mirror
vertex_t *v2 = pds->src->v2;
double dx = v2->fX() - v1->fX();
double dy = v2->fY() - v1->fY();
double x1 = v1->fX();
double y1 = v1->fY();
double x = startpos.X;
double y = startpos.Y;
// the above two cases catch len == 0
double r = ((x - x1)*dx + (y - y1)*dy) / (dx*dx + dy*dy);
ViewPos.X = (x1 + r * dx)*2 - x;
ViewPos.Y = (y1 + r * dy)*2 - y;
}
ViewAngle = pds->src->Delta().Angle() * 2 - startang;
}
else
{
P_TranslatePortalXY(pds->src, ViewPos.X, ViewPos.Y);
P_TranslatePortalZ(pds->src, ViewPos.Z);
P_TranslatePortalAngle(pds->src, ViewAngle);
P_TranslatePortalXY(pds->src, ViewPath[0].X, ViewPath[0].Y);
P_TranslatePortalXY(pds->src, ViewPath[1].X, ViewPath[1].Y);
if (!r_showviewer && camera && P_PointOnLineSidePrecise(ViewPath[0], pds->dst) != P_PointOnLineSidePrecise(ViewPath[1], pds->dst))
{
double distp = (ViewPath[0] - ViewPath[1]).Length();
if (distp > EQUAL_EPSILON)
{
double dist1 = (ViewPos - ViewPath[0]).Length();
double dist2 = (ViewPos - ViewPath[1]).Length();
if (dist1 + dist2 < distp + 1)
{
camera->renderflags |= RF_INVISIBLE;
}
}
}
}
ViewSin = ViewAngle.Sin();
ViewCos = ViewAngle.Cos();
ViewTanSin = FocalTangent * ViewSin;
ViewTanCos = FocalTangent * ViewCos;
R_CopyStackedViewParameters();
validcount++;
PortalDrawseg* prevpds = CurrentPortal;
CurrentPortal = pds;
R_ClearPlanes (false);
R_ClearClipSegs (pds->x1, pds->x2);
WindowLeft = pds->x1;
WindowRight = pds->x2;
// RF_XFLIP should be removed before calling the root function
int prevmf = MirrorFlags;
if (pds->mirror)
{
if (MirrorFlags & RF_XFLIP)
MirrorFlags &= ~RF_XFLIP;
else MirrorFlags |= RF_XFLIP;
}
// some portals have height differences, account for this here
R_3D_EnterSkybox(); // push 3D floor height map
CurrentPortalInSkybox = false; // first portal in a skybox should set this variable to false for proper clipping in skyboxes.
// first pass, set clipping
memcpy (ceilingclip + pds->x1, &pds->ceilingclip[0], pds->len*sizeof(*ceilingclip));
memcpy (floorclip + pds->x1, &pds->floorclip[0], pds->len*sizeof(*floorclip));
InSubsector = NULL;
R_RenderBSPNode (nodes + numnodes - 1);
R_3D_ResetClip(); // reset clips (floor/ceiling)
if (!savedvisibility && camera) camera->renderflags &= ~RF_INVISIBLE;
PlaneCycles.Clock();
R_DrawPlanes ();
R_DrawPortals ();
PlaneCycles.Unclock();
double vzp = ViewPos.Z;
int prevuniq = CurrentPortalUniq;
// depth check is in another place right now
unsigned int portalsAtEnd = WallPortals.Size ();
for (; portalsAtStart < portalsAtEnd; portalsAtStart++)
{
R_EnterPortal (&WallPortals[portalsAtStart], depth + 1);
}
int prevuniq2 = CurrentPortalUniq;
CurrentPortalUniq = prevuniq;
NetUpdate();
MaskedCycles.Clock(); // [ZZ] count sprites in portals/mirrors along with normal ones.
R_DrawMasked (); // this is required since with portals there often will be cases when more than 80% of the view is inside a portal.
MaskedCycles.Unclock();
NetUpdate();
R_3D_LeaveSkybox(); // pop 3D floor height map
CurrentPortalUniq = prevuniq2;
// draw a red line around a portal if it's being highlighted
if (r_highlight_portals)
R_HighlightPortal(pds);
CurrentPortal = prevpds;
MirrorFlags = prevmf;
ViewAngle = startang;
ViewPos = startpos;
ViewPath[0] = savedpath[0];
ViewPath[1] = savedpath[1];
}
//==========================================================================
//
// R_SetupBuffer
@ -889,16 +643,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
R_DrawPortals();
PlaneCycles.Unclock();
// [RH] Walk through mirrors
// [ZZ] Merged with portals
size_t lastportal = WallPortals.Size();
for (unsigned int i = 0; i < lastportal; i++)
{
R_EnterPortal(&WallPortals[i], 0);
}
CurrentPortal = NULL;
CurrentPortalUniq = 0;
R_DrawWallPortals();
NetUpdate ();