Skip to content

Commit

Permalink
Merge branch 'line_distance_cull' into qzdoom
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/swrenderer/scene/r_opaque_pass.cpp
  • Loading branch information
dpjudas committed Jul 12, 2017
2 parents 2590003 + 7d1de66 commit c38d0c1
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Expand Up @@ -691,6 +691,7 @@ set ( SWRENDER_SOURCES
swrenderer/viewport/r_viewport.cpp
swrenderer/viewport/r_walldrawer.cpp
swrenderer/line/r_line.cpp
swrenderer/line/r_farclip_line.cpp
swrenderer/line/r_walldraw.cpp
swrenderer/line/r_wallsetup.cpp
swrenderer/line/r_fogboundary.cpp
Expand Down
190 changes: 190 additions & 0 deletions src/swrenderer/line/r_farclip_line.cpp
@@ -0,0 +1,190 @@
//-----------------------------------------------------------------------------
//
// Copyright 2016 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//-----------------------------------------------------------------------------
//

#include <stdlib.h>
#include <stddef.h>
#include "templates.h"
#include "i_system.h"
#include "doomdef.h"
#include "doomstat.h"
#include "doomdata.h"
#include "p_lnspec.h"
#include "p_setup.h"
#include "r_sky.h"
#include "v_video.h"
#include "m_swap.h"
#include "w_wad.h"
#include "stats.h"
#include "a_sharedglobal.h"
#include "d_net.h"
#include "g_level.h"
#include "g_levellocals.h"
#include "r_wallsetup.h"
#include "v_palette.h"
#include "r_utility.h"
#include "r_data/colormaps.h"
#include "swrenderer/r_memory.h"
#include "swrenderer/scene/r_opaque_pass.h"
#include "swrenderer/scene/r_3dfloors.h"
#include "swrenderer/scene/r_portal.h"
#include "swrenderer/scene/r_light.h"
#include "swrenderer/scene/r_scene.h"
#include "swrenderer/viewport/r_viewport.h"
#include "swrenderer/line/r_farclip_line.h"
#include "swrenderer/line/r_walldraw.h"
#include "swrenderer/line/r_wallsetup.h"
#include "swrenderer/drawers/r_draw.h"
#include "swrenderer/segments/r_clipsegment.h"
#include "swrenderer/segments/r_drawsegment.h"
#include "swrenderer/plane/r_visibleplane.h"
#include "swrenderer/plane/r_visibleplanelist.h"
#include "swrenderer/viewport/r_skydrawer.h"
#include "swrenderer/r_renderthread.h"

namespace swrenderer
{
FarClipLine::FarClipLine(RenderThread *thread)
{
Thread = thread;
}

void FarClipLine::Render(seg_t *line, subsector_t *subsector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane)
{
mSubsector = subsector;
mFrontSector = mSubsector->sector;
mLineSegment = line;
mFloorPlane = linefloorplane;
mCeilingPlane = lineceilingplane;

DVector2 pt1 = line->v1->fPos() - Thread->Viewport->viewpoint.Pos;
DVector2 pt2 = line->v2->fPos() - Thread->Viewport->viewpoint.Pos;

// Reject lines not facing viewer
if (pt1.Y * (pt1.X - pt2.X) + pt1.X * (pt2.Y - pt1.Y) >= 0)
return;

if (WallC.Init(Thread, pt1, pt2, 32.0 / (1 << 12)))
return;

RenderPortal *renderportal = Thread->Portal.get();
if (WallC.sx1 >= renderportal->WindowRight || WallC.sx2 <= renderportal->WindowLeft)
return;

if (line->linedef == nullptr)
return;

// reject lines that aren't seen from the portal (if any)
// [ZZ] 10.01.2016: lines inside a skybox shouldn't be clipped, although this imposes some limitations on portals in skyboxes.
if (!renderportal->CurrentPortalInSkybox && renderportal->CurrentPortal && P_ClipLineToPortal(line->linedef, renderportal->CurrentPortal->dst, Thread->Viewport->viewpoint.Pos))
return;

mFrontCeilingZ1 = mFrontSector->ceilingplane.ZatPoint(line->v1);
mFrontFloorZ1 = mFrontSector->floorplane.ZatPoint(line->v1);
mFrontCeilingZ2 = mFrontSector->ceilingplane.ZatPoint(line->v2);
mFrontFloorZ2 = mFrontSector->floorplane.ZatPoint(line->v2);

mPrepped = false;

Thread->ClipSegments->Clip(WallC.sx1, WallC.sx2, true, this);
}

bool FarClipLine::RenderWallSegment(int x1, int x2)
{
if (!mPrepped)
{
mPrepped = true;

//walltop.Project(Thread->Viewport.get(), mFrontSector->ceilingplane, &WallC, mLineSegment, Thread->Portal->MirrorFlags & RF_XFLIP);
wallbottom.Project(Thread->Viewport.get(), mFrontSector->floorplane, &WallC, mLineSegment, Thread->Portal->MirrorFlags & RF_XFLIP);
memcpy(walltop.ScreenY, wallbottom.ScreenY, sizeof(short) * MAXWIDTH);
}

ClipSegmentTopBottom(x1, x2);
MarkCeilingPlane(x1, x2);
MarkFloorPlane(x1, x2);

return true;
}

void FarClipLine::ClipSegmentTopBottom(int x1, int x2)
{
// clip wall to the floor and ceiling
auto ceilingclip = Thread->OpaquePass->ceilingclip;
auto floorclip = Thread->OpaquePass->floorclip;
for (int x = x1; x < x2; ++x)
{
if (walltop.ScreenY[x] < ceilingclip[x])
{
walltop.ScreenY[x] = ceilingclip[x];
}
if (wallbottom.ScreenY[x] > floorclip[x])
{
wallbottom.ScreenY[x] = floorclip[x];
}
}
}

void FarClipLine::MarkCeilingPlane(int x1, int x2)
{
if (mCeilingPlane)
{
mCeilingPlane = Thread->PlaneList->GetRange(mCeilingPlane, x1, x2);

auto ceilingclip = Thread->OpaquePass->ceilingclip;
auto floorclip = Thread->OpaquePass->floorclip;
Clip3DFloors *clip3d = Thread->Clip3D.get();

for (int x = x1; x < x2; ++x)
{
short top = (clip3d->fakeFloor && clip3d->fake3D & FAKE3D_FAKECEILING) ? clip3d->fakeFloor->ceilingclip[x] : ceilingclip[x];
short bottom = MIN(walltop.ScreenY[x], floorclip[x]);
if (top < bottom)
{
mCeilingPlane->top[x] = top;
mCeilingPlane->bottom[x] = bottom;
}
}
}
}

void FarClipLine::MarkFloorPlane(int x1, int x2)
{
if (mFloorPlane)
{
mFloorPlane = Thread->PlaneList->GetRange(mFloorPlane, x1, x2);

auto ceilingclip = Thread->OpaquePass->ceilingclip;
auto floorclip = Thread->OpaquePass->floorclip;
Clip3DFloors *clip3d = Thread->Clip3D.get();

for (int x = x1; x < x2; ++x)
{
short top = MAX(wallbottom.ScreenY[x], ceilingclip[x]);
short bottom = (clip3d->fakeFloor && clip3d->fake3D & FAKE3D_FAKEFLOOR) ? clip3d->fakeFloor->floorclip[x] : floorclip[x];
if (top < bottom)
{
assert(bottom <= viewheight);
mFloorPlane->top[x] = top;
mFloorPlane->bottom[x] = bottom;
}
}
}
}
}
60 changes: 60 additions & 0 deletions src/swrenderer/line/r_farclip_line.h
@@ -0,0 +1,60 @@
//-----------------------------------------------------------------------------
//
// Copyright 2016 Magnus Norddahl
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//-----------------------------------------------------------------------------
//

#pragma once

#include "r_line.h"

namespace swrenderer
{
class FarClipLine : VisibleSegmentRenderer
{
public:
FarClipLine(RenderThread *thread);
void Render(seg_t *line, subsector_t *subsector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane);

RenderThread *Thread = nullptr;

private:
bool RenderWallSegment(int x1, int x2) override;

void ClipSegmentTopBottom(int x1, int x2);
void MarkCeilingPlane(int x1, int x2);
void MarkFloorPlane(int x1, int x2);

subsector_t *mSubsector;
sector_t *mFrontSector;
seg_t *mLineSegment;
VisiblePlane *mFloorPlane;
VisiblePlane *mCeilingPlane;

double mFrontCeilingZ1;
double mFrontCeilingZ2;
double mFrontFloorZ1;
double mFrontFloorZ2;

FWallCoords WallC;

bool mPrepped;

ProjectedWallLine walltop;
ProjectedWallLine wallbottom;
};
}
1 change: 1 addition & 0 deletions src/swrenderer/r_all.cpp
Expand Up @@ -9,6 +9,7 @@
#include "drawers/r_thread.cpp"
#include "line/r_fogboundary.cpp"
#include "line/r_line.cpp"
#include "line/r_farclip_line.cpp"
#include "line/r_renderdrawsegment.cpp"
#include "line/r_walldraw.cpp"
#include "line/r_wallsetup.cpp"
Expand Down
30 changes: 28 additions & 2 deletions src/swrenderer/scene/r_opaque_pass.cpp
Expand Up @@ -47,6 +47,7 @@
#include "swrenderer/things/r_particle.h"
#include "swrenderer/segments/r_clipsegment.h"
#include "swrenderer/line/r_wallsetup.h"
#include "swrenderer/line/r_farclip_line.h"
#include "swrenderer/scene/r_scene.h"
#include "swrenderer/scene/r_light.h"
#include "swrenderer/viewport/r_viewport.h"
Expand All @@ -72,7 +73,11 @@
EXTERN_CVAR(Bool, r_fullbrightignoresectorcolor);
EXTERN_CVAR(Bool, r_drawvoxels);

namespace { double sprite_distance_cull = 1e16; }
namespace
{
double sprite_distance_cull = 1e16;
double line_distance_cull = 1e16;
}

CUSTOM_CVAR(Float, r_sprite_distance_cull, 5000.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
Expand All @@ -86,6 +91,18 @@ CUSTOM_CVAR(Float, r_sprite_distance_cull, 5000.0, CVAR_ARCHIVE | CVAR_GLOBALCON
}
}

CUSTOM_CVAR(Float, r_line_distance_cull, 8000.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (r_line_distance_cull > 0.0)
{
line_distance_cull = r_line_distance_cull * r_line_distance_cull;
}
else
{
line_distance_cull = 1e16;
}
}

namespace swrenderer
{
RenderOpaquePass::RenderOpaquePass(RenderThread *thread) : renderline(thread)
Expand Down Expand Up @@ -744,10 +761,19 @@ namespace swrenderer
count = sub->numlines;
line = sub->firstline;

DVector2 viewpointPos = Thread->Viewport->viewpoint.Pos.XY();

basecolormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
while (count--)
{
if (!outersubsector || line->sidedef == nullptr || !(line->sidedef->Flags & WALLF_POLYOBJ))
double dist1 = (line->v1->fPos() - viewpointPos).LengthSquared();
double dist2 = (line->v2->fPos() - viewpointPos).LengthSquared();
if (dist1 > line_distance_cull && dist2 > line_distance_cull)
{
FarClipLine farclip(Thread);
farclip.Render(line, InSubsector, floorplane, ceilingplane);
}
else if (!outersubsector || line->sidedef == nullptr || !(line->sidedef->Flags & WALLF_POLYOBJ))
{
// kg3D - fake planes bounding calculation
if (r_3dfloors && line->backsector && frontsector->e && line->backsector->e->XFloor.ffloors.Size())
Expand Down

0 comments on commit c38d0c1

Please sign in to comment.